Is there any way to avoid "node not found" on a Pbind \off if the node was already freed?

I have a synth \a, and a Pbind that creates other synths after \a, in the same group.
I use Done.freeGroup, so that when \a is freed, the whole group is freed too. At this point, if the Pbind had already scheduled an \n_free message, I get a “FAILURE IN SERVER: Node not found” error.
I would like to avoid it, but still have the Pbind running until \a is freed. I understand that Pbind has to schedule an \n_free when it emits an event, and so it can’t know in advance if the node will be there or not… but do anyone know any way around it?

Here is a small code snippet if it makes it clearer:

g = Group(s);

a = { SinOsc.ar(100) * 0.1 * EnvGen.kr(Env.asr(releaseTime: \fadeTime.kr(3)), \gate.kr(1), doneAction: Done.freeGroup) }.play(g);

b = Pbind(\group, g, \action, \addToTail).play
a.onFree { b.stop };

a.release

The /error server message can enable/disable error messages (see the “Server Command Reference” help file for more details). You can do this for the contents of a single bundle only using a value of -1, so I think you could do something like this in your Pbind:

Pbind(
	\schedBundleArray, #{ | lag, offset, server, bundleArray, latency |
		bundleArray = ["/error", -1] ++ bundleArray;
		schedBundleArrayOnClock(offset, thisThread.clock, bundleArray, lag, server, latency);
	}
)

This is a copy of the default schedBundleArray except it injects the “no error” message at the beginning of the bundle. You could do things like make this optional via e.g. if (~serverErrors.asBoolean.not) { /* ... turn off errors */ }.

3 Likes

Thanks @scztt, this is clearly some of the wisdom you get when you spend some time on Event.sc :blush:

We were just missing some extra [] around ["/error", -1]. I’ll post below what I ended up doing for my use case, with addEventType and a conditional toggle.

But first, I’m sorry I didn’t find this post earlier, which I’m clearly duplicating:

So I also want to thank @jamshark70 for the answer he gave there.

Here is what I ended up doing. Since I only want to hide errors when the Synth is released, I turn on the ~hideErrors toggle only right before calling .release

// new event type because we like encapsulation
Event.addEventType(\noteHideErrors, Event.eventTypes[\note], (
	schedBundleArray: #{ | lag, offset, server, bundleArray, latency |
		if (~hideErrors ? false) {
			bundleArray = [["/error", -1]] ++ bundleArray;
		};
		schedBundleArrayOnClock(offset, thisThread.clock, bundleArray, lag, server, latency);
	}
));

// test code
// create synth on new group
(
a = { SinOsc.ar(100) * 0.1 * EnvGen.kr(
    Env.asr(releaseTime: \fadeTime.kr(3)), \gate.kr(1),
    doneAction: Done.freeGroup
)}.play(Group(s));
)

// Pattern: now with new type for conditional error hiding
(
b = EventPatternProxy(Pbind(
	\type, \noteHideErrors,  \dur, 0.1,
	\group, a.group, \action, \addToTail,
))
)

// setting the env before playing avoid some kind of click later
b.set(\hideErrors, false); b.play

a.onFree { b.stop };

// turn on error hiding right before release
b.set(\hideErrors, true); a.release
2 Likes