1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
class RecEvent {
dur pit;
MidiMsg @msg;
fun static RecEvent @
new(dur pit, MidiMsg @msg)
{
RecEvent obj;
pit => obj.pit;
msg @=> obj.msg;
return obj;
}
}
List buffer;
MidiOut mout;
MidiIn min;
/* always open MIDI Through port, actual connection is done by Jack */
if (!min.open(0))
me.exit();
if (!mout.open(0))
me.exit();
<<< "MIDI device:", min.num(), " -> ", min.name() >>>;
false => int looping;
fun void
do_recording()
{
buffer.flush();
now => time start;
while (min => now) {
while (MidiMsg msg => min.recv) {
<<< "REC Channel:", recev.msg.data1 & 0x0F,
"Command:", recev.msg.data1 & 0xF0,
"Controller:", recev.msg.data2,
"Value:", (recev.msg.data3 $ float)/127 >>>;
RecEvent.new(now - start, msg) => buffer.put;
now => start;
}
}
}
Shred @recording_shred;
fun void
do_playback(int looping)
{
if (buffer.getHead() == null)
return;
while (true) {
for (buffer.head.next @=> Element @cur; cur != null; cur.next @=> cur) {
cur.payload $ RecEvent @=> RecEvent @recev;
recev.pit => now;
recev.msg => mout.send;
<<< "PLAY Channel:", recev.msg.data1 & 0x0F,
"Command:", recev.msg.data1 & 0xF0,
"Controller:", recev.msg.data2,
"Value:", (recev.msg.data3 $ float)/127 >>>;
}
if (!looping)
break;
}
}
Shred @playback_shred;
/*
* Recorder configuration via MIDI
*/
"secondary" => NanoEvent.init @=> NanoEvent @nanoev;
while (nanoev => now) {
if ("recordToggle" => nanoev.isControl) {
if (nanoev.getBool()) {
if (recording_shred != null)
recording_shred.exit();
spork ~ do_recording() @=> recording_shred;
} else if (recording_shred != null) {
recording_shred.exit();
null @=> recording_shred;
/* remove recordToggle event from buffer queue */
buffer.pop();
}
} else if ("playButton" => nanoev.isControl) {
if (nanoev.getBool()) {
if (playback_shred != null)
playback_shred.exit();
spork ~ do_playback(looping) @=> playback_shred;
}
} else if ("stopButton" => nanoev.isControl) {
if (nanoev.getBool() && playback_shred != null) {
playback_shred.exit();
null @=> playback_shred;
}
} else if ("loopToggle" => nanoev.isControl) {
nanoev.getBool() => looping;
}
}
|