VST Gets Created Twice in Host, Breaks VST

Hello,

I’m trying to load a VST inside a JUCE plugin host and am experiencing some strange behavior only in my Windows build (no issues with OSX). The plugin is a sampler with internal plugin effect modules that are instantiated in a singleton registry. With JUCE 4.3 and up, when I load this vst, the effects modules disappear.

Now, I’ve traced the issue to the function in juce_VSTPluginFormat.cpp:
static VSTPluginInstance* create (const ModuleHandle::Ptr& newModule, double initialSampleRate, int initialBlockSize)

This function seems to be creating the vst twice and, probably due to a bug in the vst, the effects module instance registry gets corrupted on the second loading. I think there’s an issue with releasing the first instance before creating the second one.

Though I’m trying to find the root of the cause in the vst, commenting out the code that loads the vst the second time around seems to fix the problem. So, my actual question is: why does the vst need to be created twice, and are there any consequences to altering the function as follows?

static VSTPluginInstance* create (const ModuleHandle::Ptr& newModule,
                                  double initialSampleRate,
                                  int initialBlockSize)
{
    if (VstEffectInterface* newEffect = constructEffect (newModule))
    {
        /* commented out
        newEffect->hostSpace2 = 0;

        newEffect->dispatchFunction (newEffect, plugInOpcodeIdentify, 0, 0, 0, 0);

        newEffect->dispatchFunction (newEffect, plugInOpcodeSetSampleRate, 0, 0, 0, static_cast<float> (initialSampleRate));
        newEffect->dispatchFunction (newEffect, plugInOpcodeSetBlockSize,  0, jmax (32, initialBlockSize), 0, 0);

        newEffect->dispatchFunction (newEffect, plugInOpcodeOpen, 0, 0, 0, 0);
         */
        
        BusesProperties ioConfig = queryBusIO (newEffect);
        
        /* commented out
        newEffect->dispatchFunction (newEffect, plugInOpcodeClose, 0, 0, 0, 0);

        newEffect = constructEffect (newModule);
         */

        if (newEffect != nullptr)
            return new VSTPluginInstance (newModule, ioConfig, newEffect);
    }

    return nullptr;
}

Hi. I’m not sure why it gets created/destroyed/created (maybe the JUCE devs can comment), but there’s usually a problem in your code (from my experience) if this cycle causes an issue. Ultimately, if this causes a problem in the plugin host it’s going to cause a problem in a real host if people are creating/deleting plugin instances - maybe this is why the plugin host does it, as a test?

I think that if you remove all the registered functions, you won’t get the interactions you are looking for in your plugin. I suppose that the first call is there to check that you can instantiate the module, and the second call is made to set it up properly. Why isn’t it done in the same step? Probably because you need to have a common interface to all the different flavors of plugins, and this was the easiest and most maintainable way to do it.

If your plugin can’t be created twice, you have a serious bug in your effect.

Thanks guys.

Looks like they just quietly fixed this for VST2 hosting after I posted:

https://github.com/WeAreROLI/JUCE/commit/4c03a9079b4e1ca668c686ad3c378b57960ddc79

Though I’m still a little confused on whether there is some fatal flaw in my vst code or if this was just a host bug. Couldn’t find any issues on my side. I guess I’ll move on and hope for the best.

interesting… i think I might add it back to my build tho - as I say, it was a good sanity check :slight_smile:

Hmmmm, git blame definitely says that I’m the culprit: it doesn’t really look like a typo to me so there must have been some reason why I put it there but searching the forum (and my memory) didn’t really help me refresh my memory.

As you’ve noticed already, I’ve removed the double instantiation and tested it on the most popular plug-ins. Let’s see if anybody complains.

Note to myself: always add comments when adding workarounds :slight_smile:.

… two years later … :slight_smile:

There is a plugin that crashes because “effOpen” code gets sent to a plugin twice.
Once within the static ::create() function of the VSTPluginInstance class and then again inside the ::initialize() call.

Most VST plugins are perfectly fine with this, but this one (from Waves) crashes and it is confirmed that this is the reason for the crash.

It seems that this double call is there to make sure that the plugin is initialized with the appropriate buffer size and sample rate before it starts to process data which seems perfectly reasonable. A comment within the VST2.4 SDK itself says that AudioEffect::open() is called when the plugin is initialized. So calling multiple times seems to be a valid operation.

The real question is: can we be sure that calling “open()” multiple times is ok and this is purely an error on the plugin maker part or should we try to find a workaround?

Hi JUCE Team :slight_smile:

Any ideas how the problem mentioned by @djogon1 can be fixed or worked around?
Right now Waves VST2 plugins (at least Element and Codex) immediately crash the plugin host on loading. Commenting the dispatch (Vst2::effOpen, 0, 0, 0, 0); part in VSTPluginInstance::initialise(..) fixes the crash but I am not sure about negative side-effects.

1 Like

Hi JUCE Team,

A quick +1, any word on this yet?

Looks like an issue has been raised: https://github.com/WeAreROLI/JUCE/issues/612

FYI - I ran into some issues with the fix proposed by @djogon1. Failing to call effOpen prior to instantiation of the VSTPluginInstance leaves the numParams field with it’s default value of 1. So when the VSTPluginInstance is constructed and refreshParameterList() is called, it never gets the correct number of parameters.

On Catalina and Big Sur, with the latest release of Waves Codex, the very first dispatch of effOpen in create causes the plugin to segfault. Commenting out the call in initialise has no effect.

On Windows, I’m able to open Codex with no changes to JUCE.

At the moment, I’m inclined to say that this is a bug in the Mac version of Codex 12. I’d be reluctant to modify JUCE code to accommodate Codex, given that this may in turn break other plugins, as @dstephenson hinted at.