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