This is totally awesome work - it will be a real game-changer for a lot of people. I haven't had time to do a full review, but I've been poking the code a little and have a few design questions:
- VstPluginUGen takes bus indexes plus a channel count as arguments - this is non-standard for a ugen that processes audio input -- normally you would simply allow one or more channels of audio to be passed directly in as an "in" argument. I understand that the output channel count would still have to be a parameter (this is the norm for ugens that output a variable number of channels, so that seems fine). Is there a specific reason to use buses? It should work exactly the same to read from / write to internal Synth wirebufs, no?
- Why is VstPlugin a subclass of Synth rather than a standalone class that e.g. points to a running Synth? For example, why not:
~node = { VstPluginUgen.ar(...) }.play;
~vstInstance = VstPlugin(~node);
Subclassing Synth could make VST plugins much less flexible vs a more loose coupling between VstPlugin objects and synths (for example, what if I want a VstPlugin that controls a Synth running via an Ndef?)
- Is it possible to support specifying VST parameters via regular UGen arguments, e.g. a syntax like:
sig = VstPluginUgen.ar(input, args:['param1': SinOsc.kr(1)]);
I understand that VST's may have too many parameters to easily support them all via Synth arguments, but it seems important to be able to at least able to have the *option* to set params as part of the normal SynthDef graph (for e.g. modulating parameters).
- You mention plugin open/close and bank load/save as non-realtime-safe operations. Can these be performed asynchronously, rather than in a way that blocks the audio thread as they are now?
- The ugen index in your /u_cmd is hard-coded to 2. This definitely isn't safe - there's no guarantee that the ugen index is always going to be 2, this is an internal implementation detail. Beyond that, it limits flexibility (since this e.g. would not allow more than one VST ugen per synth). You should be able to walk the ugens of a particular SynthDef (SynthDescLib.at(\foo).def.children), find all instances of VstPluginUgen, and find their index (I believe this should be .synthIndex, or just their position in the children array) - this should be a safe and stable way to get an index for /u_cmd.
Excited to see this evolve!
Scott