
On 9/19/07, Scott Wheeler
Extra Credit: One thing that I've noticed in a couple of places is that sometimes sporking doesn't do what I would expect it to. For instance, if I change line 223 to "spork ~ node.item.set(value);" to make it non-blocking the program doesn't work. I don't see why.
I'll share my thoughts on livecoding practice and so on too, later. I just wanted to say now that bug reports benefit from a bit more exposure then this paragraph got in your mail, hence this rather explicitly topic-changing reply. I don't see why that would affect matters either, this is in reference to the "set" command that also broadcasts a event, right? The one thing I could think of would be a name space issue. Normally sporked shreds have their parent's namespace but this wouldn't be the first time things went a little odd when inside of classes and you certainly have no shortage of those here. Also; if it's namespace that should yield a complaint. Strange. :¬) Cheers, Kas. // MIDI Event IDs
int codes[0];
144 => codes["NoteOn"]; 128 => codes["NoteOff"]; 176 => codes["ControlChange"];
class MidiMessage { int id;
fun int[] data() { return [ 0, 0 ]; } }
class NoteMessage extends MidiMessage { int pitch; int velocity;
fun int[] data() { return [ pitch, velocity ]; } }
class NoteOnMessage extends NoteMessage { codes["NoteOn"] => id; 100 => velocity; }
class NoteOffMessage extends NoteMessage { codes["NoteOff"] => id; 0 => velocity; }
class ControlChangeMessage extends MidiMessage { codes["ControlChange"] => id; 8 => int control; 127 => int value;
fun int [] data() { return [ control, value ]; } }
class MidiHandler { // Members
MidiIn input; MidiOut output;
0 => int inputDevice; 0 => int outputDevice;
// Constructor
if(!input.open(inputDevice)) { <<< "Could not open MIDI input device." >>>; me.exit(); }
if(!output.open(outputDevice)) { <<< "Could not open MIDI output device." >>>; me.exit(); }
fun void send(MidiMessage message) { message.data() @=> int data[];
if(data.cap() == 2) { MidiMsg out;
message.id => out.data1; data[0] => out.data2; data[1] => out.data3;
output.send(out); } else { <<< "Invalid data() for MidiMessage." >>>; } }
fun void run() { // Now handle incoming events.
MidiMsg message;
while(true) { input => now;
while(input.recv(message)) { message.data1 => int code;
if(code == codes["NoteOn"]) { spork ~ noteOn(message.data2, message.data3); } else if(code == codes["NoteOff"]) { spork ~ noteOff(message.data2, message.data3); } else if(code == codes["ControlChange"]) { spork ~ controlChange(message.data2, message.data3); } else { <<< "Unhandled MIDI Message: ", message.data1, message.data2, message.data3 >>>; } } } }
fun void noteOn(int pitch, int velocity) { <<< "Note On: ", pitch, velocity >>>; }
fun void noteOff(int pitch, int velocity) { <<< "Note Off: ", pitch, velocity >>>; }
fun void controlChange(int control, int value) { <<< "Control Change: ", control, value >>>; } }
class Control { -1 => int cc;
ControlDispatcher.register(this);
fun void set(int value) { <<< "Control Changed: ", cc, ", ", value >>>; } }
class ControlEvent extends Event { int control; int value; }
class EventControl extends Control { ControlEvent changed;
fun void set(int value) { cc => changed.control; value => changed.value; changed.broadcast(); } }
class ControlNode { ControlNode @ next; Control @ item; }
class ControlList { static ControlNode @ first; static ControlNode @ last;
fun void append(Control control) { if(first == null) { new ControlNode @=> first; first @=> last; control @=> first.item; } else { new ControlNode @=> last.next; last.next @=> last; control @=> last.item; } } }
class ControlDispatcher extends MidiHandler { static ControlList @ controls;
fun void controlChange(int control, int value) { if(controls == null) { return; }
controls.first @=> ControlNode @ node;
while(node != null) { if(node.item.cc == control) { node.item.set(value); } node.next @=> node; } }
fun static void register(Control control) { if(controls == null) { new ControlList @=> controls; }
controls.append(control); } }
ControlDispatcher controller;
// Two demos here: one with subclassing, one with events:
class FooControl extends Control { 1 => cc;
fun void set(int value) { <<< "Foo: ", value >>>; } }
FooControl foo;
// And now with events.
EventControl bar; 2 => bar.cc;
fun void listener() { while(true) { bar.changed => now; <<< "Bar: ", bar.changed.value >>>; } }
spork ~ listener();
// And now let's create some fake hardware controls to test things.
fun void fakeKnob() { ControlChangeMessage message;
1 => message.control;
for(0 => int i; i < 10; i++) { i => message.value; controller.send(message); 10::ms => now; } }
fun void fakeButton() { ControlChangeMessage message;
2 => message.control; 127 => message.value;
controller.send(message); }
spork ~ fakeKnob(); spork ~ fakeButton();
controller.run();
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users