aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-03-02 11:41:33 +0000
committers-ol <s-ol@users.noreply.github.com>2020-03-02 11:41:33 +0000
commit03853b35a473161f377fb74a05723cacc5cbf36b (patch)
tree2e3df044cc0ff3ed24a07d6b5ee31682f077e5fa /lib
parentnew op interface part one (diff)
downloadalive-03853b35a473161f377fb74a05723cacc5cbf36b.tar.gz
alive-03853b35a473161f377fb74a05723cacc5cbf36b.zip
IO system
Diffstat (limited to 'lib')
-rw-r--r--lib/debug.moon4
-rw-r--r--lib/midi/core.moon77
-rw-r--r--lib/midi/init.moon39
-rw-r--r--lib/midi/launchctl.moon102
-rw-r--r--lib/time.moon5
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