diff --git a/src/wine-host/plugin-bridge.cpp b/src/wine-host/plugin-bridge.cpp index e7941d49..015e5761 100644 --- a/src/wine-host/plugin-bridge.cpp +++ b/src/wine-host/plugin-bridge.cpp @@ -118,19 +118,6 @@ PluginBridge::PluginBridge(std::string plugin_dll_path, current_bridge_isntance = nullptr; plugin->ptr1 = this; - // For our communication we use simple threads and blocking operations - // instead of asynchronous IO since communication has to be handled in - // lockstep anyway - dispatch_handler = std::thread([&]() { - using namespace std::placeholders; - - while (true) { - passthrough_event(host_vst_dispatch, std::nullopt, plugin, - std::bind(&PluginBridge::dispatch_wrapper, this, - _1, _2, _3, _4, _5, _6)); - } - }); - parameters_handler = std::thread([&]() { while (true) { // Both `getParameter` and `setParameter` functions are passed @@ -189,6 +176,26 @@ PluginBridge::PluginBridge(std::string plugin_dll_path, << std::endl; } +void PluginBridge::handle_dispatch() { + using namespace std::placeholders; + + // For our communication we use simple threads and blocking operations + // instead of asynchronous IO since communication has to be handled in + // lockstep anyway + try { + while (true) { + passthrough_event(host_vst_dispatch, std::nullopt, plugin, + std::bind(&PluginBridge::dispatch_wrapper, this, + _1, _2, _3, _4, _5, _6)); + } + } catch (const boost::system::system_error&) { + // This happens when the sockets got closed because the plugin is being + // shut down. In that case we can just let the whole host terminate. + parameters_handler.detach(); + process_replacing_handler.detach(); + } +} + intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin, int opcode, int index, @@ -199,9 +206,9 @@ intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin, // the X11 window handle passed by the host switch (opcode) { case effEditIdle: - // Because of the way the Win32 APi works we have to process events + // Because of the way the Win32 API works we have to process events // on the same thread the window was created, and that thread is the - // `dispatch_handler` thread + // thread that's handling dispatcher calls editor.handle_events(); return plugin->dispatcher(plugin, opcode, index, value, data, @@ -261,12 +268,6 @@ intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin, } } -void PluginBridge::wait() { - dispatch_handler.join(); - parameters_handler.join(); - process_replacing_handler.join(); -} - class HostCallbackDataConverter : DefaultDataConverter { public: HostCallbackDataConverter(AEffect* plugin, diff --git a/src/wine-host/plugin-bridge.h b/src/wine-host/plugin-bridge.h index 3400cbfb..bd1d598a 100644 --- a/src/wine-host/plugin-bridge.h +++ b/src/wine-host/plugin-bridge.h @@ -55,9 +55,13 @@ class PluginBridge { PluginBridge(std::string plugin_dll_path, std::string socket_endpoint_path); /** - * Block the main thread until the plugin shuts down. + * Handle events on the main thread until the plugin quits. This can't be + * done on another thread since some plugins (e.g. Melda) expect certain + * (but for some reason not all) events to be passed from the same thread it + * was initiated from. This is then also the same thread that should handle + * Win32 GUI events. */ - void wait(); + void handle_dispatch(); intptr_t host_callback(AEffect*, int, int, intptr_t, void*, float); @@ -115,10 +119,6 @@ class PluginBridge { */ boost::asio::local::stream_protocol::socket vst_host_aeffect; - /** - * The thread that handles dispatch events from the host. - */ - std::thread dispatch_handler; /** * The thread that responds to `getParameter` and `setParameter` requests. */ diff --git a/src/wine-host/vst-host.cpp b/src/wine-host/vst-host.cpp index 83f2649e..f782fa6d 100644 --- a/src/wine-host/vst-host.cpp +++ b/src/wine-host/vst-host.cpp @@ -35,8 +35,8 @@ int main(int argc, char* argv[]) { try { PluginBridge bridge(plugin_dll_path, socket_endpoint_path); - // Block the main thread until the plugin shuts down - bridge.wait(); + // Blocks the main thread until the plugin shuts down + bridge.handle_dispatch(); } catch (const std::runtime_error& error) { std::cerr << "Error while initializing Wine VST host:" << std::endl; std::cerr << error.what() << std::endl;