mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Pass callbacks back through to the host
Instead of using std::thread this can be done cleaner using recursive async read functions. Everything withing those functions should of course still remain synchronous.
This commit is contained in:
+19
-3
@@ -51,20 +51,27 @@ 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(AEffect* plugin, audioMasterCallback host_callback)
|
||||||
: io_context(),
|
: io_context(),
|
||||||
socket_endpoint(generate_endpoint_name().string()),
|
socket_endpoint(generate_endpoint_name().string()),
|
||||||
socket_acceptor(io_context, socket_endpoint),
|
socket_acceptor(io_context, socket_endpoint),
|
||||||
host_vst_dispatch(io_context),
|
host_vst_dispatch(io_context),
|
||||||
|
vst_host_callback(io_context),
|
||||||
|
host_callback_function(host_callback),
|
||||||
vst_host(find_wine_vst_host(),
|
vst_host(find_wine_vst_host(),
|
||||||
// The Wine VST host needs to know which plugin to load and which
|
// The Wine VST host needs to know which plugin to load and
|
||||||
// Unix domain socket to connect to
|
// which Unix domain socket to connect to
|
||||||
find_vst_plugin(),
|
find_vst_plugin(),
|
||||||
socket_endpoint.path(),
|
socket_endpoint.path(),
|
||||||
bp::env = set_wineprefix()) {
|
bp::env = set_wineprefix()) {
|
||||||
// It's very important that these sockets are connected to in the same order
|
// It's very important that these sockets are connected to in the same order
|
||||||
// in the Wine VST host
|
// in the Wine VST host
|
||||||
socket_acceptor.accept(host_vst_dispatch);
|
socket_acceptor.accept(host_vst_dispatch);
|
||||||
|
socket_acceptor.accept(vst_host_callback);
|
||||||
|
|
||||||
|
// TODO: REmove
|
||||||
|
// After accepting the sockets
|
||||||
|
removeme = std::thread([&]() { return host_callback_loop(plugin); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,6 +220,15 @@ fs::path generate_endpoint_name() {
|
|||||||
return candidate_endpoint;
|
return candidate_endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Replace blocking loop with async readers or threads for all of the
|
||||||
|
// sockets. Also extract this functionality somewhere since the host event
|
||||||
|
// callback needs to do exactly the same thing.
|
||||||
|
void Bridge::host_callback_loop(AEffect* plugin) {
|
||||||
|
while (true) {
|
||||||
|
passthrough_event(vst_host_callback, plugin, host_callback_function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|||||||
+20
-1
@@ -21,6 +21,8 @@
|
|||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/local/stream_protocol.hpp>
|
#include <boost/asio/local/stream_protocol.hpp>
|
||||||
#include <boost/process/child.hpp>
|
#include <boost/process/child.hpp>
|
||||||
|
// TODO: Remove
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This handles the communication between the Linux native VST plugin and the
|
* This handles the communication between the Linux native VST plugin and the
|
||||||
@@ -36,10 +38,14 @@ class Bridge {
|
|||||||
* TODO: Figure out whether shared memory gives us better throughput and/or
|
* TODO: Figure out whether shared memory gives us better throughput and/or
|
||||||
* lower overhead than using a Unix domain socket would.
|
* lower overhead than using a Unix domain socket would.
|
||||||
*
|
*
|
||||||
|
* @param host_callback The callback function passed to the VST plugin by
|
||||||
|
* the host.
|
||||||
|
*
|
||||||
* @throw std::runtime_error Thrown when the VST host could not be found, or
|
* @throw std::runtime_error Thrown when the VST host could not be found, or
|
||||||
* if it could not locate and load a VST .dll file.
|
* if it could not locate and load a VST .dll file.
|
||||||
*/
|
*/
|
||||||
Bridge();
|
// TODO: The plugin struct should be created here, not passed in
|
||||||
|
Bridge(AEffect* plugin, audioMasterCallback host_callback);
|
||||||
|
|
||||||
// The four below functions are the handlers from the VST2 API. They are
|
// The four below functions are the handlers from the VST2 API. They are
|
||||||
// called through proxy functions in `plugin.cpp`.
|
// called through proxy functions in `plugin.cpp`.
|
||||||
@@ -61,6 +67,9 @@ class Bridge {
|
|||||||
void set_parameter(AEffect* plugin, int32_t index, float value);
|
void set_parameter(AEffect* plugin, int32_t index, float value);
|
||||||
float get_parameter(AEffect* plugin, int32_t index);
|
float get_parameter(AEffect* plugin, int32_t index);
|
||||||
|
|
||||||
|
// TODO: Remove debug loop
|
||||||
|
void host_callback_loop(AEffect* plugin);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::asio::io_context io_context;
|
boost::asio::io_context io_context;
|
||||||
boost::asio::local::stream_protocol::endpoint socket_endpoint;
|
boost::asio::local::stream_protocol::endpoint socket_endpoint;
|
||||||
@@ -71,6 +80,16 @@ class Bridge {
|
|||||||
// `AEffect.dispatch()` calls from the native VST host to the Windows VST
|
// `AEffect.dispatch()` calls from the native VST host to the Windows VST
|
||||||
// plugin (through the Wine VST host).
|
// plugin (through the Wine VST host).
|
||||||
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
||||||
|
boost::asio::local::stream_protocol::socket vst_host_callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback function passed by the host to the VST plugin instance.
|
||||||
|
*/
|
||||||
|
audioMasterCallback host_callback_function;
|
||||||
|
// TODO: Remove
|
||||||
|
std::thread removeme;
|
||||||
|
/**
|
||||||
|
* The Wine process hosting the Windows VST plugin.
|
||||||
|
*/
|
||||||
boost::process::child vst_host;
|
boost::process::child vst_host;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,11 +61,13 @@ Bridge& get_bridge_instance(const AEffect& plugin) {
|
|||||||
* manual memory management. Clean up is done when we receive the `effClose`
|
* manual memory management. Clean up is done when we receive the `effClose`
|
||||||
* opcode from the VST host (i.e. opcode 1).`
|
* opcode from the VST host (i.e. opcode 1).`
|
||||||
*/
|
*/
|
||||||
VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback /*audioMaster*/) {
|
VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback host_callback) {
|
||||||
try {
|
try {
|
||||||
Bridge* bridge = new Bridge();
|
// TODO: Create the plugin instance in the bridge based on the received
|
||||||
|
// parameters. We can then also use a smart pointer so we only
|
||||||
|
// have to manually delete the bridge instance.
|
||||||
AEffect* plugin = new AEffect();
|
AEffect* plugin = new AEffect();
|
||||||
|
Bridge* bridge = new Bridge(plugin, host_callback);
|
||||||
plugin->ptr3 = bridge;
|
plugin->ptr3 = bridge;
|
||||||
|
|
||||||
plugin->dispatcher = dispatch_proxy;
|
plugin->dispatcher = dispatch_proxy;
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ Bridge::Bridge(std::string plugin_dll_path, std::string socket_endpoint_path)
|
|||||||
: plugin_handle(LoadLibrary(plugin_dll_path.c_str()), &FreeLibrary),
|
: plugin_handle(LoadLibrary(plugin_dll_path.c_str()), &FreeLibrary),
|
||||||
io_context(),
|
io_context(),
|
||||||
socket_endpoint(socket_endpoint_path),
|
socket_endpoint(socket_endpoint_path),
|
||||||
host_vst_dispatch(io_context) {
|
host_vst_dispatch(io_context),
|
||||||
|
vst_host_callback(io_context) {
|
||||||
// Got to love these C APIs
|
// Got to love these C APIs
|
||||||
if (plugin_handle == nullptr) {
|
if (plugin_handle == nullptr) {
|
||||||
throw std::runtime_error("Could not load a shared library at '" +
|
throw std::runtime_error("Could not load a shared library at '" +
|
||||||
@@ -63,7 +64,10 @@ Bridge::Bridge(std::string plugin_dll_path, std::string socket_endpoint_path)
|
|||||||
"'.");
|
"'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It's very important that these sockets are accepted to in the same order
|
||||||
|
// in the Linus plugin
|
||||||
host_vst_dispatch.connect(socket_endpoint);
|
host_vst_dispatch.connect(socket_endpoint);
|
||||||
|
vst_host_callback.connect(socket_endpoint);
|
||||||
|
|
||||||
// Initialize after communication has been set up We'll try to do the same
|
// Initialize after communication has been set up We'll try to do the same
|
||||||
// `get_bridge_isntance` trick as in `plugin/plugin.cpp`, but since the
|
// `get_bridge_isntance` trick as in `plugin/plugin.cpp`, but since the
|
||||||
@@ -90,14 +94,13 @@ void Bridge::dispatch_loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t Bridge::host_callback(AEffect* plugin,
|
intptr_t Bridge::host_callback(AEffect* /*plugin*/,
|
||||||
int32_t opcode,
|
int32_t opcode,
|
||||||
int32_t index,
|
int32_t index,
|
||||||
intptr_t value,
|
intptr_t value,
|
||||||
void* data,
|
void* data,
|
||||||
float option) {
|
float option) {
|
||||||
// TODO
|
return send_event(vst_host_callback, opcode, index, value, data, option);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t VST_CALL_CONV host_callback_proxy(AEffect* effect,
|
intptr_t VST_CALL_CONV host_callback_proxy(AEffect* effect,
|
||||||
|
|||||||
@@ -74,4 +74,5 @@ class Bridge {
|
|||||||
// `AEffect.dispatch()` calls from the native VST host to the Windows VST
|
// `AEffect.dispatch()` calls from the native VST host to the Windows VST
|
||||||
// plugin (through the Wine VST host).
|
// plugin (through the Wine VST host).
|
||||||
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
||||||
|
boost::asio::local::stream_protocol::socket vst_host_callback;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user