diff --git a/src/common/events.h b/src/common/events.h index 89c85977..9758637c 100644 --- a/src/common/events.h +++ b/src/common/events.h @@ -272,6 +272,8 @@ void passthrough_event(boost::asio::local::stream_protocol::socket& socket, // to create a Win32 window, pass that to the plugin, and // then write the corresponding X11 window handle to the // data pointer. + // TODO: I really want to build a more obvious mechanism + // for this return *reinterpret_cast(data); }}, event.payload); diff --git a/src/plugin/host-bridge.cpp b/src/plugin/host-bridge.cpp index 6a66d7d3..52531c81 100644 --- a/src/plugin/host-bridge.cpp +++ b/src/plugin/host-bridge.cpp @@ -261,6 +261,57 @@ intptr_t HostBridge::dispatch(AEffect* /*plugin*/, // Some events need some extra handling // TODO: Handle GUI closing? switch (opcode) { + break; + case effClose: + // TODO: Gracefully close the editor? + // TODO: Check whether the sockets and the endpoint are closed + // correctly + { + // Allow the plugin to handle its own shutdown. I've found a few + // plugins that work fine except for that they crash during + // shutdown. This shouldn't have any negative side effects since + // state has already been saved before this and all resources + // are cleaned up properly. Still not sure if this is a good way + // to handle this. + intptr_t return_value = 1; + try { + return_value = send_event( + host_vst_dispatch, dispatch_semaphore, converter, + std::pair(logger, true), opcode, index, + value, data, option); + } catch (const boost::system::system_error& a) { + // Thrown when the socket gets closed because the VST plugin + // loaded into the Wine process crashed during shutdown + logger.log("The plugin crashed during shutdown, ignoring"); + } + + // Boost.Process will send SIGKILL to the Wien host for us when + // this class gets destroyed. Because the process is running a + // few threads Wine will say something about a segfault + // (probably related to `std::terminate`), but this doesn't seem + // to have any negative impact + + // The `stop()` method will cause the IO context to just drop + // all of its work and immediately and not throw any exceptions + // that would have been caused by pipes and sockets being closed + io_context.stop(); + + // `std::thread`s are not interruptable, and since we're doing + // blocking synchronous reads there's no way to interrupt them. + // If we don't detach them then the runtime will call + // `std::terminate` for us. The workaround here is to simply + // detach the threads and then close all sockets. This will + // cause them to throw exceptions which we then catch and + // ignore. Please let me know if there's a better way to handle + // this.q + host_callback_handler.detach(); + wine_io_handler.detach(); + + delete this; + + return return_value; + } + break; case effEditOpen: // TODO: Should work as follows: // 1. Create a window in the Wine host using the Windows APIs @@ -268,60 +319,19 @@ intptr_t HostBridge::dispatch(AEffect* /*plugin*/, // 4. Use XEmbed to embmed the Wine window inside the parent // window stored in the data void pointer // 5. Return a handle to the X11 window - send_event(host_vst_dispatch, dispatch_semaphore, converter, - std::pair(logger, true), opcode, index, - value, data, option); - - return 0; - break; - case effClose: - // TODO: Gracefully close the editor? - // TODO: Check whether the sockets and the endpoint are closed - // correctly - - // Allow the plugin to handle its own shutdown. I've found a few - // plugins that work fine except for that they crash during - // shutdown. This shouldn't have any negative side effects since - // state has already been saved before this and all resources are - // cleaned up properly. Still not sure if this is a good way to - // handle this. - intptr_t return_value = 1; - try { - return_value = + { + // The plugin will return 0 if it does not actually support + // opening a window + const auto return_value = send_event(host_vst_dispatch, dispatch_semaphore, converter, std::pair(logger, true), opcode, index, value, data, option); - } catch (const boost::system::system_error& a) { - // Thrown when the socket gets closed because the VST plugin - // loaded into the Wine process crashed during shutdown - logger.log("The plugin crashed during shutdown, ignoring"); + if (return_value == 0) { + return 0; + } + + return return_value; } - - // Boost.Process will send SIGKILL to the Wien host for us when this - // class gets destroyed. Because the process is running a few - // threads Wine will say something about a segfault (probably - // related to `std::terminate`), but this doesn't seem to have any - // negative impact - - // The `stop()` method will cause the IO context to just drop all of - // its work and immediately and not throw any exceptions that would - // have been caused by pipes and sockets being closed - io_context.stop(); - - // `std::thread`s are not interruptable, and since we're doing - // blocking synchronous reads there's no way to interrupt them. If - // we don't detach them then the runtime will call `std::terminate` - // for us. The workaround here is to simply detach the threads and - // then close all sockets. This will cause them to throw exceptions - // which we then catch and ignore. Please let me know if there's a - // better way to handle this.q - host_callback_handler.detach(); - wine_io_handler.detach(); - - delete this; - - return return_value; - break; } // TODO: Maybe reuse buffers here when dealing with chunk data diff --git a/src/wine-host/plugin-bridge.cpp b/src/wine-host/plugin-bridge.cpp index 9db39043..92bf3f20 100644 --- a/src/wine-host/plugin-bridge.cpp +++ b/src/wine-host/plugin-bridge.cpp @@ -132,6 +132,10 @@ PluginBridge::PluginBridge(std::string plugin_dll_path, // the X11 window handle passed by the host if (opcode == effEditOpen) { const auto handle = editor.open(); + + // The plugin will return 0 if it can not open its + // editor window (or if it does not support it, but in + // that case the DAW should be hiding the option) const intptr_t return_value = plugin->dispatcher( plugin, opcode, index, value, handle, option); if (return_value == 0) {