From f8399f26b5cce6fc7e2a18e42493afd3fbbe79ae Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 8 Oct 2022 23:49:48 +0200 Subject: [PATCH] Enable mutual recursion for all CLAP callbacks This fixes Surge XT. It would otherwise deadlock when it tried to do a parameter rescan on first load. --- .../bridges/clap-impls/host-proxy.cpp | 3 ++ src/wine-host/bridges/clap.cpp | 46 ++++++++++--------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/wine-host/bridges/clap-impls/host-proxy.cpp b/src/wine-host/bridges/clap-impls/host-proxy.cpp index 92ab5e86..4f34e463 100644 --- a/src/wine-host/bridges/clap-impls/host-proxy.cpp +++ b/src/wine-host/bridges/clap-impls/host-proxy.cpp @@ -291,6 +291,9 @@ clap_host_proxy::ext_params_rescan(const clap_host_t* host, assert(host && host->host_data); auto self = static_cast(host->host_data); + // NOTE: This one in particular needs the mutual recursion because Surge XT + // calls this function immediately when inserting, and when the host + // opens the GUI at the same time this would otherwise deadlock self->bridge_.send_mutually_recursive_main_thread_message( clap::ext::params::host::Rescan{ .owner_instance_id = self->owner_instance_id(), .flags = flags}); diff --git a/src/wine-host/bridges/clap.cpp b/src/wine-host/bridges/clap.cpp index 78557d71..699726ca 100644 --- a/src/wine-host/bridges/clap.cpp +++ b/src/wine-host/bridges/clap.cpp @@ -355,9 +355,11 @@ void ClapBridge::run() { -> clap::ext::gui::plugin::IsApiSupported::Response { const auto& [instance, _] = get_instance(request.instance_id); - return main_context_ - .run_in_context([&, plugin = instance.plugin.get(), - gui = instance.extensions.gui]() { + // See below and the comment in `host-proxy.cpp` for why this is + // sprinkled all over the place + return do_mutual_recursion_on_gui_thread( + [&, plugin = instance.plugin.get(), + gui = instance.extensions.gui]() { // It's a bit unnecessary to bridge the entire // `is_api_supported()` function since we'll only bridge // a single config (non-floating, X11), but this is @@ -374,16 +376,15 @@ void ClapBridge::run() { request.is_floating); break; } - }) - .get(); + }); }, [&](const clap::ext::gui::plugin::Create& request) -> clap::ext::gui::plugin::Create::Response { const auto& [instance, _] = get_instance(request.instance_id); - return main_context_ - .run_in_context([&, plugin = instance.plugin.get(), - gui = instance.extensions.gui]() { + return do_mutual_recursion_on_gui_thread( + [&, plugin = instance.plugin.get(), + gui = instance.extensions.gui]() { // We don't need to do anything here yet. The actual // window is created at the final `.set_parent()` call. // Like the above function, we'll translate the API type @@ -396,25 +397,23 @@ void ClapBridge::run() { request.is_floating); break; } - }) - .get(); + }); }, [&](const clap::ext::gui::plugin::Destroy& request) -> clap::ext::gui::plugin::Destroy::Response { const auto& [instance, _] = get_instance(request.instance_id); - return main_context_ - .run_in_context([&, plugin = instance.plugin.get(), - gui = instance.extensions.gui, - &editor = instance.editor]() { + return do_mutual_recursion_on_gui_thread( + [&, plugin = instance.plugin.get(), + gui = instance.extensions.gui, + &editor = instance.editor]() { gui->destroy(plugin); // Cleanup is handled through RAII editor.reset(); return Ack{}; - }) - .get(); + }); }, [&](clap::ext::gui::plugin::SetScale& request) -> clap::ext::gui::plugin::SetScale::Response { @@ -526,10 +525,14 @@ void ClapBridge::run() { -> clap::ext::gui::plugin::SetParent::Response { const auto& [instance, _] = get_instance(request.instance_id); - return main_context_ - .run_in_context([&, plugin = instance.plugin.get(), - gui = instance.extensions.gui, - &editor = instance.editor]() { + // NOTE: This one in particular needs the mutual recursion + // because Surge XT calls this function immediately when + // inserting, and when the host opens the GUI at the same + // time this would otherwise deadlock + return do_mutual_recursion_on_gui_thread( + [&, plugin = instance.plugin.get(), + gui = instance.extensions.gui, + &editor = instance.editor]() { Editor& editor_instance = editor.emplace(main_context_, config_, generic_logger_, request.x11_window); @@ -562,8 +565,7 @@ void ClapBridge::run() { } return result; - }) - .get(); + }); }, [&](const clap::ext::gui::plugin::Show& request) -> clap::ext::gui::plugin::Show::Response {