Only perform mutual recursion from the GUI thread

JUCE incorrectly calls `IComponentHandler::performEdit()` from the audio
thread instead of using the output parameter changes queue, so this
would also cause GUI resizes to be handled from the audio thread if they
come in at the same time as such a parameter change.
This commit is contained in:
Robbert van der Helm
2021-07-10 14:30:52 +02:00
parent 04a8be6cc6
commit 3c94ee7049
2 changed files with 23 additions and 3 deletions
+5
View File
@@ -59,6 +59,11 @@ Versioning](https://semver.org/spec/v2.0.0.html).
plugins would at runtime change their query interface to support more VST3
interfaces, including the required edit controller interface. Yabridge now
requeries the supported interfaces at a later stage to work around this.
- Fixed JUCE plugins like Tokyo Dawn Records' **SlickEQ M** causing the host to
freeze when they send a parameter change from the audio thread using the wrong
VST3 API while at the same time the host is trying to resize the window. This
would happen in this particular plugin when reopning the Smart Ops panel after
having used it once.
- Fixed missing transport information for VST2 plugins in **Ardour**, breaking
host sync and LFOs in certain plugins. This was a regression from yabridge
3.2.0.
+18 -3
View File
@@ -294,8 +294,9 @@ class Vst3Bridge : public HostBridge {
}
/**
* Spawn a new thread and call `send_message()` from there, and then handle
* functions passed by calls to `do_mutual_recursion_on_gui_thread()` and
* When called form the GUI thread, spawn a new thread and call
* `send_message()` from there, and then handle functions passed by calls to
* `do_mutual_recursion_on_gui_thread()` and
* `do_mutual_recursion_on_off_thread()` on this thread until we get a
* response back. This is a very specific solution to a very specific
* problem. When a plugin wants to resize itself, it will call
@@ -316,10 +317,24 @@ class Vst3Bridge : public HostBridge {
* context.
*
* We apply the same trick in `Vst3HostBridge`.
*
* NOTE: This is meant to allow mutually recursive call chains where every
* function is called from and handled on the GUI thread. JUCE calls
* `IComponentHandler::performEdit` from the audio thread because they
* didn't implement the VST3 output parameters, and if at the same
* time a resize request comes in from the host that would mean that
* the resize request is also called from the audio thread. To prevent
* this we will make sure to only do this mutual recursion stuff if
* this is actually called form the GUI thread.
*/
template <typename T>
typename T::Response send_mutually_recursive_message(const T& object) {
return mutual_recursion.fork([&]() { return send_message(object); });
if (main_context.is_gui_thread()) {
return mutual_recursion.fork(
[&]() { return send_message(object); });
} else {
return send_message(object);
}
}
/**