Does plugin hosting support plugin GUI as a Component child?


#1

I've tried doing this in order to load a plugin and embed its GUI into my content component :

    delete m_plugin_instance;
    VSTPluginFormat vstformat;
    PluginDescription* desc = m_kplist->getType(the_proc_info.m_plugin_id);
    AudioPluginInstance* pluginst = vstformat.createInstanceFromDescription(*desc,44100.0,512);
    if (pluginst != nullptr)
    {
        Logger::writeToLog("Managed to create plugin " + pluginst->getName());
        if (pluginst->hasEditor() == true)
        {
            AudioProcessorEditor* ed = pluginst->createEditor();
            m_content_comp->addChildComponent(ed);
            ed->setTopLeftPosition(2, m_output_waveform->getBottom());
        }
        else
        {
            GenericAudioProcessorEditor* ed = new GenericAudioProcessorEditor(pluginst);
            m_content_comp->addChildComponent(ed);
            ed->setVisible(true);
            ed->setSize(300, 200);
            ed->setTopLeftPosition(2, m_output_waveform->getBottom());
        }
        m_plugin_instance = pluginst;
    }


Which seems to work at first, but fails slightly unpredictably (that is, almost everytime but not always) if I try running the code again for another plugin.  When the failure happens, the call stack shows some Juce timer keeps running and attempts to call into an invalid plugin instance. There appears to be no code of mine in the call stack. Does this have to do with the plugin GUI being added as a child of the content component? Or am I destroying the previous plugin instance in some incorrect way?

If it's about having the plugin GUI as a child component, that's unfortunate as I would really like to not have the plugin GUI as a separate window, which is how for example the Juce plugin hosting demo does it.


#2

Basically, adding a guest plug-in's editor to a component does work (doing this myself with a plug-in that hosts guest plug-ins).

Make shure you do this on the message thread. Also check what happens when your component and/or the guest-plugin's editor get deleted (ownership). I don't remember the details at this moment.

Also, there are hosts that do not seem to support this. The only way to deal with this for me was to detect the host and use standalone windows for guest plug-ins where required.

And lastly, editors require different sizes. Your component needs to adapt to them (resize dynamically).

HTH


#3

I'd appreciate if you could take a look at your code. I did myself try various other things (removing the plugin editor explicitly from the parent component, deleting the GUI editor explicitly before deleting the plugin etc) than what is shown in the code above, but nothing seemed to help this issue.


#4

You can put the hosted gui in a Component. But only one at the time. The plugins need their own native window.
By best advice is to keep this simple and don’t try anything creative as there are lots of plugins out there that make assumptions on how the host handles the plugin window


#5

Hmm well, for example Reaper, FL Studio and Cubase do have their own added GUI elements around the plugin GUI, so it isn't exceptional to have that kind of plugin GUI handling. IMHO that should work with Juce's plugin hosting too.

I wonder if it would help if I add a Juce Component into my content Component that would only have the plugin GUI as a child component...


#6

These hosts might possibly place an independent, borderless window on top of theirs, that moves and resizes with the parent.

I'm just guessing, but remember that I did it this way years ago to cope with issues that arose from adding the GUI as a child component. No idea how I finally got it working, but will have a look into the code.

I assume you are building a plug-in that hosts guest plugins, right?

If however you are building a host, you have more options, as you are in full control of the entire UI.


#7

This is basically what I'm doing to add the GUI (editor):

editor->setBounds (PluginInset, PluginOffsetFromTop, editor->getWidth(), editor->getHeight());
addAndMakeVisible (editor);
setSize (computeWidth  (editor->getWidth()), computeHeight (editor->getHeight()));     
getTopLevelComponent()->toFront (true); 

To remove it, I just delete it, which will remove it from the view hierarchy. Make sure the following things

1. Add/remove the guest-GUI on the message thread only!

2. Delete the GUI only when it's idle, i.e. no render callbacks anymore, no GUI updates (use a lock)

3. Remove your reference to the GUI before you delete it. Make sure it is totally isolated from anything before you delte it (i.e. does not longer receive messages, updates, etc that your parent UI might dispatch to it).

 

 


#8

Yeah, tracktion does too!

The point here isn't that you can't put a border around it - you can do that.

But you can't put multiple plugin windows inside the same parent. That'll lead to all kinds of clashes, as many plugins assume they're the only child of their parent windiw.


#9

I don't mean just window borders/title bar as those are kind of mandatory to have so that the window with the plugin can be moved, but I mean additional controls/components like in Reaper's plugin windows (the preset dropdown, dry/wet knob etc.) :

Tracktion's plugin container windows don't have stuff like that, right?

My own window that is supposed to have the plugin GUI "embedded" is just a bit more complicated than the above screenshot.

Multiple plugin GUIs within the same window was actually something I was planning to attempt, but I suppose I'll have to skip that at least with Juce's plugin hosting...

 

 


#10

Tracktion's plugin container windows don't have stuff like that, right?

No, but the tracktion title bar itself is basically just a large border with some stuff drawn in it, and it should work fine if you want to add other things in there.


#11

Dear @Xenakios,

I have a related issue. I used setContentComponent() function to set a dll ui plugin to host.

setContentComponent(AudioProcessor->createEditorIfNeeded() , false, false);

Now I cannot exit the application, because this plugin cannot be unloaded.
I took much time to search about deleting editor before deleting the plugin, but seems no forum discusses about it.
Can you give me a idea about this case?


#12

I still have not fully figured out how the plugin GUI editor components should be handled for my use case…Crashes and other problems still happen. :tired_face: It looks like having a plugin GUI as a child component is just not fully supported in Juce.

If for your use case you only need the plugin in a separate window, the Juce example plugin host seems to have a working solution which you could use for inspiration. (It appears you are trying to have a plugin GUI as the content component of a ResizableWindow or such because you are using setContentComponent,right?)


#13

Another snippet to look at might be the new standalone plugin type, there is also the editor inside a component:
Do you lack by chance the call to “AudioProcessor::editorBeingDeleted()”?


#14

I did a lot of experimenting when trying to put multiple VST editors wrapped inside the main window. I found it very difficult – I did it, though with some ugly JUCE code changes on multiple levels.

JUCE VST hosting code finds the actual plugin GUI window handle (HWND) using Windows function. HWND is later used in all kind of GUI related operations, so it is crucial.

pluginHWND = GetWindow ((HWND) getWindowHandle(), GW_CHILD);

This works perfect as long you have one child VSTPluginWindow opened. When you open the second one, this code fails. You always get HWND of the LAST opened plugin, so unexpected things start to happen. Interesting is, that even if you put each GUI inside its own parent component and then make this component a child of the main window, it still doesn’t work.

I somehow succeeded – I had to find the proper window handle of each plugin, when GUI is displayed plus a bunch of weird code. It is a realy nasty way of doing it. I would really like to see beter solution for this.