mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-14 12:30:00 +02:00
Skip event loop with partially initialized plugins
This should prevent T-RackS 5 from potentially stalling indefinitely when using plugin groups.
This commit is contained in:
+26
-29
@@ -41,20 +41,6 @@
|
||||
* which can be required because in the Win32 model all GUI related operations
|
||||
* have to be handled from the same thread. This will be run from the
|
||||
* application's main thread.
|
||||
*
|
||||
* TODO: Add some point we might have to add some way to inhibit the event loop
|
||||
* from running when a plugin is in a partially initialized state. So far
|
||||
* only the VST2 versions of the T-RackS 5 plugins have this issue (and
|
||||
* only when running them in a plugin group because with individually
|
||||
* hosted plugins the event loop and the plugin's initialization will
|
||||
* align). This will require a fairly significant architectural change to
|
||||
* do this in a clean way (`HostBridge` would need some function that
|
||||
* returns a boolean to indicate whether the event loop should be
|
||||
* inhibited, and then we would need to pass a function object or lambda
|
||||
* to `MainContext` that checks this for all currently hosted plugins so
|
||||
* we can integrate that into `async_handle_events()`). Now that I've
|
||||
* written this out, it's not actually as bad as I thought it would be, so
|
||||
* we'll probably add this sooner rather than later.
|
||||
*/
|
||||
class MainContext {
|
||||
public:
|
||||
@@ -112,33 +98,44 @@ class MainContext {
|
||||
* @param handler The function that should be executed in the IO context
|
||||
* when the timer ticks. This should be a function that handles both the
|
||||
* X11 events and the Win32 message loop.
|
||||
* @param predicate A function returning a boolean to indicate whether
|
||||
* `handler` should be run. If this returns `false`, then the current
|
||||
* event loop cycle will be skipped. This is used to prevent the Win32
|
||||
* message loop from being run when there are partially initialized
|
||||
* plugins. So far the VST2 versions of T-RackS 5 are the only plugins
|
||||
* where this has been an issue as those plugins have a race condition
|
||||
* that will cause them to stall indefinitely in this situation, but who
|
||||
* knows which other plugins exert similar behaviour.
|
||||
*/
|
||||
template <typename F>
|
||||
void async_handle_events(F handler) {
|
||||
template <typename F, typename P>
|
||||
void async_handle_events(F handler, P predicate) {
|
||||
// Try to keep a steady framerate, but add in delays to let other events
|
||||
// get handled if the GUI message handling somehow takes very long.
|
||||
events_timer.expires_at(
|
||||
std::max(events_timer.expiry() + timer_interval,
|
||||
std::chrono::steady_clock::now() + timer_interval / 4));
|
||||
events_timer.async_wait(
|
||||
[&, handler](const boost::system::error_code& error) {
|
||||
[&, handler, predicate](const boost::system::error_code& error) {
|
||||
if (error.failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: These periodic callbacks should not be able to
|
||||
// interrupt other threads that are actively processing
|
||||
// audio. For me personally having the GUI open makes
|
||||
// absolutely zero difference on DSP usage (as it should),
|
||||
// but for some others it does have an impact.
|
||||
// TODO: Benchmark this further on a properly configured system,
|
||||
// see if it does not increase average load because of the
|
||||
// rapid scheduling switching.
|
||||
set_realtime_priority(false);
|
||||
handler();
|
||||
set_realtime_priority(true);
|
||||
if (predicate()) {
|
||||
// NOTE: These periodic callbacks should not be able to
|
||||
// interrupt other threads that are actively
|
||||
// processing audio. For me personally having the GUI
|
||||
// open makes absolutely zero difference on DSP usage
|
||||
// (as it should), but for some others it does have an
|
||||
// impact.
|
||||
// TODO: Benchmark this further on a properly configured
|
||||
// system, see if it does not increase average load
|
||||
// because of the rapid scheduling switching.
|
||||
set_realtime_priority(false);
|
||||
handler();
|
||||
set_realtime_priority(true);
|
||||
}
|
||||
|
||||
async_handle_events(handler);
|
||||
async_handle_events(handler, predicate);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user