mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29: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'])
|
boost_dep = dependency('boost', modules : ['filesystem'])
|
||||||
msgpack_dep = dependency('msgpack')
|
msgpack_dep = dependency('msgpack')
|
||||||
|
threads_dep = dependency('threads')
|
||||||
|
|
||||||
include_dir = include_directories('src/include')
|
include_dir = include_directories('src/include')
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ shared_library(
|
|||||||
],
|
],
|
||||||
native : true,
|
native : true,
|
||||||
include_directories : include_dir,
|
include_directories : include_dir,
|
||||||
dependencies : [boost_dep, msgpack_dep],
|
dependencies : [boost_dep, msgpack_dep, threads_dep],
|
||||||
link_args : ['-ldl']
|
link_args : ['-ldl']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+66
-2
@@ -38,18 +38,30 @@ namespace fs = boost::filesystem;
|
|||||||
*/
|
*/
|
||||||
constexpr auto yabridge_wine_host_name = "yabridge-host.exe";
|
constexpr auto yabridge_wine_host_name = "yabridge-host.exe";
|
||||||
|
|
||||||
|
fs::path find_vst_plugin();
|
||||||
fs::path find_wine_vst_host();
|
fs::path find_wine_vst_host();
|
||||||
|
fs::path generate_endpoint_name();
|
||||||
bp::environment set_wineprefix();
|
bp::environment set_wineprefix();
|
||||||
|
|
||||||
// TODO: When adding debug information, print both the path to the VST host and
|
// TODO: When adding debug information, print both the path to the VST host and
|
||||||
// the chosen wineprefix
|
// the chosen wineprefix
|
||||||
Bridge::Bridge()
|
Bridge::Bridge()
|
||||||
: vst_stdin(),
|
: io_context(),
|
||||||
|
socket_endpoint(generate_endpoint_name().string()),
|
||||||
|
host_vst_dispatch(io_context),
|
||||||
|
vst_stdin(),
|
||||||
vst_stdout(),
|
vst_stdout(),
|
||||||
vst_host(find_wine_vst_host(),
|
vst_host(find_wine_vst_host(),
|
||||||
bp::std_in = vst_stdin,
|
bp::std_in = vst_stdin,
|
||||||
bp::std_out = vst_stdout,
|
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
|
* 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;
|
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.
|
* 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
|
* This way it's also possible to run .dll files outside of a wineprefix using
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <vestige/aeffect.h>
|
#include <vestige/aeffect.h>
|
||||||
|
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/local/stream_protocol.hpp>
|
||||||
#include <boost/process/child.hpp>
|
#include <boost/process/child.hpp>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +62,15 @@ class Bridge {
|
|||||||
float get_parameter(AEffect* plugin, int32_t index);
|
float get_parameter(AEffect* plugin, int32_t index);
|
||||||
|
|
||||||
private:
|
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::opstream vst_stdin;
|
||||||
boost::process::ipstream vst_stdout;
|
boost::process::ipstream vst_stdout;
|
||||||
boost::process::child vst_host;
|
boost::process::child vst_host;
|
||||||
|
|||||||
Reference in New Issue
Block a user