diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-03-02 11:41:33 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-03-02 11:41:33 +0000 |
| commit | 03853b35a473161f377fb74a05723cacc5cbf36b (patch) | |
| tree | 2e3df044cc0ff3ed24a07d6b5ee31682f077e5fa /lib | |
| parent | new op interface part one (diff) | |
| download | alive-03853b35a473161f377fb74a05723cacc5cbf36b.tar.gz alive-03853b35a473161f377fb74a05723cacc5cbf36b.zip | |
IO system
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/debug.moon | 4 | ||||
| -rw-r--r-- | lib/midi/core.moon | 77 | ||||
| -rw-r--r-- | lib/midi/init.moon | 39 | ||||
| -rw-r--r-- | lib/midi/launchctl.moon | 102 | ||||
| -rw-r--r-- | lib/time.moon | 5 |
5 files changed, 106 insertions, 121 deletions
diff --git a/lib/debug.moon b/lib/debug.moon index 1457cee..e098800 100644 --- a/lib/debug.moon +++ b/lib/debug.moon @@ -1,6 +1,4 @@ -import Op from require 'core' -import ValueInput, EventInput from require 'core.base' -import match from require 'core.pattern' +import Op, ValueInput, EventInput, match from require 'core' class out extends Op @doc: "(out [name-str?] value) - log value to the console" diff --git a/lib/midi/core.moon b/lib/midi/core.moon index 3bf47a9..e0a3334 100644 --- a/lib/midi/core.moon +++ b/lib/midi/core.moon @@ -1,8 +1,6 @@ +import IO, Op, Registry, ValueInput, match from require 'core' import RtMidiIn, RtMidiOut, RtMidi from require 'luartmidi' import band, bor, lshift, rshift from require 'bit32' -import Op, Registry from require 'core' -import ValueInput, EventInput from require 'core.base' -import match from require 'core.pattern' MIDI = { [0x9]: 'note-on' @@ -28,11 +26,9 @@ find_port = (Klass, name) -> \openport id -class MidiPort +class MidiPort extends IO new: (@inp, @out) => - - dirty: => - @updated == Registry.active!.tick + @messages = {} tick: => if @inp @@ -43,76 +39,65 @@ class MidiPort { status, a, b } = bytes chan = band status, 0xf status = MIDI[rshift status, 4] - { :status, :chan, :a, :b } + { :status, :chan, :a, :b, port: @ } - if @messages - @updated = Registry.active!.tick + dirty: => #@messages > 0 receive: => - assert @inp, "#{@} is not an input port" - return unless @messages coroutine.wrap -> for msg in *@messages coroutine.yield msg send: (status, chan, a, b) => - assert @out, "#{@} is not an output port" + assert @out, "#{@} is not an output or bidirectional port" if 'string' == type 'status' status = bor (lshift rMIDI[status], 4), chan @out\sendmessage status, a, b -class input extends Op - @doc: "(midi/input name) - create a MIDI input port" - +class PortOp extends Op new: => super 'midi/port' + destroy: => + Registry.active!\remove_io @port if @port + + tick: (inp, out) => + if (inp and inp\dirty!) or (out and out\dirty!) + Registry.active!\remove_io @port if @port + inp = inp and find_port RtMidiIn, inp! + out = out and find_port RtMidiOut, out! + @port = MidiPort inp, out + Registry.active!\add_io @port + + @out\set @port + +class input extends PortOp + @doc: "(midi/input name) - create a MIDI input port" + setup: (inputs) => { name } = match 'str', inputs - super - name: ValueInput name - root: EventInput Registry.active!.kr - - tick: => - if @inputs.name\dirty! - @out\set MidiPort find_port RtMidiIn, @inputs.name! + super name: ValueInput name - @out\unwrap!\tick! + tick: => super @inputs.name -class output extends Op +class output extends PortOp @doc: "(midi/output name) - create a MIDI output port" - new: => super 'midi/port' - setup: (inputs) => { name } = match 'str', inputs - super - name: ValueInput name - root: EventInput Registry.active!.kr - - tick: => - if @inputs.name\dirty! - @out\set MidiPort nil, find_port RtMidiOut, @inputs.name! + super name: ValueInput name - @out\unwrap!\tick! + tick: => super nil, @inputs.name -class inout extends Op +class inout extends PortOp @doc: "(midi/inout inname outname) - create a bidirectional MIDI port" - new: => super 'midi/port' - setup: (inputs) => - { inp, out } = match 'str, str', inputs + { inp, out } = match 'str str', inputs super inp: ValueInput inp out: ValueInput out - root: EventInput Registry.active!.kr - - tick: => - { :inp, :out } = @inputs - if inp\dirty! or out\dirty! - @out\set MidiPort (find_port RtMidiIn, inp!), (find_port RtMidiOut, out!) - @out\unwrap!\tick! + tick: => super @inputs.inp, @inputs.out apply_range = (range, val) -> if range\type! == 'str' diff --git a/lib/midi/init.moon b/lib/midi/init.moon index 0cbe5e0..3bfba48 100644 --- a/lib/midi/init.moon +++ b/lib/midi/init.moon @@ -1,7 +1,5 @@ -import Value, Op from require 'core' +import Value, Op, ValueInput, IOInput, match from require 'core' import input, output, inout, apply_range from require 'lib.midi.core' -import ValueInput, EventInput from require 'core.base' -import match from require 'core.pattern' class gate extends Op @doc: "(midi/gate port note [chan]) - gate from note-on and note-off messages" @@ -10,9 +8,9 @@ class gate extends Op super 'bool', false setup: (inputs) => - { port, note, chan } = match '=midi/port num num?', inputs + { :port, :note, :chan } = match 'midi/port num num?', inputs super - port: EventInput port.value! + port: IOInput port note: ValueInput note chan: ValueInput chan or Value.num -1 @@ -22,12 +20,13 @@ class gate extends Op if note\dirty! or chan\dirty! @out\set false - for msg in port\receive! - if msg.a == note! and (chan == -1 or msg.chan == chan!) - if msg.status == 'note-on' - @out\set true - elseif msg.status == 'note-off' - @out\set false + if port\dirty! + for msg in port!\receive! + if msg.a == note! and (chan! == -1 or msg.chan == chan!) + if msg.status == 'note-on' + @out\set true + elseif msg.status == 'note-off' + @out\set false class cc extends Op @doc: "(midi/cc port cc [chan [range]]) - MIDI CC to number @@ -42,11 +41,10 @@ range can be one of: new: => super 'num' - setup: (inputs) => - { port, cc, chan, range } = match '=midi/port num num? any?', inputs + { port, cc, chan, range } = match 'midi/port num num? any?', inputs super - port: EventInput port.value! + port: IOInput port cc: ValueInput cc chan: ValueInput chan or Value.num -1 range: ValueInput range or Value.str 'uni' @@ -55,12 +53,13 @@ range can be one of: @out\set apply_range @inputs.range, 0 tick: => - { port, cc, chan, range } = @inputs - for msg in port\receive! - if msg.status == 'control-change' and - (chan == -1 or msg.chan == chan!) and - msg.a == cc! - @out\set apply_range range, msg.b + { :port, :cc, :chan, :range } = @inputs + if port\dirty! + for msg in port!\receive! + if msg.status == 'control-change' and + (chan! == -1 or msg.chan == chan!) and + msg.a == cc! + @out\set apply_range range, msg.b { :input diff --git a/lib/midi/launchctl.moon b/lib/midi/launchctl.moon index aab20bd..b3bf5da 100644 --- a/lib/midi/launchctl.moon +++ b/lib/midi/launchctl.moon @@ -1,4 +1,4 @@ -import Value, Op from require 'core' +import Value, Op, ValueInput, EventInput, IOInput, match from require 'core' import apply_range from require 'lib.midi.core' import bor, lshift from require 'bit32' @@ -22,42 +22,42 @@ range can be one of: super 'num' @steps = {} - setup: (params) => - super params + setup: (inputs) => + { port, i, start, + chan, steps, range } = match 'midi/port num num num num? any?', inputs - @inputs[5] or= Value.num 8 - @inputs[6] or= Value.str 'uni' - assert #@inputs == 6 - assert @inputs[6].type == 'num' or @inputs[6].type == 'str' - @assert_first_types 'midi/port', 'num', 'num', 'num', 'num' - @impulses = { @inputs[1]\unwrap! } + super + port: IOInput port + i: ValueInput i + start: ValueInput start + chan: ValueInput chan + steps: ValueInput steps or Value.num 8 + range: ValueInput range or Value.str 'uni' if not @out\unwrap! - @out\set apply_range @inputs[6], 0 + @out\set apply_range @inputs.range, 0 - tick: (first) => - port = @inputs[1]\unwrap! - _, i, start, chan, steps = unpack @inputs + tick: => + { :port, :i, :start, :chan, :steps, :range } = @inputs - if first or @inputs[5]\dirty! - steps = @inputs[5]! - while steps > #@steps + if steps\dirty! + while steps! > #@steps table.insert @steps, 0 - while steps < #@steps + while steps! < #@steps table.remove @steps - curr_i = i\unwrap! % #@steps - changed = false - - for msg in port\receive! - if msg.status == 'control-change' and msg.chan == chan! - rel_i = msg.a - start! - if rel_i >= 0 and rel_i < #@steps - @steps[rel_i+1] = msg.b - changed = rel_i == curr_i - - if changed or i\dirty! or start\dirty! or chan\dirty! or steps\dirty! - @out\set apply_range @inputs[6], @steps[curr_i+1] + curr_i = i! % #@steps + if port\dirty! + changed = false + for msg in port!\receive! + if msg.status == 'control-change' and msg.chan == chan! + rel_i = msg.a - start! + if rel_i >= 0 and rel_i < #@steps + @steps[rel_i+1] = msg.b + changed = rel_i == curr_i + @out\set apply_range range, @steps[curr_i+1] if changed + else + @out\set apply_range range, @steps[curr_i+1] class gate_seq extends Op @doc: "(launctl/gate-seq port i start chan [steps]) - Gate-Sequencer @@ -69,13 +69,15 @@ steps defaults to 8." super 'bool', false @steps = {} - setup: (params) => - super params + setup: (inputs) => + { port, i, start, chan, steps } = match 'midi/port num num num num?', inputs - @inputs[5] or= Value.num 8 - @inputs[6] or= Value.str 'uni' - @assert_types 'midi/port', 'num', 'num', 'num', 'num', 'str' - @impulses = { @inputs[1]\unwrap! } + super + port: IOInput port + i: ValueInput i + start: ValueInput start + chan: ValueInput chan + steps: ValueInput steps or Value.num 8 light = (set, active) -> set = if set then 'S' else ' ' @@ -85,29 +87,31 @@ steps defaults to 8." when ' A' then 1, 1 when 'S ' then 1, 0 when 'SA' then 3, 1 + display: (i, active) => - port, _, start, chan = @unwrap_inputs! + { :port, :start, :chan } = @unwrap_all! port\send 'note-on', chan, (start + i), light @steps[i+1], active - tick: (first) => - port, curr_i, start, chan, steps = @unwrap_inputs! + tick: => + { :port, :i, :start, :chan, :steps } = @inputs - if first or @inputs[5]\dirty! - while steps > #@steps + if steps\dirty! + while steps! > #@steps table.insert @steps, false - while steps < #@steps + while steps! < #@steps table.remove @steps - curr_i = curr_i % #@steps + curr_i = i! % #@steps - for msg in port\receive! - if msg.status == 'note-on' and msg.chan == chan - rel_i = msg.a - start - if rel_i >= 0 and rel_i < #@steps - @steps[rel_i+1] = not @steps[rel_i+1] - @display rel_i, rel_i == curr_i + if port\dirty! + for msg in port!\receive! + if msg.status == 'note-on' and msg.chan == chan! + rel_i = msg.a - start! + if rel_i >= 0 and rel_i < #@steps + @steps[rel_i+1] = not @steps[rel_i+1] + @display rel_i, rel_i == curr_i - if @inputs[2]\dirty! + if i\dirty! prev_i = (curr_i - 1) % #@steps @display curr_i, true diff --git a/lib/time.moon b/lib/time.moon index 007c4de..31fad58 100644 --- a/lib/time.moon +++ b/lib/time.moon @@ -1,6 +1,5 @@ -import Registry, Value, Result, Op from require 'core' -import ValueInput, EventInput from require 'core.base' -import match from require 'core.pattern' +import Registry, Value, Result, Op, ValueInput, EventInput, match + from require 'core' import monotime from require 'system' class clock extends Op |
