reset changelog for debian package
[debian/orchestra.git] / src / player / if_pipe.go
1 // if_pipe
2 //
3 // 'pipe' score interface
4 //
5 // The PIPE score interface works much like the ENV interace, but also attaches
6 // a pipe to STDOUT which captures <x>=<y> repsonse values.
7
8 package main
9
10 import (
11         "strings"
12         "bufio"
13         "os"
14         o "orchestra"
15 )
16
17 const (
18         pipeEnvironmentPrefix = "ORC_"
19 )
20
21 func init() {
22         RegisterInterface("pipe", newPipeInterface)
23 }
24
25 type PipeInterface struct {
26         task    *TaskRequest
27         pipew   *os.File
28 }
29
30 func newPipeInterface(task *TaskRequest) (iface ScoreInterface) {
31         ei := new(PipeInterface)
32         ei.task = task
33
34         return ei
35 }
36
37
38 // pipeListener is the goroutine that sits on the stdout pipe and
39 // processes what it sees.
40 func pipeListener(task *TaskRequest, outpipe *os.File) {
41         defer outpipe.Close()
42
43         r := bufio.NewReader(outpipe)
44         for {
45                 lb, _, err := r.ReadLine()
46                 if err == os.EOF {
47                         return
48                 }
49                 if err != nil {
50                         o.Warn("pipeListener failed: %s", err)
51                         return
52                 }
53                 linein := string(lb)
54                 if strings.Index(linein, "=") >= 0 {
55                         bits := strings.SplitN(linein, "=", 2)
56                         task.MyResponse.Response[bits[0]] = bits[1]
57                 }
58         }
59 }
60
61
62 func (ei *PipeInterface) Prepare() bool {
63         lr, lw, err := os.Pipe()
64         if (err != nil) {
65                 return false
66         }
67         // save the writing end of the pipe so we can close our local end of it during cleanup.
68         ei.pipew = lw
69
70         // start the pipe listener
71         go pipeListener(ei.task, lr)
72
73         return true
74 }
75
76 func (ei *PipeInterface) SetupProcess() (ee *ExecutionEnvironment) {
77         ee = NewExecutionEnvironment()
78         for k,v := range ei.task.Params {
79                 ee.Environment[pipeEnvironmentPrefix+k] = v
80         }
81         ee.Files = make([]*os.File, 2)
82         ee.Files[1] = ei.pipew
83         return ee
84 }
85
86 func (ei *PipeInterface) Cleanup() {
87         // close the local copy of the pipe.
88         //
89         // if the child didn't start, this will also EOF the
90         // pipeListener which will clean up that goroutine.
91         ei.pipew.Close()
92 }