Handle mutual recursion in context menus

REAPER will call `getState()` while the context menu is open, and that
also has to be handled from the GUI thread.
This commit is contained in:
Robbert van der Helm
2021-04-30 02:49:54 +02:00
parent 52428c8749
commit 36b3636072
3 changed files with 20 additions and 16 deletions
+2
View File
@@ -71,6 +71,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- Fixed _FabFilter_ VST3 plugins freezing in **Ardour** and **Mixbus** when - Fixed _FabFilter_ VST3 plugins freezing in **Ardour** and **Mixbus** when
trying to duplicate existing instances of the plugin while the GUI editor is trying to duplicate existing instances of the plugin while the GUI editor is
open. open.
- Fixed a regression where REAPER would freeze when opening a VST3 plugin
context menu.
- _PSPaudioware InifniStrip_ would fail to initialize because the plugin expects - _PSPaudioware InifniStrip_ would fail to initialize because the plugin expects
the host to always be using Microsoft COM and it won't initialize it by the host to always be using Microsoft COM and it won't initialize it by
itself. InfiniStrip loads as expected now. itself. InfiniStrip loads as expected now.
@@ -114,7 +114,10 @@ tresult PLUGIN_API Vst3ContextMenuProxyImpl::removeItem(
tresult PLUGIN_API Vst3ContextMenuProxyImpl::popup(Steinberg::UCoord x, tresult PLUGIN_API Vst3ContextMenuProxyImpl::popup(Steinberg::UCoord x,
Steinberg::UCoord y) { Steinberg::UCoord y) {
return bridge.send_message( // NOTE: This requires mutual recursion, because REAPER will call
// `getState()` whle the context menu is open, and `getState()` also
// has to be handled from the GUi thread
return bridge.send_mutually_recursive_message(
YaContextMenu::Popup{.owner_instance_id = owner_instance_id(), YaContextMenu::Popup{.owner_instance_id = owner_instance_id(),
.context_menu_id = context_menu_id(), .context_menu_id = context_menu_id(),
.x = x, .x = x,
+14 -15
View File
@@ -253,22 +253,21 @@ void Vst3Bridge::run() {
-> Vst3PluginProxy::GetState::Response { -> Vst3PluginProxy::GetState::Response {
// NOTE: The VST3 version of Algonaut Atlas doesn't restore // NOTE: The VST3 version of Algonaut Atlas doesn't restore
// state unless this function is run from the GUI thread // state unless this function is run from the GUI thread
// NOTE: This also requires mutual recursion because REAPER will
// call `getState()` while opening a popup menu
const tresult result = const tresult result =
main_context do_mutual_recursion_on_gui_thread<tresult>([&]() {
.run_in_context<tresult>([&]() { // This same function is defined in both `IComponent`
// This same function is defined in both // and `IEditController`, so the host is calling one or
// `IComponent` and `IEditController`, so the host // the other
// is calling one or the other if (object_instances[request.instance_id].component) {
if (object_instances[request.instance_id] return object_instances[request.instance_id]
.component) { .component->getState(&request.state);
return object_instances[request.instance_id] } else {
.component->getState(&request.state); return object_instances[request.instance_id]
} else { .edit_controller->getState(&request.state);
return object_instances[request.instance_id] }
.edit_controller->getState(&request.state); });
}
})
.get();
return Vst3PluginProxy::GetStateResponse{ return Vst3PluginProxy::GetStateResponse{
.result = result, .state = std::move(request.state)}; .result = result, .state = std::move(request.state)};