aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-01-30 23:01:51 +0000
committers-ol <s+removethis@s-ol.nu>2021-01-30 23:10:34 +0000
commitdbdfb1364c91d4905d3f0c947bf150d25ce0c817 (patch)
treec612d986abe729a5c99e4dad08986a8d1d5a7b60
parentfix array builtin (diff)
downloadalive-dbdfb1364c91d4905d3f0c947bf150d25ce0c817.tar.gz
alive-dbdfb1364c91d4905d3f0c947bf150d25ce0c817.zip
lib: switch to losc
-rw-r--r--README.md4
-rw-r--r--alv-lib/_osc.moon33
-rw-r--r--alv-lib/osc.moon69
-rw-r--r--alv-lib/sc.moon83
-rw-r--r--dist/release.bat1
-rwxr-xr-xdist/release.sh1
-rw-r--r--docs/gen/shim.moon2
-rw-r--r--shell.nix24
8 files changed, 130 insertions, 87 deletions
diff --git a/README.md b/README.md
index cd955ad..7e35733 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ processes. For more information, visit the full [online documentation][docs].
- [LPeg][lpeg]*: `luarocks install lpeg`
- [socket][socket]: `luarocks install luasocket`
- [system][system]: `luarocks install luasystem`
-- [oscpack][oscpack]: `luarocks install oscpack` (optional)
+- [losc][losc]: `luarocks install losc` (optional)
- [lua-rtmidi][rtmidi]: `luarocks install
https://raw.githubusercontent.com/s-ol/lua-rtmidi/master/lua-rtmidi-dev-1.rockspec` (optional)
- [busted][busted]: `luarocks install busted` (optional, for tests)
@@ -54,7 +54,7 @@ development, simply pass the files as arguments:
[moonscript]: https://moonscript.org/
[lfs]: https://keplerproject.github.io/luafilesystem/
[lpeg]: http://www.inf.puc-rio.br/~roberto/lpeg/
-[oscpack]: https://github.com/s-ol/lua-oscpack
+[losc]: https://github.com/davidgranstrom/losc
[system]: https://github.com/o-lim/luasystem
[socket]: http://w3.impa.br/~diego/software/luasocket/
[rtmidi]: https://github.com/s-ol/lua-rtmidi/
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:
diff --git a/dist/release.bat b/dist/release.bat
index 7224e7a..b8fe7e1 100644
--- a/dist/release.bat
+++ b/dist/release.bat
@@ -19,7 +19,6 @@ xcopy /E /I dist\win\wrappers\* dist\%BUNDLE%\
cd dist\%BUNDLE%\lua
call luarocks install busted
-call luarocks install %DEPS%\osc-1.0.1-1.rockspec
call luarocks install luarocks-fetch-gitrec
call luarocks install luarocks-build-cpp
call luarocks install %DEPS%\fltk4lua-0.1-1.rockspec FLTK_LIBDIR=%DEPS%\fltk-1.3.5\lib FLTK_INCDIR=%DEPS%\fltk-1.3.5
diff --git a/dist/release.sh b/dist/release.sh
index a9b817a..811ddb2 100755
--- a/dist/release.sh
+++ b/dist/release.sh
@@ -91,6 +91,7 @@ dependencies = {
"luafilesystem",
"luasystem",
"luasocket",
+ "losc",
}
build = {
diff --git a/docs/gen/shim.moon b/docs/gen/shim.moon
index 2a69f52..46da0ac 100644
--- a/docs/gen/shim.moon
+++ b/docs/gen/shim.moon
@@ -4,7 +4,7 @@ export require
require = do
old_require = require
- blacklist = {k, true for k in *{'oscpack', 'socket', 'system', 'luartmidi'}}
+ blacklist = {k, true for k in *{'losc', 'socket', 'system', 'luartmidi'}}
(mod, ...) ->
return {} if blacklist[mod]
old_require mod, ...
diff --git a/shell.nix b/shell.nix
index 71a8f46..90eff5f 100644
--- a/shell.nix
+++ b/shell.nix
@@ -35,7 +35,7 @@ let
url = "mirror://luarocks//${pname}-${version}.src.rock";
sha256 = "Dp3bKIG4swrD4+1NNtRTgyj68Di2cSUlh1r7Z2Rkzn0=";
};
- propagatedBuildInputs = [ pkgs.lua5_3 pkgs.git ];
+ propagatedBuildInputs = with pkgs; [ lua5_3 git ];
meta = with pkgs.stdenv.lib; {
homepage = "https://github.com/siffiejoe/lua-fltk4lua/";
@@ -52,7 +52,7 @@ let
url = "mirror://luarocks//${pname}-${version}.src.rock";
sha256 = "fD31FruqVriMecFcvSV4W7JRia38+bg7j3T5k5pFZec=";
};
- buildInputs = with pkgs; [ pkgs.fltk libjpeg ];
+ buildInputs = with pkgs; [ fltk libjpeg ];
propagatedBuildInputs = [ pkgs.lua5_3 luarocks-build-cpp luarocks-fetch-gitrec ];
meta = with pkgs.stdenv.lib; {
@@ -62,6 +62,24 @@ let
};
};
+ losc = pkgs.lua53Packages.buildLuarocksPackage rec {
+ pname = "losc";
+ version = "1.0.0-1";
+
+ src = pkgs.fetchurl {
+ url = "mirror://luarocks//${pname}-${version}.src.rock";
+ sha256 = "MArhj51V1awF5k2zToFYEXpS2c6o8bnNDn4wLhooHos=";
+ };
+ buildInputs = with pkgs; [ stdenv.cc.cc.lib ];
+ propagatedBuildInputs = [ pkgs.lua5_3 ];
+
+ meta = with pkgs.stdenv.lib; {
+ homepage = "https://github.com/davidgranstrom/losc";
+ description = "Open Sound Control (OSC) for lua/luajit with no external dependencies.";
+ license.fullName = "MIT";
+ };
+ };
+
discount = pkgs.lua53Packages.buildLuarocksPackage {
pname = "discount";
version = "0.4-1";
@@ -117,7 +135,7 @@ in pkgs.mkShell {
buildInputs = with pkgs; [
(lua5_3.withPackages (p: with p; [
moonscript lpeg
- luafilesystem luasocket luasystem fltk4lua bit32
+ luafilesystem luasocket luasystem fltk4lua losc bit32
ldoc busted discount
]))
];