diff --git a/src/plugin/plugin-bridge.cpp b/src/plugin/plugin-bridge.cpp index 377c46eb..3953f00e 100644 --- a/src/plugin/plugin-bridge.cpp +++ b/src/plugin/plugin-bridge.cpp @@ -19,11 +19,8 @@ #include #include #include -#include - -#ifdef USE_WINEDBG #include -#endif +#include // Generated inside of build directory #include @@ -74,35 +71,8 @@ PluginBridge::PluginBridge(audioMasterCallback host_callback) config(Configuration::load_for(get_this_file_location())), wine_version(get_wine_version()), wine_stdout(io_context), - wine_stderr(io_context), -#ifndef USE_WINEDBG - vst_host(vst_host_path, - // The Wine VST host needs to know which plugin to load - // and which Unix domain socket to connect to - vst_plugin_path, - socket_endpoint.path(), - bp::env = set_wineprefix(), - bp::std_out = wine_stdout, - bp::std_err = wine_stderr) -#else - // This is set up for KDE Plasma. Other desktop environments and window - // managers require some slight modifications to spawn a detached terminal - // emulator. - vst_host("/usr/bin/kstart5", - "konsole", - "--", - "-e", - "winedbg", - "--gdb", - vst_host_path.string() + ".so", - vst_plugin_path.filename(), - socket_endpoint.path(), - bp::env = set_wineprefix(), - // winedbg has no reliable way to escape spaces, so we'll start - // the process in the plugin's directory - bp::start_dir = vst_plugin_path.parent_path()) -#endif -{ + wine_stderr(io_context) { + launch_vst_host(); log_init_message(); // Print the Wine host's STDOUT and STDERR streams to the log file. This @@ -479,7 +449,12 @@ intptr_t PluginBridge::dispatch(AEffect* /*plugin*/, // loaded into the Wine process crashed during shutdown logger.log("The plugin crashed during shutdown, ignoring"); } - vst_host.terminate(); + + // Don't terminate group host processes. They will shut down + // automatically after all plugins have exited. + if (!config.group.has_value()) { + vst_host.terminate(); + } // The `stop()` method will cause the IO context to just drop all of // its work immediately and not throw any exceptions that would have @@ -634,6 +609,45 @@ void PluginBridge::async_log_pipe_lines(patched_async_pipe& pipe, }); } +void PluginBridge::launch_vst_host() { + // TODO: Connect to and launch group host processes + +#ifndef USE_WINEDBG + std::vector args{vst_host_path.string()}; +#else + // This is set up for KDE Plasma. Other desktop environments and window + // managers require some slight modifications to spawn a detached terminal + // emulator. + std::vector args{"/usr/bin/kstart5", + "konsole", + "--", + "-e", + "winedbg", + "--gdb", + vst_host_path.string() + ".so"}; +#endif + +#ifndef USE_WINEDBG + args.push_back(vst_plugin_path.string()); + const fs::path starting_dir = fs::current_path(); +#else + // winedbg has no reliable way to escape spaces, so we'll start the process + // in the plugin's directory + args.push_back(vst_plugin_path.filename().string()); + const fs::path starting_dir = vst_plugin_path.parent_path(); + + if (vst_plugin_path.filename().string().find(' ') != std::string::npos) { + logger.log("Warning: winedbg does not support paths containing spaces"); + } +#endif + + args.push_back(socket_endpoint.path()); + + vst_host = + bp::child(args, bp::env = set_wineprefix(), bp::std_out = wine_stdout, + bp::std_err = wine_stderr, bp::start_dir = starting_dir); +} + void PluginBridge::log_init_message() { std::stringstream init_msg; diff --git a/src/plugin/plugin-bridge.h b/src/plugin/plugin-bridge.h index d26aff36..e42787b1 100644 --- a/src/plugin/plugin-bridge.h +++ b/src/plugin/plugin-bridge.h @@ -109,6 +109,19 @@ class PluginBridge { boost::asio::streambuf& buffer, std::string prefix = ""); + /** + * Launch the Wine VST host to host the plugin. When using plugin groups, + * this will first try to connect to the plugin group's socket (determined + * based on group name, Wine prefix and architecture). If that fails, it + * will launch a new, detached group host process. This will likely outlive + * this plugin instance if multiple instances of yabridge using the same + * plugin group are in use. In the event that two yabridge instances are + * initialized at the same time and both instances spawn their own group + * host process, then the later one will simply terminate gracefully after + * it fails to listen on the socket. + */ + void launch_vst_host(); + /** * Format and log all relevant debug information during initialization. */ @@ -217,6 +230,8 @@ class PluginBridge { /** * The Wine process hosting the Windows VST plugin. + * + * @see launch_vst_host */ boost::process::child vst_host;