From 0eb80fe866d3e097f80c1d92b714223903bbcb92 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 2 Dec 2020 00:35:41 +0100 Subject: [PATCH] Add a general entry point to HostBridge Since for all plugin types we would need to start listening for incoming events this way. --- src/wine-host/bridges/common.h | 15 +++++++++++++++ src/wine-host/bridges/group.cpp | 2 +- src/wine-host/bridges/vst2.cpp | 2 +- src/wine-host/bridges/vst2.h | 13 +------------ src/wine-host/individual-host.cpp | 28 +++++++++++++--------------- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/wine-host/bridges/common.h b/src/wine-host/bridges/common.h index d932ac50..85eac4e1 100644 --- a/src/wine-host/bridges/common.h +++ b/src/wine-host/bridges/common.h @@ -25,6 +25,21 @@ */ class HostBridge { public: + virtual ~HostBridge(){}; + + /** + * Handle events until the plugin exits. The actual events are posted to + * `main_context` to ensure that all operations to could potentially + * interact with Win32 code are run from a single thread, even when hosting + * multiple plugins. The message loop should be run on a timer within the + * same IO context. + * + * @note Because of the reasons mentioned above, for this to work the plugin + * should be initialized within the same thread that calls + * `main_context.run()`. + */ + virtual void run() = 0; + /** * Handle X11 events for the editor window if it is open. This can safely be * run from any thread. diff --git a/src/wine-host/bridges/group.cpp b/src/wine-host/bridges/group.cpp index 3fee24da..25dc67bd 100644 --- a/src/wine-host/bridges/group.cpp +++ b/src/wine-host/bridges/group.cpp @@ -116,7 +116,7 @@ void GroupBridge::handle_plugin_dispatch(size_t plugin_id) { // Blocks this thread until the plugin shuts down, handling all events on // the main IO context - bridge->handle_dispatch(); + bridge->run(); logger.log("'" + bridge->vst_plugin_path.string() + "' has exited"); // After the plugin has exited we'll remove this thread's plugin from the diff --git a/src/wine-host/bridges/vst2.cpp b/src/wine-host/bridges/vst2.cpp index 216d7e02..03bb7ca1 100644 --- a/src/wine-host/bridges/vst2.cpp +++ b/src/wine-host/bridges/vst2.cpp @@ -271,7 +271,7 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context, }); } -void Vst2Bridge::handle_dispatch() { +void Vst2Bridge::run() { sockets.host_vst_dispatch.receive_events( std::nullopt, [&](Event& event, bool /*on_main_thread*/) { if (event.opcode == effProcessEvents) { diff --git a/src/wine-host/bridges/vst2.h b/src/wine-host/bridges/vst2.h index 5d82c146..65e719ea 100644 --- a/src/wine-host/bridges/vst2.h +++ b/src/wine-host/bridges/vst2.h @@ -62,18 +62,7 @@ class Vst2Bridge : public HostBridge { std::string plugin_dll_path, std::string endpoint_base_dir); - /** - * Handle events until the plugin exits. The actual events are posted to - * `main_context` to ensure that all operations to could potentially - * interact with Win32 code are run from a single thread, even when hosting - * multiple plugins. The message loop should be run on a timer within the - * same IO context. - * - * @note Because of the reasons mentioned above, for this to work the plugin - * should be initialized within the same thread that calls - * `main_context.run()`. - */ - void handle_dispatch(); + void run() override; /** * Forward the host callback made by the plugin to the host and return the diff --git a/src/wine-host/individual-host.cpp b/src/wine-host/individual-host.cpp index f3f75e10..5ea79a4e 100644 --- a/src/wine-host/individual-host.cpp +++ b/src/wine-host/individual-host.cpp @@ -76,25 +76,12 @@ main(int argc, char* argv[]) { // don't need to differentiate between individually hosted plugins and // plugin groups when it comes to event handling. MainContext main_context{}; - Win32Thread worker_thread; - std::shared_ptr bridge; + std::unique_ptr bridge; try { switch (plugin_type) { case PluginType::vst2: - bridge = std::make_shared( + bridge = std::make_unique( main_context, plugin_location, socket_endpoint_path); - - // We'll listen for `dispatcher()` calls on a different thread, - // but the actual events will still be executed within the IO - // context - worker_thread = Win32Thread([&]() { - std::static_pointer_cast(bridge) - ->handle_dispatch(); - - // When the sockets get closed, this application should - // terminate gracefully - main_context.stop(); - }); break; case PluginType::vst3: std::cerr << "TODO: Not yet implemented" << std::endl; @@ -114,6 +101,17 @@ main(int argc, char* argv[]) { return 1; } + // Let the plugin receive and handle its events on its own thread. Some + // potentially unsafe events that should always be run from the UI thread + // will be posted to `main_context`. + Win32Thread worker_thread([&]() { + bridge->run(); + + // When the sockets get closed, this application should + // terminate gracefully + main_context.stop(); + }); + std::cout << "Finished initializing '" << plugin_location << "'" << std::endl;