@Dave Gamble nailed it, but I wanted to add a few things on VST shell plugins, since they are a bit tricky to work with.
To determine if a VST is a shell plugin, send the effGetPlugCategory
opcode to the plugin dispatcher. If it returns kPlugCategShell
, then it's a shell plugin. To get the list of sub-plugins in the shell, you basically call effShellGetNextPlugin
until it returns 0. Example code snippit (adapted from a working VST host):
// All this stuff should probably be set up far earlier in your code...
// This assumes that you have already opened the plugin and called VSTPluginMain()
typedef VstIntPtr (*Vst2xPluginDispatcherFunc)(AEffect *effect, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt);
Vst2xPluginDispatcherFunc dispatcher;
AEffect* plugin;
char nameBuffer[40];
while(true) {
memset(nameBuffer, 0, 40);
VstInt32 shellPluginId = dispatcher(pluginHandle, effShellGetNextPlugin, 0, 0, nameBuffer, 0.0f);
if(shellPluginId == 0 || nameBuffer[0] == '\0') {
break;
}
else {
// Do something with the name and ID
}
}
If you actually want to load a plugin in a VST shell, it's a bit trickier. First, your host needs to handle the audioMasterCurrentId
opcode in the host callback. When you call the VST's VSTPluginMain()
method to instantiate the plugin, it will call the host callback with this opcode and ask for the unique ID which should be loaded.
Because this callback is made before the main function returns (and hence, before it delivers an AEffect*
to your host), that means that you probably will need to store the shell plugin ID to load in a global variable, since you will not be able to save a pointer to any meaningful data in void* user
field of the AEffect
struct in time for it to be passed back to you in the host callback.