handleVstHostCallbackAvailable(), handleVstManufacturerSpecific() and friends

Follow up to the thread " Attaching to the Reaper API VST2 vs VST3 "

By more research I found That the problems I described are not specific for the use of the plugin in Reaper, but the functions

handleVstPluginCanDo()
handleVstManufacturerSpecific()
and most important
handleVstHostCallbackAvailable()

can be used to attach to any VST host that provides the appropriate functionality in the VST API.

These functions just need to be overridden in a class derived from struct VSTCallbackHandler. By doing this, they are supposed to be called, (e.g) when the plugin is initiating.

I found and happily verified in an example I found and ported from JUCE 5.x to JUCE 6.x, that this works fine when I compile the code to a VST2 and load it in Reaper. I did not try other VST hosts, but I am sure that the same kind of code will work as appropriate.

When compiling the same code to a VST3 everything compiles perfectly OK, but these functions are not called using the same DAW.

I am positive that this is not because Reaper does not implement these functions in it’s VST3 API. I found discussions in Forums claiming that there are working examples of VST3s using this functionality on Reaper.

Moreover I found discussions in Forums that explicitly state that the JUCE framework nicely provides these function perfectly working for VST2 but not workable for VST3. This seem to be the currant state (since some four years).

Moreover I found discussions in Forums that claim that a rather simple patch for JUCE (5.x at that time) - seemingly not needing to deal with the complexity of COM interfaces that the VST3 API introduces, as this already perfectly is provided by the JUCE framework - would suffice to allow for enabling these functions when compiling to a VST3.

Edit:
It seems the interface stuff needs to be provided in a host specific way. From the docu for “embedding” a copy of the VST GUI in Reaper’s Track or Mixer control panel:
" * to support via VST3: IController should support IReaperUIEmbedInterface "
(looks intimidating :frowning: )

-Michael

JUCE now handles both VST2 and VST3 extensions. I’ve added a demo to the repository showing how to use this new functionality to add REAPER-specific features:

2 Likes

GREAT !
I’ll try this with my preliminary demo ASAP.
-Michael

Which version of JUCE should I use ?
Thanks,
-Michael

This change is on the latest develop branch.

Am I entiteled to d/l same ?
How ?
Thanks again,
-Michael

If you’re using git, just git checkout develop && git pull should do it. Alternatively, you can download a zip from github.

Thanks!
-Michael

I could d/l the folder “JUCE-4b0b245b55429b33a638ccea94aaa300baf5d524” that does contain the example “ReaperEmbeddedViewPluginDemo.h”.
I can do a build in CS Vode using “F7”. But the examples are not build, just the common files. No “examples” folder in the build" folder, no *.vst3 file anywhere.
Even after this, when clicking “ALL BUILD” in the bottom line, I get a list that does not contain any examples to allow them to be build.
What am I doing wrong ?
-Michael

To enable the demos, you need to configure the CMake build with JUCE_BUILD_EXAMPLES=ON. It looks like the settings.json is the place to set this, although I haven’t tried building with VS Code myself. There are some more details here.

Thanks. I’ll try ASAP.
I also tried to build it with cmake in a command line, but here I did not find out whch options to use, either.
-Michael

Sorry for my ignorance, but I seem to be unable to compile the example using CMake form the command line, either.
But compiling the example would not help me anyway with porting my example project from the “unofficial prerelease” (patched) JUCE version to your now official JUCE preview.
I am unable to decide how to set up the CMAKE config file I got a while ago from gxray (that contains some instructions to deal with the patched version) for a “clean” build. And this supposedly is the necessary step to try to compile and then update the *.cpp (and *.h) files in my project.
Thanks again for listening !
-Michael

There are well-commented example CMake projects in examples/CMake. Hopefully that should contain enough information to allow you to build an arbitrary plugin project.

Thanks to your help, I was able to build my ported to the new JUCE library example code.
I now have

DEF_CLASS_IID (IReaperHostApplication)
DEF_CLASS_IID (IReaperUIEmbedInterface)

....

Steinberg::TPtrInt handledEmbeddedUIMessage (int msg,
                                             Steinberg::TPtrInt parm2,
                                             Steinberg::TPtrInt parm3) override;

juce::pointer_sized_int handleVstManufacturerSpecific (juce::int32,
                                                 juce::pointer_sized_int value,
                                                 void* ptr,
                                                 float opt) override;

In the AudioPluginAudioProcessor class witch now inherits from VSTCallbackHandler, VST3ClientExtensions (, and EmbeddedViewListener).

But placing breakpoints at AudioPluginAudioProcessor::handleVstManufacturerSpecific() and AudioPluginAudioProcessor::handledEmbeddedUIMessage(), same never are hit.

What am I doing wrong ?
-Michael

handleVstManufacturerSpecific will only be called in VST plugins. In VST3 plugins, you must override queryIEditController, and have it return a pointer to an instance of reaper::IReaperUIEmbedInterface as shown in the example project.

Yep.
I did the overrides for queryIEditController() and setIHostApplication().
In fact both are called.
GREAT !
Unfortunately I am not able to compile my example with the necessary code implemented in queryIEditController() die to the structure if header files.
Maybe you might be able to provide some hint-.
In my source tree PluginProcessor.cpp and PluginEditor.cpp both include PluginProcessor.h to define the pluginprocessor class.
Hence (due to the inheritance and type definition implications)

DEF_CLASS_IID (IReaperHostApplication)
DEF_CLASS_IID (IReaperUIEmbedInterface)

needs to be in the header file.

But as same is include in both cpps, I get the linker error message that the iids are defined twice.

Now I have no idea how to resolve this :frowning:

Thanks for any help,
-Michael

You can create a new .cpp and put the DEF_CLASS_IID lines in there, instead of in a header.

Thanks a lot !
Silly me did not read correctly the hint given in the example source code right above the iid definitions. :hot_face:
-Michael

It now works great as a VST3.

I tried but is seems like I need to modify the code when compiling as a VST2. It in fact does compile, but the functions setIHostApplication() and queryIEditController() seemingly are not called in that case.

In fact I do have older examples providing the Reaper API and the Reaper VST embedding feature with VST2s, Do I need to switch to that (rather different) Methods even with the new version of the SDK ?

-Michael

The Embedded View Demo should work as both VST and VST3. When loaded as a VST, extensions can be handled by implementing the VSTCallbackHandler interface. When loaded as a VST3, extensions can be handled by implementing VST3ClientExtensions.

In the demo, the VST-specific functions are implemented like so:

    pointer_sized_int handleVstPluginCanDo (int32, pointer_sized_int, void* ptr, float) override
    {
        if (auto* str = static_cast<const char*> (ptr))
        {
            if (strcmp (str, "hasCockosEmbeddedUI") == 0)
                return 0xbeef0000;
        }

        return 0;
    }

    pointer_sized_int handleVstManufacturerSpecific (int32,
                                                     pointer_sized_int value,
                                                     void* ptr,
                                                     float opt) override
    {
        return (pointer_sized_int) handledEmbeddedUIMessage ((int) opt,
                                                             (Steinberg::TPtrInt) value,
                                                             (Steinberg::TPtrInt) ptr);
    }

Here, handledEmbeddedUIMessage is called by both the VST extensions interface (via handleVstManufacturerSpecific) and the VST3 extensions interface (via reaper::IReaperUIEmbedInterface::embed_message).