diff options
| author | s-ol <s+removethis@s-ol.nu> | 2021-01-30 23:01:51 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2021-01-30 23:10:34 +0000 |
| commit | dbdfb1364c91d4905d3f0c947bf150d25ce0c817 (patch) | |
| tree | c612d986abe729a5c99e4dad08986a8d1d5a7b60 /alv-lib | |
| parent | fix array builtin (diff) | |
| download | alive-dbdfb1364c91d4905d3f0c947bf150d25ce0c817.tar.gz alive-dbdfb1364c91d4905d3f0c947bf150d25ce0c817.zip | |
lib: switch to losc
Diffstat (limited to 'alv-lib')
| -rw-r--r-- | alv-lib/_osc.moon | 33 | ||||
| -rw-r--r-- | alv-lib/osc.moon | 69 | ||||
| -rw-r--r-- | alv-lib/sc.moon | 83 |
3 files changed, 105 insertions, 80 deletions
diff --git a/alv-lib/_osc.moon b/alv-lib/_osc.moon new file mode 100644 index 0000000..43297df --- /dev/null +++ b/alv-lib/_osc.moon @@ -0,0 +1,33 @@ +import new_message from require 'losc' +import opairs from require 'alv.util' +import T, Array, Struct from require 'alv.base' + +add_item = (message, type, val) -> + switch type.__class + when Array + -- message\add '[' + for i=1,type.size + add_item message, type.type, val[i] + -- message\add ']' + when Struct + -- message\add '[' + for key, subtype in opairs type.types + -- message\add '[' + message\add 's', key + add_item message, subtype, val[key] + -- message\add ']' + -- message\add ']' + else + ts = switch type + when T.num then 'f' + when T.str, T.sym then 's' + when T.bool, T.bang + if val then 'T' else 'F' + else + error "unknown primitive type" + message\add ts, val + +{ + :new_message + :add_item +} diff --git a/alv-lib/osc.moon b/alv-lib/osc.moon index e0dddba..cf802b7 100644 --- a/alv-lib/osc.moon +++ b/alv-lib/osc.moon @@ -1,5 +1,5 @@ -import Op, Constant, SigStream, Input, T, sig, evt from require 'alv.base' -import pack from require 'oscpack' +import Op, PureOp, Constant, SigStream, Input, T, sig, evt from require 'alv.base' +import new_message, add_item from require 'alv-lib._osc' import dns, udp from require 'socket' unpack or= table.unpack @@ -29,56 +29,41 @@ connect = Constant.meta send = Constant.meta meta: name: 'send' - summary: "Send events via OSC." - examples: { '(osc/send [socket] path evt)' } - description: "Sends an OSC message with `evt` as an argument. + summary: "Send an OSC message." + examples: { '(osc/send [socket] path val…)' } + description: "Sends an OSC message to `path` with `val…` as arguments. - `socket` should be a `udp/socket` value. This argument can be omitted and the value be passed as a dynamic definition in `*sock*` instead. - `path` is the OSC path to send the message to. It should be a string-value. -- `evt` is the argument to send. It should be an event stream." - value: class extends Op - pattern = -sig['udp/socket'] + sig.str + evt! - setup: (inputs, scope) => - { socket, path, value } = pattern\match inputs - super - socket: Input.cold socket or scope\get '*sock*' - path: Input.cold path - value: Input.hot value +- the arguments can be any type: + - `num` will be sent as `f` + - `str` will be sent as `s` + - `bool` will be sent as `T`/`F` + - `bang` will be sent as `T` + - arrays will be unwrapped + - structs will be sent as a series of key/value tuples - tick: => - { :socket, :path, :value } = @unwrap_all! - if value - msg = pack path, if 'table' == type value then unpack value else value - socket\send msg +This is a pure op, so between the values at most one !-stream input is allowed." -sync = Constant.meta - meta: - name: 'sync' - summary: "Synchronize a value via OSC." - examples: { '(osc/sync [socket] path val)' } - description: "sends a message whenever any parameter is dirty." - description: "Sends an OSC message with `val` as an argument whenever any -of the arguments change. + value: class extends PureOp + pattern: (evt! / sig!)^0 -- `socket` should be a `udp/socket` value. This argument can be omitted and the - value be passed as a dynamic definition in `*sock*` instead. -- `path` is the OSC path to send the message to. It should be a string-value. -- `val` is the value to Synchronize. It should be a value stream." - - value: class extends Op - pattern = -sig['udp/socket'] + sig.str + sig! + full_pattern = -sig['udp/socket'] + sig.str + (evt! / sig!)^0 setup: (inputs, scope) => - { socket, path, value } = pattern\match inputs - super - socket: Input.hot socket or scope\get '*sock*' - path: Input.hot path - value: Input.hot value + { socket, path, values } = full_pattern\match inputs + super values, scope, { + socket: Input.cold socket or scope\get '*sock*' + path: Input.cold path + } tick: => - { :socket, :path, :value } = @unwrap_all! - msg = pack path, if 'table' == type value then unpack value else value - socket\send msg + args = @unwrap_all! + { :socket, :path } = args + msg = new_message path + for i=1,#args + add_item msg, @inputs[i]\type!, args[i] + socket\send msg.pack msg.content Constant.meta meta: diff --git a/alv-lib/sc.moon b/alv-lib/sc.moon index fbc4588..16d8fa0 100644 --- a/alv-lib/sc.moon +++ b/alv-lib/sc.moon @@ -1,81 +1,88 @@ -import Op, Constant, Input, sig, evt from require 'alv.base' -import pack from require 'oscpack' -import dns, udp from require 'socket' +import Op, Constant, Input, Array, Struct, T, sig, evt from require 'alv.base' +import new_message, add_item from require 'alv-lib._osc' unpack or= table.unpack -play = Constant.meta +validate_ctrls = (type) -> + switch type.__class + when Array + assert (type.type == T.num) or (type.type == T.str), + "synthdef control values have to be either num or str" + when Struct + for k, t in pairs type.types + assert (t == T.num) or (t == T.str), + "synthdef control value '#{k}' has to be either num or str" + +play_ = Constant.meta meta: - name: 'play' + name: 'play!' summary: 'Play a SuperCollider SynthDef on bangs.' - examples: { '(play [socket] synth trig [param val…])' } + examples: { '(play [socket] synth trig ctrls)' } description: " Plays the synth `synth` on the `udp/socket` `socket` whenever `trig` is live. - `socket` should be a `udp/socket` value. This argument can be omitted and the value be passed as a dynamic definition in `*sock*` instead. - `synth` is the SC synthdef name. It should be a string-value. -- `trig` is the trigger signal. It should be a stream of bang-events. -- `param` is the name of a synthdef parameter. It should be a string-value." +- `trig` is the trigger signal. It should be a !-stream of bang-events. +- `ctrls` is a struct of synthdef controls. It should be a ~-stream." value: class extends Op - pattern = -sig['udp/socket'] + sig.str + evt.bang + (sig.str + sig.num)\rep 0 + pattern = -sig['udp/socket'] + sig.str + evt.bang + sig! setup: (inputs, scope) => { socket, synth, trig, ctrls } = pattern\match inputs - flat_ctrls = {} - for { key, value } in *ctrls - table.insert flat_ctrls, key - table.insert flat_ctrls, value + validate_ctrls ctrls\type! super trig: Input.hot trig socket: Input.cold socket or scope\get '*sock*' synth: Input.cold synth - ctrls: [Input.cold v for v in *flat_ctrls] + ctrls: Input.cold ctrls tick: => - if @inputs.trig\dirty! and @inputs.trig! - { :socket, :synth, :ctrls } = @unwrap_all! - msg = pack '/s_new', synth, -1, 0, 1, unpack ctrls - socket\send msg + { :socket, :synth, :ctrls } = @unwrap_all! + msg = new_message '/s_new' + msg\add 's', synth + msg\add 'i', -1 + msg\add 'i', 0 + msg\add 'i', 1 + add_item msg, @inputs.ctrls\type!, ctrls + socket\send msg.pack msg.content -play_ = Constant.meta + +play = Constant.meta meta: - name: 'play!' + name: 'play' summary: 'Play a SuperCollider SynthDef on events.' - examples: { '(play [socket] synth [param evt/val…])' } + examples: { '(play [socket] synth ctrls)' } description: " -Plays the synth `synth` on the `udp/socket` `socket` whenever any `evt` is live. +Plays the synth `synth` on the `udp/socket` `socket` whenever an event arrives. - `socket` should be a `udp/socket` value. This argument can be omitted and the value be passed as a dynamic definition in `*sock*` instead. - `synth` is the SC synthdef name. It should be a string-value. -- `param` is the name of a synthdef parameter. It should be a string-value. -- `val` and `evt` are the parameter values to send. They should be number - streams. Incoming events will cause a note to be played, while value changes - will not." +- `ctrls` is a struct of synthdef controls. It should be a !-stream." value: class extends Op - pattern = -sig['udp/socket'] + sig.str + (sig.str + (sig.num / evt.num))\rep 0 + pattern = -sig['udp/socket'] + sig.str + evt! setup: (inputs, scope) => - { socket, synth, trig, ctrls } = pattern\match inputs + { socket, synth, ctrls } = pattern\match inputs - flat = {} - for { key, value } in *ctrls - table.insert flat, Input.cold key - table.insert flat, if value\metatype! == 'event' - Input.hot value - else - Input.cold value + validate_ctrls ctrls\type! super socket: Input.cold socket or scope\get '*sock*' synth: Input.cold synth - ctrls: flat + ctrls: Input.hot ctrls tick: => { :socket, :synth, :ctrls } = @unwrap_all! - msg = pack '/s_new', synth, -1, 0, 1, unpack ctrls - socket\send msg + msg = new_message '/s_new' + msg\add 's', synth + msg\add 'i', -1 + msg\add 'i', 0 + msg\add 'i', 1 + add_item msg, @inputs.ctrls\type!, ctrls + socket\send msg.pack msg.content Constant.meta meta: |
