// SendDef sends a synthdef to scsynth. // This method blocks until a /done message is received // indicating that the synthdef was loaded func (self *Client) SendDef(def *Synthdef) error { msg := osc.NewMessage("/d_recv") db, err := def.Bytes() if err != nil { return err } msg.Append(db) self.oscServer.SendTo(self.addr, msg) var done *osc.Message select { case done = <-self.doneChan: goto ParseMessage case err = <-self.oscErrChan: return err } ParseMessage: // error if this message was not an ack of the synthdef errmsg := "expected /done with /d_recv argument" if done.CountArguments() != 1 { return fmt.Errorf(errmsg) } if addr, isString := done.Arguments[0].(string); !isString || addr != "/d_recv" { return fmt.Errorf(errmsg) } return nil }
// Gen generates a buffer using a routine. // A runtime panic will occur if routine is not one of the // BufferRoutine constants. func (self *buffer) Gen(routine string, flags int, args ...float32) error { checkBufferRoutine(routine) checkBufferGenFlags(flags) pat := bufferGenAddress gen := osc.NewMessage(pat) gen.Append(self.Num()) gen.Append(routine) gen.Append(int32(flags)) for _, arg := range args { gen.Append(arg) } err := self.c.oscServer.SendTo(self.c.conn, gen) if err != nil { return err } var done *osc.Message select { case done = <-self.c.doneChan: break case err = <-self.c.oscErrChan: return err } if done.CountArguments() != 2 { return fmt.Errorf("expected two arguments to /done message") } if addr, isString := done.Arguments[0].(string); !isString || addr != pat { return fmt.Errorf("expected first argument to be %s but got %s", pat, addr) } var bufnum int32 var isInt32 bool if bufnum, isInt32 = done.Arguments[1].(int32); !isInt32 { m := "expected int32 as second argument, but got %s (%v)" return fmt.Errorf(m, reflect.TypeOf(done.Arguments[1]), done.Arguments[1]) } // TODO: // Don't error if we get a done message for a different buffer. // We should probably requeue this particular done message on doneChan. if bufnum != self.Num() { m := "expected done message for buffer %d, but got one for buffer %d" return fmt.Errorf(m, self.Num(), bufnum) } return nil }
// Gen generates a buffer using a routine. // A runtime panic will occur if routine is not one of the // BufferRoutine constants. func (self *Buffer) Gen(routine string, flags int, args ...float32) error { if err := checkBufferRoutine(routine); err != nil { return err } if err := checkBufferGenFlags(flags); err != nil { return err } pat := bufferGenAddress gen, err := osc.NewMessage(pat) if err != nil { return err } if err := gen.WriteInt32(self.Num); err != nil { return err } if err := gen.WriteString(routine); err != nil { return err } if err := gen.WriteInt32(int32(flags)); err != nil { return err } for _, arg := range args { if err := gen.WriteFloat32(arg); err != nil { return err } } if err := self.client.oscConn.Send(gen); err != nil { return err } var done *osc.Message select { case done = <-self.client.doneChan: case err = <-self.client.oscErrChan: return err } if done.CountArguments() != 2 { return errors.New("expected two arguments to /done message") } _, err = done.ReadString() if err != nil { return err } bufnum, err := done.ReadInt32() if err != nil { return err } // TODO: // Don't error if we get a done message for a different buffer. // We should probably requeue this particular done message on doneChan. if bufnum != self.Num { m := "expected done message for buffer %d, but got one for buffer %d" return fmt.Errorf(m, self.Num, bufnum) } return nil }
// AllocBuffer allocates a buffer on the server func (self *Client) AllocBuffer(frames, channels int) (Buffer, error) { buf := newBuffer(self) pat := bufferAllocAddress alloc := osc.NewMessage(pat) alloc.Append(buf.Num()) alloc.Append(int32(frames)) alloc.Append(int32(channels)) err := self.oscServer.SendTo(self.conn, alloc) if err != nil { return nil, err } var done *osc.Message select { case done = <-self.doneChan: break case err = <-self.oscErrChan: return nil, err } // error if this message was not an ack of the synthdef if done.CountArguments() != 2 { return nil, fmt.Errorf("expected two arguments to /done message") } if addr, isString := done.Arguments[0].(string); !isString || addr != pat { return nil, fmt.Errorf("expected first argument to be %s but got %s", pat, addr) } var bufnum int32 var isInt32 bool if bufnum, isInt32 = done.Arguments[1].(int32); !isInt32 { m := "expected int32 as second argument, but got %s (%v)" return nil, fmt.Errorf(m, reflect.TypeOf(done.Arguments[1]), done.Arguments[1]) } // TODO: // Don't error if we get a done message for a different buffer. // We should probably requeue this particular done message on doneChan. if bufnum != buf.Num() { m := "expected done message for buffer %d, but got one for buffer %d" return nil, fmt.Errorf(m, buf.Num(), bufnum) } return buf, nil }
func newStatus(msg *osc.Message) (*ServerStatus, error) { if msg.Address != statusReplyAddress { errmsg := "Can not get status from message with address %s" return nil, fmt.Errorf(errmsg, msg.Address) } numArgs := msg.CountArguments() status := new(ServerStatus) if numArgs != 9 || len(msg.Arguments) != 9 { errmsg := "Only got %d arguments in /status.reply message" return nil, fmt.Errorf(errmsg, numArgs) } status.NumUgens = msg.Arguments[1].(int32) status.NumSynths = msg.Arguments[2].(int32) status.NumGroups = msg.Arguments[3].(int32) status.NumSynthdefs = msg.Arguments[4].(int32) status.AvgCpu = msg.Arguments[5].(float32) status.PeakCpu = msg.Arguments[6].(float32) status.NominalSampleRate = msg.Arguments[7].(float64) status.ActualSampleRate = msg.Arguments[8].(float64) return status, nil }
// SendDef sends a synthdef to scsynth. // This method blocks until a /done message is received // indicating that the synthdef was loaded func (self *Client) SendDef(def *Synthdef) error { msg, err := osc.NewMessage(synthdefReceiveAddress) if err != nil { return err } db, err := def.Bytes() if err != nil { return err } if err := msg.WriteBlob(db); err != nil { return err } if err := self.oscConn.Send(msg); err != nil { return err } var done *osc.Message select { case done = <-self.doneChan: goto ParseMessage case err = <-self.oscErrChan: return err } ParseMessage: // error if this message was not an ack of the synthdef errmsg := "expected /done with /d_recv argument" if done.CountArguments() != 1 { return fmt.Errorf(errmsg) } addr, err := done.ReadString() if err != nil { return err } if addr != synthdefReceiveAddress { return errors.New(errmsg) } return nil }
// AllocBuffer allocates a buffer on the server func (self *Client) AllocBuffer(frames, channels int) (*Buffer, error) { buf := newBuffer(self) pat := bufferAllocAddress alloc, err := osc.NewMessage(pat) if err != nil { return nil, err } if err := alloc.WriteInt32(buf.Num); err != nil { return nil, err } if err := alloc.WriteInt32(int32(frames)); err != nil { return nil, err } if err := alloc.WriteInt32(int32(channels)); err != nil { return nil, err } if err := self.oscConn.Send(alloc); err != nil { return nil, err } var done *osc.Message select { case done = <-self.doneChan: break case err = <-self.oscErrChan: return nil, err } // error if this message was not an ack of the synthdef if done.CountArguments() != 2 { return nil, fmt.Errorf("expected two arguments to /done message") } addr, err := done.ReadString() if err != nil { return nil, err } if addr != pat { return nil, fmt.Errorf("expected first argument to be %s but got %s", pat, addr) } bufnum, err := done.ReadInt32() if err != nil { return nil, err } // TODO: // Don't error if we get a done message for a different buffer. // We should probably requeue this particular done message on doneChan. if bufnum != buf.Num { m := "expected done message for buffer %d, but got one for buffer %d" return nil, fmt.Errorf(m, buf.Num, bufnum) } return buf, nil }
// ReadBuffer tells the server to read an audio file and // load it into a buffer func (self *Client) ReadBuffer(path string, num int32) (*Buffer, error) { allocRead, err := osc.NewMessage(bufferReadAddress) if err != nil { return nil, err } buf := newReadBuffer(path, num, self) if err := allocRead.WriteInt32(buf.Num); err != nil { return nil, err } if err := allocRead.WriteString(path); err != nil { return nil, err } if err := self.oscConn.Send(allocRead); err != nil { return nil, err } var done *osc.Message select { case done = <-self.doneChan: case err = <-self.oscErrChan: return nil, err } // error if this message was not an ack of the buffer read if done.CountArguments() != 2 { return nil, fmt.Errorf("expected two arguments to /done message") } addr, err := done.ReadString() if err != nil { return nil, err } if addr != bufferReadAddress { return nil, fmt.Errorf("expected first argument to be %s but got %s", bufferReadAddress, addr) } bufnum, err := done.ReadInt32() if err != nil { return nil, err } // TODO: // Don't error if we get a done message for a different buffer. // We should probably requeue this particular done message on doneChan. if bufnum != buf.Num { m := "expected done message for buffer %d, but got one for buffer %d" return nil, fmt.Errorf(m, buf.Num, bufnum) } return buf, nil }
// parseGroup parses information about a group from a message // received at /g_queryTree // it *does not* recursively query for child groups func parseGroup(msg *osc.Message) (*Group, error) { // return an error if msg.Address is not right if msg.Address != gQueryTreeReply { return nil, fmt.Errorf("msg.Address should be %s, got %s", gQueryTreeReply, msg.Address) } // g_queryTree replies should have at least 3 arguments g, numArgs := new(Group), msg.CountArguments() if numArgs < 3 { return nil, fmt.Errorf("expected 3 arguments for message, got %d", numArgs) } // get the id of the group this reply is for var isint bool g.Node.id, isint = msg.Arguments[1].(int32) if !isint { v := msg.Arguments[1] t := reflect.TypeOf(v) return nil, fmt.Errorf("expected arg 1 to be int32, got %s (%v)", t, v) } // initialize the children array var numChildren int32 numChildren, isint = msg.Arguments[2].(int32) if !isint { v := msg.Arguments[1] t := reflect.TypeOf(v) return nil, fmt.Errorf("expected arg 2 to be int32, got %s (%v)", t, v) } if numChildren < 0 { return nil, fmt.Errorf("expected numChildren >= 0, got %d", numChildren) } g.children = make([]*Node, numChildren) // get the childrens' ids var nodeID, numControls, numSubChildren int32 for i := 3; i < numArgs; { nodeID, isint = msg.Arguments[i].(int32) if !isint { v := msg.Arguments[i] t := reflect.TypeOf(v) return nil, fmt.Errorf("expected arg %d (nodeID) to be int32, got %s (%v)", i, t, v) } g.children[i-3] = &Node{nodeID} // get the number of children of this node // if -1 this is a synth, if >= 0 this is a group numSubChildren, isint = msg.Arguments[i+1].(int32) if !isint { v := msg.Arguments[i] t := reflect.TypeOf(v) return nil, fmt.Errorf("expected arg %d (numControls) to be int32, got %s (%v)", i, t, v) } if numSubChildren == -1 { // synth i += 3 numControls, isint = msg.Arguments[i].(int32) if !isint { v := msg.Arguments[i] t := reflect.TypeOf(v) return nil, fmt.Errorf("expected arg %d (numControls) to be int32, got %s (%v)", i, t, v) } i += 1 + int(numControls*2) } else if numSubChildren >= 0 { // group i += 2 } } return g, nil }
// parseGroup parses information about a group from a message // received at /g_queryTree // it *does not* recursively query for child groups func parseGroup(msg *osc.Message) (*Group, error) { // return an error if msg.Address is not right if msg.Address() != gQueryTreeReply { return nil, fmt.Errorf("msg.Address should be %s, got %s", gQueryTreeReply, msg.Address()) } // g_queryTree replies should have at least 3 arguments g, numArgs := new(Group), msg.CountArguments() if numArgs < 3 { return nil, fmt.Errorf("expected 3 arguments for message, got %d", numArgs) } // get the id of the group this reply is for nodeID, err := msg.ReadInt32() if err != nil { return nil, err } g.Node.id = nodeID // initialize the children array numChildren, err := msg.ReadInt32() if err != nil { return nil, err } if numChildren < 0 { return nil, fmt.Errorf("expected numChildren >= 0, got %d", numChildren) } g.children = make([]*Node, numChildren) // get the childrens' ids var numControls, numSubChildren int32 for i := 3; i < numArgs; { nodeID, err = msg.ReadInt32() if err != nil { return nil, err } g.children[i-3] = &Node{nodeID} // get the number of children of this node // if -1 this is a synth, if >= 0 this is a group numSubChildren, err = msg.ReadInt32() if err != nil { return nil, err } if numSubChildren == -1 { // synth i += 3 numControls, err = msg.ReadInt32() if err != nil { return nil, err } i += 1 + int(numControls*2) } else if numSubChildren >= 0 { // group i += 2 } } return g, nil }