updateHostDisplay / updateDisplay() ignored by hosts

I got a plugin with an own preset-management. It only exposes to the host as a ‘single-patch-plugin’.
I wrapped a VST2.4 plugin in JUCE with createPluginInstance and expose it as VST3.

I noticed that several hosts do not properly update the program name in their interface when the patch name is changed from within the plugin.

In the VST2.4 SDK you called AudioEffectX::updateDisplay () to notify the host about it. This did work in 99% of the cases. It seems that JUCE does not recognize or forward the updateDisplay() call from the loaded plugin.

I tried a different approach by polling it. Now I can at least notice when the patch name changed. However the hosts I tested still do not update the program name.

void processBlock(juce::AudioBuffer& buffer, juce::MidiBuffer& midiMessages) override
{ …
juce::String pnm;
pnm = plugin->getProgramName(0);
const char* pnmc = static_cast<const char*> (pnm.toUTF8());
if (strcmp(pnmc, oldprogramname) != 0)
{
MessageBox(“name has changed”, pnmc);
AudioProcessor::updateHostDisplay();
}
strcpy(oldprogramname,pnmc);
}

So, you’ve got a plugin instance inside another audio processor?

If that’s the case, then it’s not surprising that when you call updateHostDisplay() from inside the inner AudioProcessor, nothing happens in the host. The AudioProcessor holding the plugin instance is the host!

Why are you doing this wrapping?

To get this working, your wrapper plugin will need to register as an AudioProcessorListener of the inner plugin, and will need to call updateHostDisplay itself every time it receives a listener callback from the inner plugin.

class WrapperProcessor: public juce::AudioProcessor, public juce::AudioProcessorListener
{
WrapperProcessor(std::unique_ptrjuce::AudioPluginInstance processorToUse): AudioProcessor(getBusesPropertiesFromProcessor(processorToUse.get())),plugin(std::move(processorToUse))
{
plugin->addListener(this);
}

void audioProcessorParameterChanged(AudioProcessor* callingProcessor, int parameterIndex, float newValue) override
{
AudioProcessor::sendParamChangeMessageToListeners(parameterIndex, newValue);
}

void updateHostDisplay(const AudioProcessor::ChangeDetails& details )override { AudioProcessor::updateHostDisplay(details); }

Not sure how I can hook on this, since the fuction is not defined as virtual by JUCE like audioProcessorParameterChanged

Rather than overriding updateHostDisplay, I was suggesting that your outer AudioProcessor would implement AudioProcessorListener and override audioProcessorChanged. The outer processor should call addListener on the inner processor so that it can listen to changes triggered by the inner processor. In the implementation of the outer processor’s audioProcessorChanged function, you would directly forward the ChangeDetails to updateHostDisplay, i.e.

void OuterProcessor::audioProcessorChanged (AudioProcessor* inner, const ChangeDetails& d)
{
    updateHostDisplay (d);
}
1 Like

The code snipper above causes error C2385. I changed the code to make it compile.

void WrapperProcessor::audioProcessorChanged(AudioProcessor* inner, const AudioProcessor::ChangeDetails& details) override
{
updateHostDisplay(details);
}

However Reaper still does not update the patch name.
I also tried calling AudioProcessor::updateHostDisplay(details) and WrapperProcessor::updateHostDisplay(details) instead which did not help.
Or do I need to call inner->updateHostDisplay(details); ?

What does the implementation of WrapperProcessor::getProgramName() look like? Does it ask the inner plugin for the program name and then return that?

yes:

const juce::String WrapperProcessor::getProgramName(int index) override
{
return plugin->getProgramName(index);
}

On the off chance that you forgot: did you register the listener? :slight_smile: