mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-09 20:29:10 +02:00
Always run the event loop, fixing processing issue
Also remove any special `effEditIdle` handling. Apparently plugins rely on the message loop for their internal tasks, even for things that have nothing to do with GUIs, such as deferring initialization.
This commit is contained in:
@@ -12,8 +12,6 @@ There are a few things that should be done before releasing this, including:
|
|||||||
- Fix implementation bugs:
|
- Fix implementation bugs:
|
||||||
- Serum crashed and audio engine froze while browsing through Serum presets in
|
- Serum crashed and audio engine froze while browsing through Serum presets in
|
||||||
the browser?
|
the browser?
|
||||||
- Plugins from certain manufacturers, such as KiloHearts or Image-Line, don't
|
|
||||||
do any audio processing until the editor has been opened.
|
|
||||||
- KiloHearts plugins create a ridiculous amount of file descriptor leaks in
|
- KiloHearts plugins create a ridiculous amount of file descriptor leaks in
|
||||||
wineserver when esync is enabled. I haven't come across any other plugins
|
wineserver when esync is enabled. I haven't come across any other plugins
|
||||||
that do this. Not sure if this is fixable in yabridge.
|
that do this. Not sure if this is fixable in yabridge.
|
||||||
|
|||||||
@@ -131,18 +131,18 @@ void Editor::send_idle_event() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Editor::handle_events() {
|
void Editor::handle_events() {
|
||||||
send_idle_event();
|
MSG msg;
|
||||||
|
|
||||||
// The null value for the second argument is needed to handle interaction
|
// The null value for the second argument is needed to handle interaction
|
||||||
// with child GUI components
|
// with child GUI components
|
||||||
MSG msg;
|
|
||||||
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||||
// This timer would periodically send `effEditIdle` events so the editor
|
// This timer would periodically send `effEditIdle` events so the editor
|
||||||
// remains responsive even during blocking GUI operations such as open
|
// remains responsive even during blocking GUI operations such as open
|
||||||
// dropdowns or message boxes. We filter it out here because we will
|
// dropdowns or message boxes. This is only needed when the GUI is
|
||||||
// send sent the event manually every time the host calls
|
// actually blocked and it will be dispatched by the messaging loop of
|
||||||
// `effEditIdle()`. It will still be fired implicitely when the GUI
|
// the blocking GUI component. Since we're not touching the
|
||||||
// thread gets blocked.
|
// `effEditIdle` event sent by the host we can always filter this timer
|
||||||
|
// event out in this event loop.
|
||||||
if (msg.message == WM_TIMER && msg.wParam == idle_timer_id &&
|
if (msg.message == WM_TIMER && msg.wParam == idle_timer_id &&
|
||||||
msg.hwnd == win32_handle.get()) {
|
msg.hwnd == win32_handle.get()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -201,6 +201,7 @@ void Editor::handle_events() {
|
|||||||
xcb_flush(x11_connection.get());
|
xcb_flush(x11_connection.get());
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(generic_event);
|
free(generic_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,14 +88,14 @@ class Editor {
|
|||||||
/**
|
/**
|
||||||
* Send a single `effEditIdle` event to the plugin to allow it to update its
|
* Send a single `effEditIdle` event to the plugin to allow it to update its
|
||||||
* GUI state. This is called periodically from a timer while the GUI is
|
* GUI state. This is called periodically from a timer while the GUI is
|
||||||
* being blocked.
|
* being blocked, and also called explicitly by the host on a timer.
|
||||||
*/
|
*/
|
||||||
void send_idle_event();
|
void send_idle_event();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pump messages from the editor GUI's event loop until all events are
|
* Pump messages from the editor GUI's event loop until all events are
|
||||||
* process. Must be run from the same thread the GUI was created in because
|
* process. Must be run from the same thread the GUI was created in because
|
||||||
* of Win32 limitations. I guess that's what `effEditIdle` is for.
|
* of Win32 limitations.
|
||||||
*/
|
*/
|
||||||
void handle_events();
|
void handle_events();
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,26 @@ void PluginBridge::handle_dispatch() {
|
|||||||
passthrough_event(host_vst_dispatch, std::nullopt, plugin,
|
passthrough_event(host_vst_dispatch, std::nullopt, plugin,
|
||||||
std::bind(&PluginBridge::dispatch_wrapper, this,
|
std::bind(&PluginBridge::dispatch_wrapper, this,
|
||||||
_1, _2, _3, _4, _5, _6));
|
_1, _2, _3, _4, _5, _6));
|
||||||
|
|
||||||
|
// Because of the way the Win32 API works we have to process events
|
||||||
|
// on the same thread as the one the window was created on, and that
|
||||||
|
// thread is the thread that's handling dispatcher calls.
|
||||||
|
if (editor.has_value()) {
|
||||||
|
// This will handle Win32 events similar to the loop below, and
|
||||||
|
// it will also handle any X11 events.
|
||||||
|
editor->handle_events();
|
||||||
|
} else {
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
// Since some plugins rely on the Win32 message API even for
|
||||||
|
// non-editor related tasks (such as deferring the loading of
|
||||||
|
// presets using a timer), we have to run a message loop even
|
||||||
|
// when the editor is closed.
|
||||||
|
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (const boost::system::system_error&) {
|
} catch (const boost::system::system_error&) {
|
||||||
// The plugin has cut off communications, so we can shut down this host
|
// The plugin has cut off communications, so we can shut down this host
|
||||||
@@ -286,17 +306,6 @@ intptr_t PluginBridge::dispatch_wrapper(AEffect* plugin,
|
|||||||
// We have to intercept GUI open calls since we can't use
|
// We have to intercept GUI open calls since we can't use
|
||||||
// the X11 window handle passed by the host
|
// the X11 window handle passed by the host
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case effEditIdle:
|
|
||||||
// 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
|
|
||||||
// thread that's handling dispatcher calls
|
|
||||||
// To allow the GUI to update even when this thread gets blocked
|
|
||||||
// (e.g. when a dropdown is open), the actual `effEditIdle` event
|
|
||||||
// gets sent to the plugin on a timer.
|
|
||||||
editor->handle_events();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
case effEditOpen: {
|
case effEditOpen: {
|
||||||
// Create a Win32 window through Wine, embed it into the window
|
// Create a Win32 window through Wine, embed it into the window
|
||||||
// provided by the host, and let the plugin embed itself into the
|
// provided by the host, and let the plugin embed itself into the
|
||||||
|
|||||||
Reference in New Issue
Block a user