Pass through the plugin's AEffect struct

This commit is contained in:
Robbert van der Helm
2020-03-05 14:52:02 +01:00
parent 8f34947307
commit 4f29a98cea
5 changed files with 106 additions and 73 deletions
+68 -6
View File
@@ -49,14 +49,29 @@ fs::path find_wine_vst_host();
fs::path generate_endpoint_name();
bp::environment set_wineprefix();
intptr_t dispatch_proxy(AEffect*, int32_t, int32_t, intptr_t, void*, float);
void process_proxy(AEffect*, float**, float**, int32_t);
void setParameter_proxy(AEffect*, int32_t, float);
float getParameter_proxy(AEffect*, int32_t);
/**
* Fetch the bridge instance stored in an unused pointer from a VST plugin. This
* is sadly needed as a workaround to avoid using globals since we need free
* function pointers to interface with the VST C API.
*/
HostBridge& get_bridge_instance(const AEffect& plugin) {
return *static_cast<HostBridge*>(plugin.ptr3);
}
// TODO: When adding debug information, print both the path to the VST host and
// the chosen wineprefix
HostBridge::HostBridge(AEffect* plugin, audioMasterCallback host_callback)
HostBridge::HostBridge(audioMasterCallback host_callback)
: io_context(),
socket_endpoint(generate_endpoint_name().string()),
socket_acceptor(io_context, socket_endpoint),
host_vst_dispatch(io_context),
vst_host_callback(io_context),
vst_host_aeffect(io_context),
host_callback_function(host_callback),
vst_host(find_wine_vst_host(),
// The Wine VST host needs to know which plugin to load and
@@ -68,10 +83,28 @@ HostBridge::HostBridge(AEffect* plugin, audioMasterCallback host_callback)
// in the Wine VST host
socket_acceptor.accept(host_vst_dispatch);
socket_acceptor.accept(vst_host_callback);
socket_acceptor.accept(vst_host_aeffect);
// TODO: REmove
// After accepting the sockets
removeme = std::thread([&]() { return host_callback_loop(plugin); });
// Set up all pointers for our `AEffect` struct. We will fill this with data
// from the VST plugin loaded in Wine at the end of this constructor.
plugin.ptr3 = this;
plugin.dispatcher = dispatch_proxy;
plugin.process = process_proxy;
plugin.setParameter = setParameter_proxy;
plugin.getParameter = getParameter_proxy;
// TODO: Add processReplacing
// TODO: Replace manual thread creation with an async_read loop
// Start accepting host callbacks after we've set up our sockets and basic
// `AEffect` struct.
removeme = std::thread([&]() { return host_callback_loop(); });
// Read the plugin's information from the Wine process. This can only be
// done after we started accepting host callbacks as the plugin might do
// this during initialization.
// XXX: If the plugin has crashed then this read should fail instead of
// blocking indefinitely, check if this is the case
plugin = read_object(vst_host_aeffect, plugin);
}
/**
@@ -223,9 +256,9 @@ fs::path generate_endpoint_name() {
// 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 HostBridge::host_callback_loop(AEffect* plugin) {
void HostBridge::host_callback_loop() {
while (true) {
passthrough_event(vst_host_callback, plugin, host_callback_function);
passthrough_event(vst_host_callback, &plugin, host_callback_function);
}
}
@@ -252,3 +285,32 @@ bp::environment set_wineprefix() {
return env;
}
// The below functions are proxy functions for the methods defined in
// `Bridge.cpp`
intptr_t dispatch_proxy(AEffect* plugin,
int32_t opcode,
int32_t index,
intptr_t value,
void* data,
float option) {
return get_bridge_instance(*plugin).dispatch(plugin, opcode, index, value,
data, option);
}
void process_proxy(AEffect* plugin,
float** inputs,
float** outputs,
int32_t sample_frames) {
return get_bridge_instance(*plugin).process(plugin, inputs, outputs,
sample_frames);
}
void setParameter_proxy(AEffect* plugin, int32_t index, float value) {
return get_bridge_instance(*plugin).set_parameter(plugin, index, value);
}
float getParameter_proxy(AEffect* plugin, int32_t index) {
return get_bridge_instance(*plugin).get_parameter(plugin, index);
}