diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f59e968..7374a922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,8 @@ Versioning](https://semver.org/spec/v2.0.0.html). - Fixed _FabFilter_ VST3 plugins freezing in **Ardour** and **Mixbus** when trying to duplicate existing instances of the plugin while the GUI editor is 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 the host to always be using Microsoft COM and it won't initialize it by itself. InfiniStrip loads as expected now. diff --git a/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp b/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp index 50165d1e..8fa59869 100644 --- a/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp +++ b/src/wine-host/bridges/vst3-impls/context-menu-proxy.cpp @@ -114,7 +114,10 @@ tresult PLUGIN_API Vst3ContextMenuProxyImpl::removeItem( tresult PLUGIN_API Vst3ContextMenuProxyImpl::popup(Steinberg::UCoord x, 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(), .context_menu_id = context_menu_id(), .x = x, diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 3f10f661..2b6fba22 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -253,22 +253,21 @@ void Vst3Bridge::run() { -> Vst3PluginProxy::GetState::Response { // NOTE: The VST3 version of Algonaut Atlas doesn't restore // 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 = - main_context - .run_in_context([&]() { - // This same function is defined in both - // `IComponent` and `IEditController`, so the host - // is calling one or the other - if (object_instances[request.instance_id] - .component) { - return object_instances[request.instance_id] - .component->getState(&request.state); - } else { - return object_instances[request.instance_id] - .edit_controller->getState(&request.state); - } - }) - .get(); + do_mutual_recursion_on_gui_thread([&]() { + // This same function is defined in both `IComponent` + // and `IEditController`, so the host is calling one or + // the other + if (object_instances[request.instance_id].component) { + return object_instances[request.instance_id] + .component->getState(&request.state); + } else { + return object_instances[request.instance_id] + .edit_controller->getState(&request.state); + } + }); return Vst3PluginProxy::GetStateResponse{ .result = result, .state = std::move(request.state)};