Stopping an event with infinite duration

Here’s a wrapper-way to do almost this (i.e. group-based solution) for an existing Pbind without changing its source code… “Almost” because it kills the group rather than gate it out, I think:

(~gwrap = { |pat| Pproto(
    { ~newgroup = (type: \group).yield; },
    Pset(\group, Pkey(\newgroup), pat))})

p = ~gwrap.(Pbind(\dur, inf)).trace.play
p.stop // stops it!

This simplified version works too:

~gwrap2 = { |pat| Pproto({ ~group = (type: \group).yield; }, pat);  }
p = ~gwrap2.(Pbind(\dur, inf)).trace.play
p.stop // works too

It’s because the Pproto’s prototyped stuff gets passed to the event, but unlike the longer version it won’t override \group if there’s already one in pat. (I’m not sure in general if this is preferable or not.)

I can confirm that group is indeed killed, not released. There “magic” happens in the EventTypesWithCleanup class, which has group: \kill (Pproto does a lookup there to construct its default cleanup). Now I’m pondering if this can be changed to release…

Probably the selling point of this is that since it changes what stop does on the resulting ESP, it can be seamlessly combined with Pdefs further upstream.

Pdef(\heh, ~gwrap2.(Pbind(\dur, inf)))
Pdef(\heh).play
Pdef(\heh).stop //works

Surprisingly (for me), this works too

p = ~gwrap.(Pfunc({ |ev| ev[\dur] = inf })).play
p.stop // works somehow

I was expecting that to fail because Pproto does this conversion internally

stream = Pfpar(pattern.asArray).asStream;

I’m not sure exactly what the limitations stemming from that are (I guess I’d better ask separately.)

Another issue that’s perhaps worth mentioning here is that Pgroup is useless for this scenario, but at least it’s obvious why: it tries to schedule its group cleanup after all the events from the stream have finished so that clearly is a no-op with a dur: inf event.