VSTCallbackHandler

Juce is designed to build multiple plugin formats from a single code base (VST2, VST3, AU, AAX). Not all of those formats support the same feature sets. Juce mainly supports what is common to all of them. (That said, there still are a few plugin format specific features.)

I don’t think there is any particular documentation for this kind of stuff. As a hint, you can look in the juce_VST3_Wrapper.cpp the class JuceVST3Component and the method initialize(FUnknown* hostContext) in that. You have to somehow be able to pass the hostContext pointer into your Juce AudioProcessor subclass. Then you can initialize the Reaper specific VST3 extensions stuff. (Also note that initializing the Reaper extensions for VST3 works completely differently compared to VST2 also.)

I have no idea how you should implement such kind of mechanism and even if that would be technically possible this would be super annoying if you wanted to build a VST2 and VST3 version from the very same code base (and this is basically what JUCE is all about when it comes to plugins).

The VST3 interface works completely different compared to the VST2 one, so there is not much point in applying these callbacks to VST3. Adding VST3 extension currently is only possible with modification of the JUCE wrapper code. I did that a while back to implement some of the Presonus extensions in our in-house JUCE fork. If you are not used to this COM interface stuff this can be quite a challenging task.

AFAIU, there are #define symbols that denote what kind of target is compiled, so the inappropriate code can be turened off, which can’t be used by somebody who wants to use the same user code base for VST2 and VST3, and …

COM interfaces ??? Is this not pure Windows stuff ?

Thanks,
-Michael

For fun, I’ll look in the juce_VST3_Wrapper.cpp the class JuceVST3Component ad debug to see ir Reaper sends anythiong that might look interesting…

In a JUCE plugin project, the shared code is compiled once for all wrapper types into a static library. After that, each format specific wrapper code is compiled and linked against that shared code library.

Therefore, you don’t know anything about the wrapper type at the time point you are compiling the shared code and it’s not possible to use any preprocessor defines for this purpose.

Nope. I have to admit that I’m by far no expert in that field, but afaik while coming from the Windows world originally it’s also used outside of it. And the VST3 standard makes use of it. I think you’ll quickly figure out that these interfaces don’t look very well readable at first when having a look at the VST3 wrapper code.

??? AFAIU, I need to use *.h files to allow overriding functions in derived classes in my code. Hence these *.h files could contain format specific code via #if s.
-Michael

So inside your plugin code you basically want to write something like

#include <JuceHeader.h>

class MyPluginProcessor : public juce::AudioProcessor
#if VST2
                         ,public juce::VSTCallbackHandler
#endif
{

#if VST3
void someFunctionOnlyAvailableToVST3();
#endif

}

juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new MyPluginProcessor(); }

This is not really possible with the structure JUCE works. A JUCE plugin project always consists of multiple targets.

The first target is the shared code target. This target will compile your project code, including the audio processor and the createPluginFilter factory function once into the static library.

Once that compilation run is done, the format specific wrapper code gets compiled by a different format specific target and then links against the static library containing the precompiled code used by all plugin formats. So at the timepoint where your AudioProcessor class gets compiled it knows nothing about wether a VST, AU or AAX wrapper target will link against it after that compilation task is done.

If in theory a certain format specific define would be set during the compilation run of the shared code, this would mean that the created binary would not be suitable to be shared by all format wrappers anymore. Instead it would mean that all your plugin code would have to be compiled completely for each format you are targeting, making the shared code target approach useless.

In case you are wondering why JUCE is not simply compiling all the code separately for each format to allow that you might want to take big and complex plugin projects into consideration. E.g. one of the more complex plugin projects I’m currently working on, easily reaches compile times of approx. 10 to 15 minutes for a complete build on a decent up-to-date machine. Compiling the sources separately for all four formats usually targeted would mean compile times greater 40 minutes for the same project – this is not desirable at all.

Did that clear up things a bit or did you mean something different?

I understand.
Thanks,
-Michael