summaryrefslogtreecommitdiff
path: root/midi_recorder.ck
blob: 7cba165beef37ca17175608666f1344d9057853f (plain)
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;
	}
}