Thanks a lot for this very interesting discussion, I’m learning lot.
It’s important here to understand the division of labor between the language and the audio server.
I see, it makes sense, I though all this code was run on the server here, I did not realize the OSC message where from the server to the client, I thought it was local to the server. Is there a way to “debug” to see what code/osc messge is running where? For instance, if I use a Condition
in a synth, will it send and OSC messge to the client ?
I’d say the critique is rather exaggerated
Ahah yes, I’m just trying to understand what’s the cleanest solution and the various implications, but this is not that bad sure.
they could execute remote code in SC only if you receive a string over OSC and your code .interpret
-s it
Well this assumes that the server does not contain any security flows, buffer overflow-like attacks can allow arbitrary code execution on innocent looking code… (countless attacks are done this way) but I’m working in cryptography so I’m maybe a bit too paranoid here (like most cryptographers) and I just like to avoid unecessary attack vectors. Actually, if I don’t specify an IP adress in the OSC commands, will it execute messages coming from any IP address or is it only allowing the server by default?
Name conflicts are not hard to manage, and as you correctly found, a one shot OSCFunc avoids them entirely.
I guess I can add in front of all OSC path a fixed string to create a kind of namespace yes, combined with argTemplate
it is indeed quite unlikely to find collision I guess. But I don’t how OSCFunc helps more than OSCDef in this case, both need to specify a hardcoded path.
I think NodeWatcher can be used in some cases:
Thanks, but I tried the same code without the NodeWatcher and I get exactly the same result (but onFree
is indeed interesting in some cases). What is NodeWatcher doing here exactly?
In any case, the point that was missed in the concern over a “race condition” is that SendReply includes two numbers apart from the command path and the values – the node ID from which the message is being sent …
Oh, using nodeID as an identifier is a great idea, much simpler than my imagined workarounds involving random UUID creation. Thanks a lot for these nice examples and tricks! argTemplate
makes the code even cleaner.
While going through the doc, I also found some related functions that may be useful:
SendTrig
is like SendReplay
but directly comes with some pre-chosen paths & messages (based on message ID)
Condition
can sometimes be helpful to pause a thread until another thread does an action (see hang/unhang)
FreeSelf
can be used to free a synth when its input goes above/below a threshold (e.g. when reverb is finished), and it can be combined with waitForFree
to start another action when the sync has finished playing:
// From the documentation of Conditional:
(
SynthDef(\help, { |out|
var mod = LFNoise2.kr(ExpRand(0.5, 2)) * 0.5;
var snd = mod * Blip.ar(Rand(200, 800) * (mod + 1));
Out.ar(out, snd);
FreeSelf.kr(mod < 0); // free the synth when amplitude goes below 0.
}).add;
)
(
fork {
10.do {
"started a synth".postln;
Synth(\help).waitForFree;
"This one ended. Wait a second, I will start the next one.".postln;
1.wait;
};
"This is it.".postln;
}
);