[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-dev] bug in OSCMultiResponder



Hi Sciss,

It's funny, I was just starting to look at the OSC stuff again.
I wonder if it might be better to take a more process oriented approach to all of this 
in the manner of MIDIIn.waitControl, etc. It would certainly be simpler.

Here is a version built on the current OSCresponder, OSCresponderNode stuff.


OSCEvent {
var <>addr, <>cmdName, <>thread, <>time, <>msg, <>respAddr, dispatcher;

*new { arg addr, cmdName;
^super.newCopyArgs(addr, cmdName.asSymbol);


}
add {
var found;
dispatcher = OSCMultiResponder(addr, cmdName);
found = OSCresponder.all.findMatch(dispatcher);
if(found.isNil) { 
dispatcher.nodes = [this]; 
dispatcher.add; 
} {
if (found.class === OSCresponder, {
found.remove;
dispatcher.nodes = [found, this];
dispatcher.add;
},{
dispatcher = found;
found.nodes = found.nodes.add(this)
});
}
}


remove { 
dispatcher.nodes.remove(this);
if(dispatcher.isEmpty, { dispatcher.remove });
dispatcher = nil;
}


value { | argTime, node, argMsg, argAddr |
time = argTime; msg = argMsg; respAddr = argAddr;
if (thread.next(this).isNil) { this.remove};
}


wait { 
thread = thisThread;
if (dispatcher.isNil) { this.add };
this.yield
}


action {} // needed to patch into current OSCresponder set up

}

/*
r = Routine({ var ev;
ev = OSCEvent(nil,'/n_go');
a = ev;
loop { ev.wait; ev.msg.postln; ev.respAddr.postln; }
});
r.reset.next
(server: Server.local).play
OSCresponder.all.do{ | i | i.dump }
r.stop

().play
*/

On Nov 6, 2006, at 9:56 AM, Sciss wrote:

here's the fix for OSCpathResponder: findDispatcher must read:

findDispatcher {
var responder, match, pathIndices;
if( OSCpathDispatcher.cmdPathIndices.includes( cmdName ).not, {
pathIndices = Array.series( path.size, 1 );
});
responder = OSCpathDispatcher(addr, cmdName, nil, pathIndices );
match = OSCresponder.all.findMatch(responder);
if(match.isNil, { ^responder.add });
if (match.class === OSCresponder,  {
match.remove;
responder.nodes_([match]);
^responder.add
});
if (match.class === OSCMultiResponder, {
match.remove;
responder.nodes_(match.nodes);
^responder.add;
});
^match;
}

quick checking:

OSCpathResponder( nil, [ '/test', 1, 2, 4 ], { arg time, resp, msg; ("GOT: " ++msg).postln; }).add
NetAddr.localAddr.sendMsg( '/test' ); // doesn't respond
NetAddr.localAddr.sendMsg( '/test', 1 ); // doesn't respond
NetAddr.localAddr.sendMsg( '/test', 1, 2 ); // doesn't respond
NetAddr.localAddr.sendMsg( '/test', 1, 2, 5 ); // doesn't respond
NetAddr.localAddr.sendMsg( '/test', 1, 3, 4 ); // doesn't respond
NetAddr.localAddr.sendMsg( '/test', 1, 2, 4 ); // ok!

checking against example in OSCpathResponder.help.rtf : ok!


still cryptic stuff...

ciao, -sciss-



Am 06.11.2006 um 15:42 schrieb Sciss:

hallo,

in OSCresponder.sc, can this :

OSCMultiResponder : OSCresponder {
var <>nodes;


value { arg time, msg;
var iterlist;
iterlist = nodes.copy;
iterlist.do({ arg node; node.action.value(time, node, msg) });
}
isEmpty { ^nodes.size == 0 }


}

... be changed into this :

OSCMultiResponder : OSCresponder {
var <>nodes;


value { arg time, msg, addr;
var iterlist;
iterlist = nodes.copy;
iterlist.do({ arg node; node.value(time, msg, addr) });
}
isEmpty { ^nodes.size == 0 }


}


such as to pass the sender's NetAddr so OSCresponderNode s. i think calling node.value is more appropriate than node.action.value since this would allow subclasses to do things slightly different in their own value methods!

likewise, in OSCpathResponder.sc -> OSCpathDispatcher  : old :

value { arg time, msg;
var cmdPath, match, responder;
super.value(time, msg);
if (pathIndices.notNil, {
cmdPath = [cmdName] ++ pathIndices.collect({ arg i; msg.at(i) });
responder = OSCpathResponder(addr, cmdPath);
match = pathResponders.findMatch(responder);
if (match.notNil, {
match.value(time, msg);
});
pathIndices.size.do({ arg i;
responder.path.put(i,nil);
match = pathResponders.findMatch(responder);
if (match.notNil, {
match.value(time, msg);
});
});
});
}

new:

value { arg time, msg, replyAddr;
var cmdPath, match, responder;
super.value(time, msg, replyAddr);
if (pathIndices.notNil, {
cmdPath = [cmdName] ++ pathIndices.collect({ arg i; msg.at(i) });
responder = OSCpathResponder(addr, cmdPath);
match = pathResponders.findMatch(responder);
if (match.notNil, {
match.value(time, msg, replyAddr);
});
pathIndices.size.do({ arg i;
responder.path.put(i,nil);
match = pathResponders.findMatch(responder);
if (match.notNil, {
match.value(time, msg, replyAddr);
});
});
});
}



on a related thing, OSCpathResponder is broken for commands other than found in OSCpathDispatcher.cmdPathIndices . i tried to quickly find a fix, but the whole mechanism is so extremely tricky with methods jumping forth and backwards between super / sub / helper classes that i gave up. this should be probably rewritten in a more clear way.

thx, -sciss-

_______________________________________________
sc-dev mailing list

_______________________________________________
sc-dev mailing list