mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Handle all dispatch calls from the main thread
Some plugins apparently assume that all events (or at least some specific ones) are sent from the thread it was created on and will segfault otherwise. The is the case for Melda plugins.
This commit is contained in:
@@ -118,19 +118,6 @@ PluginBridge::PluginBridge(std::string plugin_dll_path,
|
||||
current_bridge_isntance = nullptr;
|
||||
plugin->ptr1 = this;
|
||||
|
||||
// For our communication we use simple threads and blocking operations
|
||||
// instead of asynchronous IO since communication has to be handled in
|
||||
// lockstep anyway
|
||||
dispatch_handler = std::thread([&]() {
|
||||
using namespace std::placeholders;
|
||||
|
||||
while (true) {
|
||||
passthrough_event(host_vst_dispatch, std::nullopt, plugin,
|
||||
std::bind(&PluginBridge::dispatch_wrapper, this,
|
||||
_1, _2, _3, _4, _5, _6));
|
||||
}
|
||||
});
|
||||
|
||||
parameters_handler = std::thread([&]() {
|
||||
while (true) {
|
||||
// Both `getParameter` and `setParameter` functions are passed
|
||||
@@ -189,6 +176,26 @@ PluginBridge::PluginBridge(std::string plugin_dll_path,
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void PluginBridge::handle_dispatch() {
|
||||
using namespace std::placeholders;
|
||||
|
||||
// For our communication we use simple threads and blocking operations
|
||||
// instead of asynchronous IO since communication has to be handled in
|
||||
// lockstep anyway
|
||||
try {
|
||||
while (true) {
|
||||
passthrough_event(host_vst_dispatch, std::nullopt, plugin,
|
||||
std::bind(&PluginBridge::dispatch_wrapper, this,
|
||||
_1, _2, _3, _4, _5, _6));
|
||||
}
|
||||
} catch (const boost::system::system_error&) {
|
||||
// This happens when the sockets got closed because the plugin is being
|
||||
// shut down. In that case we can just let the whole host terminate.
|
||||
parameters_handler.detach();
|
||||
process_replacing_handler.detach();
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin,
|
||||
int opcode,
|
||||
int index,
|
||||
@@ -199,9 +206,9 @@ intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin,
|
||||
// the X11 window handle passed by the host
|
||||
switch (opcode) {
|
||||
case effEditIdle:
|
||||
// Because of the way the Win32 APi works we have to process events
|
||||
// Because of the way the Win32 API works we have to process events
|
||||
// on the same thread the window was created, and that thread is the
|
||||
// `dispatch_handler` thread
|
||||
// thread that's handling dispatcher calls
|
||||
editor.handle_events();
|
||||
|
||||
return plugin->dispatcher(plugin, opcode, index, value, data,
|
||||
@@ -261,12 +268,6 @@ intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin,
|
||||
}
|
||||
}
|
||||
|
||||
void PluginBridge::wait() {
|
||||
dispatch_handler.join();
|
||||
parameters_handler.join();
|
||||
process_replacing_handler.join();
|
||||
}
|
||||
|
||||
class HostCallbackDataConverter : DefaultDataConverter {
|
||||
public:
|
||||
HostCallbackDataConverter(AEffect* plugin,
|
||||
|
||||
@@ -55,9 +55,13 @@ class PluginBridge {
|
||||
PluginBridge(std::string plugin_dll_path, std::string socket_endpoint_path);
|
||||
|
||||
/**
|
||||
* Block the main thread until the plugin shuts down.
|
||||
* Handle events on the main thread until the plugin quits. This can't be
|
||||
* done on another thread since some plugins (e.g. Melda) expect certain
|
||||
* (but for some reason not all) events to be passed from the same thread it
|
||||
* was initiated from. This is then also the same thread that should handle
|
||||
* Win32 GUI events.
|
||||
*/
|
||||
void wait();
|
||||
void handle_dispatch();
|
||||
|
||||
intptr_t host_callback(AEffect*, int, int, intptr_t, void*, float);
|
||||
|
||||
@@ -115,10 +119,6 @@ class PluginBridge {
|
||||
*/
|
||||
boost::asio::local::stream_protocol::socket vst_host_aeffect;
|
||||
|
||||
/**
|
||||
* The thread that handles dispatch events from the host.
|
||||
*/
|
||||
std::thread dispatch_handler;
|
||||
/**
|
||||
* The thread that responds to `getParameter` and `setParameter` requests.
|
||||
*/
|
||||
|
||||
@@ -35,8 +35,8 @@ int main(int argc, char* argv[]) {
|
||||
try {
|
||||
PluginBridge bridge(plugin_dll_path, socket_endpoint_path);
|
||||
|
||||
// Block the main thread until the plugin shuts down
|
||||
bridge.wait();
|
||||
// Blocks the main thread until the plugin shuts down
|
||||
bridge.handle_dispatch();
|
||||
} catch (const std::runtime_error& error) {
|
||||
std::cerr << "Error while initializing Wine VST host:" << std::endl;
|
||||
std::cerr << error.what() << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user