Evaluate Function when MIDIClient is disposed of?

Is there a way to implement something like an AbstractSystemAction for MIDIClient such that I could register a Function to be evaluated when MIDIClient is disposed of or restarted?

I’m writing some classes for working with a control surface and would like to be able to clean up its state along with the client. Any advice would be appreciated; thanks!

I built MIDIWatcher for this (https://github.com/scztt/MidiWatcher.quark). You can do:

// MIDIWatcher.start;

MIDIWatcher.signal(\sourceAdded).connectToUnique({
	|watcher, signal, sources|
	"Added sources: %".format(sources).postln;
});

MIDIWatcher.signal(\sourceRemoved).connectToUnique({
	|watcher, signal, sources|
	"Removed sources: %".format(sources).postln;
});

MIDIWatcher.signal(\destinationAdded).connectToUnique({
	|watcher, signal, destinations|
	"Added destination: %".format(destinations).postln;
});

MIDIWatcher.signal(\destinationRemoved).connectToUnique({
	|watcher, signal, destinations|
	"Removed destination: %".format(destinations).postln;
});

You’ll need to add MIDIWatcher.start to your startup file, or run it once when you want to start monitoring.

1 Like

Thanks very much; will be curious to have a look at your implementation!

Okay, finally had time to take a look at your code and while I like the idea of using SkipJack (which I don’t make enough use of myself), I’d ideally be looking for something that will also work when MIDIClient is disposed of along with Main (i.e. through thisProcess.recompile, which would also destroy the SkipJack iiuc).

When MIDIClient is initialized, it registers a Function to clean itself up (ShutDown.add({ this.disposeClient })), but adding a Function to ShutDown.objects that sends cc messages to zero a control surface doesn’t seem to work:

MyControllerClass {
    *init {
        ShutDown.objects.addFirst({ /* send some cc's */ })
    }
}

I’d assume this is because MIDI output is async and MIDIClient gets cleaned up before the messages can be sent despite its cleanup Function being ordered later in ShutDown.objects. This is the first approach I thought to try, and when it didn’t work, I thought “well, really what I want is something that’s tied to MIDIClient, not ShutDown. It’s a shame that there’s no AbstractSystemAction for MIDIClient.”

Perfectly willing to concede that this isn’t possible as things currently stand, but still curious to know whether anyone else has thought of something I haven’t.