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