mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-06 19:40:10 +02:00
Add a Unix domain socket for host->vst events
This commit is contained in:
+2
-1
@@ -22,6 +22,7 @@ endif
|
||||
|
||||
boost_dep = dependency('boost', modules : ['filesystem'])
|
||||
msgpack_dep = dependency('msgpack')
|
||||
threads_dep = dependency('threads')
|
||||
|
||||
include_dir = include_directories('src/include')
|
||||
|
||||
@@ -33,7 +34,7 @@ shared_library(
|
||||
],
|
||||
native : true,
|
||||
include_directories : include_dir,
|
||||
dependencies : [boost_dep, msgpack_dep],
|
||||
dependencies : [boost_dep, msgpack_dep, threads_dep],
|
||||
link_args : ['-ldl']
|
||||
)
|
||||
|
||||
|
||||
+66
-2
@@ -38,18 +38,30 @@ namespace fs = boost::filesystem;
|
||||
*/
|
||||
constexpr auto yabridge_wine_host_name = "yabridge-host.exe";
|
||||
|
||||
fs::path find_vst_plugin();
|
||||
fs::path find_wine_vst_host();
|
||||
fs::path generate_endpoint_name();
|
||||
bp::environment set_wineprefix();
|
||||
|
||||
// TODO: When adding debug information, print both the path to the VST host and
|
||||
// the chosen wineprefix
|
||||
Bridge::Bridge()
|
||||
: vst_stdin(),
|
||||
: io_context(),
|
||||
socket_endpoint(generate_endpoint_name().string()),
|
||||
host_vst_dispatch(io_context),
|
||||
vst_stdin(),
|
||||
vst_stdout(),
|
||||
vst_host(find_wine_vst_host(),
|
||||
bp::std_in = vst_stdin,
|
||||
bp::std_out = vst_stdout,
|
||||
bp::env = set_wineprefix()) {}
|
||||
bp::env = set_wineprefix()) {
|
||||
boost::asio::local::stream_protocol::acceptor acceptor(io_context,
|
||||
socket_endpoint);
|
||||
|
||||
// It's very important that these sockets are connected to in the same order
|
||||
// in the Wine VST host
|
||||
acceptor.accept(host_vst_dispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an event sent by the VST host. Most of these opcodes will be passed
|
||||
@@ -140,6 +152,58 @@ fs::path find_wine_vst_host() {
|
||||
return vst_host_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the VST plugin .dll file that corresponds to this copy of
|
||||
* `libyabridge.so`. This should be the same as the name of this file but with a
|
||||
* `.dll` file extension instead of `.so`.
|
||||
*
|
||||
* @return The a path to the accompanying VST plugin .dll file.
|
||||
* @throw std::runtime_error If no matching .dll file could be found.
|
||||
*/
|
||||
fs::path find_vst_plugin() {
|
||||
fs::path plugin_path = boost::dll::this_line_location();
|
||||
plugin_path.replace_extension(".dll");
|
||||
|
||||
// This function is used in the constructor's initializer list so we have to
|
||||
// throw when the path could not be found
|
||||
if (!fs::exists(plugin_path)) {
|
||||
throw std::runtime_error(
|
||||
"'" + plugin_path.string() +
|
||||
"' does not exist, make sure to rename 'libyabridge.so' to match a "
|
||||
"VST plugin .dll file.");
|
||||
}
|
||||
|
||||
return plugin_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique name for the Unix domain socket endpoint based on the VST
|
||||
* plugin's name.
|
||||
*
|
||||
* @return A path to a not yet existing Unix domain socket endpoint.
|
||||
* @throw std::runtime_error If no matching .dll file could be found.
|
||||
*/
|
||||
fs::path generate_endpoint_name() {
|
||||
auto plugin_name =
|
||||
find_vst_plugin().filename().replace_extension("").string();
|
||||
|
||||
fs::path candidate_endpoint;
|
||||
do {
|
||||
std::string random_id("TODO");
|
||||
candidate_endpoint =
|
||||
fs::temp_directory_path()
|
||||
.append("yabridge")
|
||||
.append(plugin_name + "-" + random_id + ".sock");
|
||||
} while (fs::exists(candidate_endpoint));
|
||||
|
||||
// TODO: Should probably try creating the endpoint right here and catch any
|
||||
// exceptions since this could technically result in a race condition
|
||||
// when two instances of yabridge decide to use the same endpoint name
|
||||
// at the same time
|
||||
|
||||
return candidate_endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the wineprefix and set the `WINEPREFIX` environment variable if found.
|
||||
* This way it's also possible to run .dll files outside of a wineprefix using
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <vestige/aeffect.h>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/local/stream_protocol.hpp>
|
||||
#include <boost/process/child.hpp>
|
||||
|
||||
/**
|
||||
@@ -60,6 +62,15 @@ class Bridge {
|
||||
float get_parameter(AEffect* plugin, int32_t index);
|
||||
|
||||
private:
|
||||
boost::asio::io_context io_context;
|
||||
boost::asio::local::stream_protocol::endpoint socket_endpoint;
|
||||
|
||||
// The naming convention for these sockets is `<from>_<to>_<event>`. For
|
||||
// instance the socket named `host_vst_dispatch` forwards
|
||||
// `AEffect.dispatch()` calls from the native VST host to the Windows VST
|
||||
// plugin (through the Wine VST host).
|
||||
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
||||
|
||||
boost::process::opstream vst_stdin;
|
||||
boost::process::ipstream vst_stdout;
|
||||
boost::process::child vst_host;
|
||||
|
||||
Reference in New Issue
Block a user