Hi there,
I am having an issue with using a PopupMenu
to load presets from disk. The summary of the issue is as follows:
- on the forum I’ve read that when using
PopupMenu
you should use theshowAsync
method if you are working inside a plugin (as I am). - calling
showAsync
works the first time and the preset state is loaded after the user selects from the popup menu. - the second time the menu is launched, the plugin crashes.
- changing the code to use
show
makes it so the preset loading works all the time.
I’ve read that show()
is inappropriate in this use case but it works where showAsync
does not. What is going on here? Can someone help me figure out the cause of the crash? Also can anyone help my cartoon of the threading model here?
The relevant code is below. The PresetManager::Instance().loadPreset(number, processor)
line calls the setStateInformation()
method on the processor. If it is needed for reference, let me know and I will include that class as well.
Thanks!
class PresetDisplayButtonListener : public juce::Button::Listener {
public:
PresetDisplayButtonListener(TelegraphUIContentComponent& uiComp, TelegraphAudioProcessor& proc)
:ui(uiComp)
,processor(proc)
,menu(std::make_unique<juce::PopupMenu>())
{
ui.getPresetDisplay()->addListener(this);
ui.getPresetDisplay()->setButtonText(PresetFileManager::Instance().getCurrentPresetName());
}
void buttonClicked(Button* button) override {
menu->clear();
menu->addItem (0, "SELECT PRESET", false, false);
menu->addSeparator();
for(size_t prog_idx=0; prog_idx<static_cast<size_t>(PresetFileManager::Instance().getNumPresets()); prog_idx++){
auto presetName = PresetFileManager::Instance().getPresetName(prog_idx);
bool isCurrentPreset = presetName == PresetFileManager::Instance().getCurrentPresetName();
menu->addItem (prog_idx+1, PresetFileManager::Instance().getPresetName(prog_idx), true, isCurrentPreset);
}
/*THIS CODE CRASHES ON SECOND POPUP OPEN*/
// menu->showMenuAsync(
// juce::PopupMenu::Options()
// .withTargetComponent(button)
// .withMinimumWidth(button->getBounds().getWidth()),
// popupCallback
// );
/* THIS CODE WORKS ??? */
int result = menu->show();
if(result>0){
PresetFileManager::Instance().loadPreset(result-1, processor);
ui.getPresetDisplay()->setButtonText(PresetFileManager::Instance().getCurrentPresetName());
}
}
private:
TelegraphUIContentComponent& ui;
TelegraphAudioProcessor& processor;
std::unique_ptr<juce::PopupMenu> menu;
std::function<void (int)> popupCallback = std::function<void (int)>([&](int result){
if(result>0){
PresetFileManager::Instance().loadPreset(result-1, processor);
ui.getPresetDisplay()->setButtonText(PresetFileManager::Instance().getCurrentPresetName());
}
});
};