On 9/19/07, Scott Wheeler <wheeler@kde.org> wrote:
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