diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cc3412f..6eb51132 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 VST3 plugins freezing in **Ardour** and **Mixbus** when the plugin tries + to automate a parameter while loading a preset. - Fixed a regression from yabridge 3.1.0 where REAPER would freeze when opening a VST3 plugin context menu. - Fixed a potential assertion failure when setting VST3 preset data. This would diff --git a/src/wine-host/bridges/vst3-impls/component-handler-proxy.cpp b/src/wine-host/bridges/vst3-impls/component-handler-proxy.cpp index b9d3e0b9..227082e9 100644 --- a/src/wine-host/bridges/vst3-impls/component-handler-proxy.cpp +++ b/src/wine-host/bridges/vst3-impls/component-handler-proxy.cpp @@ -47,10 +47,15 @@ Vst3ComponentHandlerProxyImpl::beginEdit(Steinberg::Vst::ParamID id) { tresult PLUGIN_API Vst3ComponentHandlerProxyImpl::performEdit( Steinberg::Vst::ParamID id, Steinberg::Vst::ParamValue valueNormalized) { - return bridge.send_message(YaComponentHandler::PerformEdit{ - .owner_instance_id = owner_instance_id(), - .id = id, - .value_normalized = valueNormalized}); + // HACK: Ardour/Mixbus will in some cases immediately call + // `IEditController::setParamNormalized()` after this `performEdit()`, + // so we need to be able to receive that + // `IEditController::setParamNormalized()` on the same thread. + return bridge.send_mutually_recursive_message( + YaComponentHandler::PerformEdit{ + .owner_instance_id = owner_instance_id(), + .id = id, + .value_normalized = valueNormalized}); } tresult PLUGIN_API diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 2b6fba22..b6ec5119 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -440,9 +440,16 @@ void Vst3Bridge::run() { }, [&](const YaEditController::SetParamNormalized& request) -> YaEditController::SetParamNormalized::Response { - return object_instances[request.instance_id] - .edit_controller->setParamNormalized(request.id, - request.value); + // HACK: Under Ardour/Mixbus, `IComponentHandler::performEdit()` + // and `IEditController::setParamNormalized()` can be + // mutually recursive because the host will immediately + // relay the parameter change the plugin has just + // announced. + return do_mutual_recursion_on_off_thread([&]() { + return object_instances[request.instance_id] + .edit_controller->setParamNormalized(request.id, + request.value); + }); }, [&](YaEditController::SetComponentHandler& request) -> YaEditController::SetComponentHandler::Response {