ModalityTeam/Modality-toolkit

Collectives individual action problems

Opened this issue · 1 comments

Hello

After some confusement about collectives in Modality I had a chat with Alberto Decampo (@adcxyz) on the mailing list and we seem to have discovered a bug with collectives.

My goal was to make a desc file for a touch osc app with xy-faders outputting data sort of like /xy [x] [y]. Using trace, I could see the changes on the fader being received and registered by the desc, but registering individual actions for them did not work. Alberto developed a quickfix that solved this and I am posting it here for reference.

You can see the full thread here: sc user list thread

(
    d = (
        idInfo: "osc app",
        name: \sccontroller1,
        netAddrInfo: (
            recvPort: NetAddr.langPort,
            srcPort: 6666,
            ipAddress: nil
        ),
        deviceType: \phoneApp,
        protocol: \osc,
        collectives: (
                sliders: (
                    oscPath: '/xy/xy1',
                    elements: [ [\sl, \x], [\sl,\y]], // the order in this array determines the order how the message is parsed
                    ioType: \in
                )
            ),
        elementsDesc: (
            elements: [
                // Buttons
                (
                    key: 'bt',
                    shared: (
                        type: 'button',
                        ioType: \in,
                        spec: \but
                    ),
                    elements:[
                        (oscPath: '/xy/rec'),
                        (oscPath: '/xy/play'),
                        (oscPath: '/xy/stop'),
                        (oscPath: '/xy/prev'),
                        (oscPath: '/xy/next')
                    ]
                ),
                // XY Sliders
                (
                    key: 'sl',
                    shared: (
                        elementType: 'slider',
                        ioType: \collectiveIn,
                        spec: \unipolar,
                    ),
                    elements:[
                        (key: \x),
                        (key: \y),
                    ]
                ),

            ]
        )
    );

    m.free; m = MKtl.new(\scc1, d);

    // m.device.updateSrcAddr("192.168.43.1", 60310);

    m.trace;

    /* OSCFunc.trace(true); */
)


m.elAt(\sl); // the slider group
m.trace;
m.gui;
n = NetAddr.localAddr;
// tell m to listen to local osc from SC itself:
m.device.updateSrcAddr(n.hostname, n.port);

// this changes a button value
n.sendMsg('/xy/rec', 1);
n.sendMsg('/xy/rec', 0);

// should change the values in sl1, sl2
n.sendMsg('/xy/xy1', 0.5, 0.5);
n.sendMsg('/xy/xy1', 0.2, 0.8);


// give the sl group a debug post action, 
// could also be used to set two values of something
m.elAt(\sl).action = { "sl group action runs".postln };


// give slider x and y separate example actions for testing
m.elAt(\sl, \x).action = { |sl| "sl X action ...".postln };
m.elAt(\sl, \y).action = { |sl| "sl Y action ...".postln };


/// ... as Modality is ATM, sl group, x, y actions do not run!
n.sendMsg('/xy/xy1', 0.5, 0.5);
n.sendMsg('/xy/xy1', 0.2, 0.8);


/// QUICK AND DIRTY FIX - should really be fixed in Modality !

// tell the collectives action to ...
m.collectivesDict[\sliders].action = { |coll|
	// post debug message for now ...
	"collective 'sliders' action runs".postln;
	// trigger the group action once ...
	m.elAt(\sl).action.value(m.elAt(\sl));
	// and trigger the individual element actions
	coll.do { |elem| elem.action.value(elem) };
};

///// now group ction and indiv elem actions run
// when a simulated osc message comes in:
n.sendMsg('/xy/xy1', 0.5, 0.5);
n.sendMsg('/xy/xy1', 0.2, 0.8);

Hi @sensestage @madskjeldgaard @weego ,

After I stumbled over it again yesterday, I now find that the quick and dirty fix here
should really be an optional feature in MKtlElementCollective:
Collectives always get their values set as a group; depending on use case,
which element and group actions should be triggered will differ quite a bit.

So, I propose that users should be able to specify whether setting a collective's value will:

  • not run the individual element actions (for efficiency; this is the current state)
  • run all individual element actions
  • run each individual element's actions if the value has changed (e.g. for efficient buttons)
  • run specific actions and groupActions of element groups that contain elements of the coll / or not

Any other options you consider useful and necessary?
Opinions highly welcome,
adc

Untested first idea how to do it:

MKtlElementCollective { 
    ... 
   init { 
        elemsToRunAction = [];
        elemsToRunGroupAction = [];
   }
   // when new values to the collective come in:
         elemsToRunAction.do { |el| el.action.value(el) };
         elemsToRunGroupAction.do { |el| el.groupAction.value(el) };
    ...
}

x = MKtl(\x);
x.elemsToRunAction; // is an [];
x.elemsToRunGroupAction; // is an [];
// add all indiv elements so their action will run:
x.collAt(\accel).addElementsToRunActionOnSet( x.collAt(\accel).asArray );
// add the element group (NOT the collective) so its action will run too:
x.collAt(\accel).addElementsToRunActionOnSet( x.elAt(\accel) );
// add the element group (NOT the collective) so its groupAction will run once when new values come in:
x.collAt(\accel).addElementsToRunGroupActionOnSet( x.elAt(\accel) );