aboutsummaryrefslogtreecommitdiffstats
path: root/lib/midi/launchctl.moon
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-03-25 10:43:29 +0000
committers-ol <s-ol@users.noreply.github.com>2020-03-25 11:25:05 +0000
commit7cb862f6f6079509dafd466fff83c719cb2fd89e (patch)
tree843f92c4d4b2507e88a525b7c56c29d343958e5b /lib/midi/launchctl.moon
parentValue -> Value/Event/IO-Stream (diff)
downloadalive-7cb862f6f6079509dafd466fff83c719cb2fd89e.tar.gz
alive-7cb862f6f6079509dafd466fff83c719cb2fd89e.zip
new core.base.match, update lib
Diffstat (limited to 'lib/midi/launchctl.moon')
-rw-r--r--lib/midi/launchctl.moon133
1 files changed, 98 insertions, 35 deletions
diff --git a/lib/midi/launchctl.moon b/lib/midi/launchctl.moon
index 37ccb82..1e33cc4 100644
--- a/lib/midi/launchctl.moon
+++ b/lib/midi/launchctl.moon
@@ -1,15 +1,15 @@
-import Value, Op, Input, match from require 'core.base'
+import ValueStream, EventStream, Op, Input, val, evt from require 'core.base'
import apply_range, bit from require 'lib.midi.core'
import bor, lshift from bit
unpack or= table.unpack
color = (r, g) -> bit.bor 12, r, (bit.lshift g, 4)
-cc_seq = Value.meta
+cc_seq = ValueStream.meta
meta:
name: 'cc-seq'
summary: "MIDI CC-Sequencer."
- examples: { '(launchctl/cc-seq port i start chan [steps [range]])' }
+ examples: { '(launchctl/cc-seq [port] i start chan [steps [range]])' }
description: "
returns the value for the i-th step steps (buttons starting from start).
steps defaults to 8.
@@ -23,22 +23,21 @@ range can be one of:
- (num) [ 0 - num["
value: class extends Op
- new: => super 'num'
-
- setup: (inputs) =>
- { port, i, start,
- chan, steps, range } = match 'midi/port num num num num? any?', inputs
+ num = val.num
+ pattern = -evt['midi/port'] + num + num + num + -num + -(val.str + num)
+ setup: (inputs, scope) =>
+ { port, i, start, chan, steps, range } = pattern\match inputs
super
- port: Input.io port
- i: Input.value i
- start: Input.value start
- chan: Input.value chan
- steps: Input.value steps or Value.num 8
- range: Input.value range or Value.str 'uni'
+ port: Input.hot port or scope\get '*ctrl*'
+ i: Input.hot i
+ start: Input.hot start
+ chan: Input.hot chan
+ steps: Input.hot steps or ValueStream.num 8
+ range: Input.hot range or ValueStream.str 'uni'
- if not @out\unwrap!
- @out\set apply_range @inputs.range, 0
+ @state or= {}
+ @out or= ValueStream 'num', apply_range @inputs.range, 0
tick: =>
{ :port, :i, :start, :chan, :steps, :range } = @inputs
@@ -52,7 +51,7 @@ range can be one of:
curr_i = i! % #@state
if port\dirty!
changed = false
- for msg in port!\receive!
+ for msg in *port!
if msg.status == 'control-change' and msg.chan == chan!
rel_i = msg.a - start!
if rel_i >= 0 and rel_i < #@state
@@ -62,29 +61,28 @@ range can be one of:
else
@out\set apply_range range, @state[curr_i+1]
-gate_seq = Value.meta
+gate_seq = ValueStream.meta
meta:
name: 'gate-seq'
summary: "MIDI Gate-Sequencer."
- examples: { '(launchctl/gate-seq port i start chan [steps])' }
+ examples: { '(launchctl/gate-seq [port] i start chan [steps])' }
description: "
-returns `true` or `false` for the `i`-th note-button (MIDI-notes starting from
+Send `true` or `false` for the `i`-th note-button (MIDI-notes starting from
`start`). `steps` defaults to 8."
value: class extends Op
- new: =>
- super 'bool', false
- @state = {}
-
- setup: (inputs) =>
- { port, i, start, chan, steps } = match 'midi/port num num num num?', inputs
+ pattern = -evt['midi/port'] + val.num + val.num + val.num + -val.num
+ setup: (inputs, scope) =>
+ @out or= ValueStream 'bool'
+ @state or= {}
+ { port, i, start, chan, steps } = pattern\match inputs
super
- port: Input.io port
- i: Input.value i
- start: Input.value start
- chan: Input.value chan
- steps: Input.value steps or Value.num 8
+ port: Input.hot port or scope\get '*ctrl*'
+ i: Input.hot i
+ start: Input.hot start
+ chan: Input.hot chan
+ steps: Input.hot steps or ValueStream.num 8
light = (set, active) ->
set = if set then 'S' else ' '
@@ -96,8 +94,8 @@ returns `true` or `false` for the `i`-th note-button (MIDI-notes starting from
when 'SA' then 3, 1
display: (i, active) =>
- { :port, :start, :chan } = @unwrap_all!
- port\send 'note-on', chan, (start + i), light @state[i+1], active
+ start, chan = @inputs.start!, @inputs.chan!
+ @inputs.port.stream\send 'note-on', chan, (start + i), light @state[i+1], active
tick: =>
{ :port, :i, :start, :chan, :steps } = @inputs
@@ -111,7 +109,7 @@ returns `true` or `false` for the `i`-th note-button (MIDI-notes starting from
curr_i = i! % #@state
if port\dirty!
- for msg in port!\receive!
+ for msg in *port!
if msg.status == 'note-on' and msg.chan == chan!
rel_i = msg.a - start!
if rel_i >= 0 and rel_i < #@state
@@ -126,7 +124,72 @@ returns `true` or `false` for the `i`-th note-button (MIDI-notes starting from
@out\set @state[curr_i+1]
+trig_seq = ValueStream.meta
+ meta:
+ name: 'trig-seq'
+ summary: "MIDI Trigger-Sequencer."
+ examples: { '(launchctl/trig-seq [port] i start chan [steps])' }
+ description: "
+Send bangs for the `i`-th note-button (MIDI-notes starting from `start`).
+`steps` defaults to 8."
+
+ value: class extends Op
+ pattern = -evt['midi/port'] + val.num + val.num + val.num + -val.num
+ setup: (inputs, scope) =>
+ @out or= EventStream 'bang'
+ @state or= {}
+ { port, i, start, chan, steps } = pattern\match inputs
+
+ super
+ port: Input.hot port or scope\get '*ctrl*'
+ i: Input.hot i
+ start: Input.hot start
+ chan: Input.hot chan
+ steps: Input.hot steps or ValueStream.num 8
+
+ light = (set, active) ->
+ set = if set then 'S' else ' '
+ active = if active then 'A' else ' '
+ color switch set .. active
+ when ' ' then 0, 0
+ when ' A' then 1, 1
+ when 'S ' then 1, 0
+ when 'SA' then 3, 1
+
+ display: (i, active) =>
+ start, chan = @inputs.start!, @inputs.chan!
+ @inputs.port.stream\send 'note-on', chan, (start + i), light @state[i+1], active
+
+ tick: =>
+ { :port, :i, :start, :chan, :steps } = @inputs
+
+ if steps\dirty!
+ while steps! > #@state
+ table.insert @state, false
+ while steps! < #@state
+ table.remove @state
+
+ curr_i = i! % #@state
+
+ if port\dirty!
+ for msg in *port!
+ if msg.status == 'note-on' and msg.chan == chan!
+ rel_i = msg.a - start!
+ if rel_i >= 0 and rel_i < #@state
+ @state[rel_i+1] = not @state[rel_i+1]
+ @display rel_i, rel_i == curr_i
+
+ if i\dirty!
+ prev_i = (curr_i - 1) % #@state
+
+ @display curr_i, true
+ @display prev_i, false
+
+ if @state[curr_i+1]
+ @out\add true
+
{
- 'gate-seq': gate_seq
'cc-seq': cc_seq
+ 'gate-seq': gate_seq
+ 'trig-seq': trig_seq
}