Thanks, very precise as always!
This is what I was looking for, because by reconnecting to the server it’s actually possible to access the nodes, wrap them into Synth objects, and for example, release them gracefully.
Here is some example code, in case anybody is interested:
// first run: set maxLogins, create some synths, crash interpreter
s.options.maxLogins_(2);
s.reboot;
SynthDef(\asrSine){|freq=440,gate=1,amp=0.1|
Out.ar(0,
SinOsc.ar(freq)
*EnvGen.kr(Env.asr,gate,doneAction:2)
*amp
)
}.add;
10.do{Synth(\asrSine,[freq:exprand(20,2000),amp:0.01])};
"killall sclang".unixCmd;
// second run: reboot interpreter, get synths, release them:
s.startAliveThread
(
OSCdef(\releaseTree,{|msg|
var reply = msg.drop(2);
var groups = Order[];
var nodes = Order[];
var parseChildren = {|parent|
var numChildren = reply[1];
if(numChildren == -1){
parent[reply.first] = reply[2];
nodes[reply.first] = reply[2];
reply = reply.drop(3);
}{
var newParent = Order[];
parent[reply[0]] = newParent;
reply = reply.drop(2);
numChildren.do{
parseChildren.(newParent);
};
}
};
while{reply.size>1}{
parseChildren.(groups)
};
nodes.indices.postln.do{|i|Synth.basicNew(nodes[i],s,i).release(10)}
},'/g_queryTree.reply').oneShot;
s.sendMsg('/g_queryTree',0,0);
)
It’s not nice to crash the language and occupy clientIDs like that… especially if after the first time I manage to crash it again and again… but it is nice to know that it’s possible to do something about it, especially in a single client live-coding situation, where I might have scheduled too many events, too fast, on the language, and I’m left with a drone of static synths playing.