mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-06-25 05:17:25 +02:00
Work around thread safety issue in Melda plugins
This is super difficult to trigger on purpose, but I did run into it at least once just now so it seems like a good idea to at least make sure that this doesn't happen.
This commit is contained in:
@@ -80,6 +80,9 @@ Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
tries to use REAPER's [host function
|
tries to use REAPER's [host function
|
||||||
API](https://www.reaper.fm/sdk/vst/vst_ext.php#vst_host). This currently isn't
|
API](https://www.reaper.fm/sdk/vst/vst_ext.php#vst_host). This currently isn't
|
||||||
supported by yabridge. We now explicitly ignore these requests.
|
supported by yabridge. We now explicitly ignore these requests.
|
||||||
|
- Worked around a rare thread safety issue in _MeldaProduction_ VST3 plugins
|
||||||
|
where the plugin would deadlock when the host asks for the editor's size while
|
||||||
|
plugin is also being initialized form the audio thread.
|
||||||
- Fixed JUCE VST3 plugins like Tokyo Dawn Records' _SlickEQ M_ causing the host
|
- Fixed JUCE VST3 plugins like Tokyo Dawn Records' _SlickEQ M_ causing the host
|
||||||
to freeze when they send a parameter change from the audio thread using the
|
to freeze when they send a parameter change from the audio thread using the
|
||||||
wrong VST3 API while the plugin is also trying to resize the window from the
|
wrong VST3 API while the plugin is also trying to resize the window from the
|
||||||
|
|||||||
@@ -800,13 +800,20 @@ void Vst3Bridge::run() {
|
|||||||
.get();
|
.get();
|
||||||
},
|
},
|
||||||
[&](YaPlugView::GetSize& request) -> YaPlugView::GetSize::Response {
|
[&](YaPlugView::GetSize& request) -> YaPlugView::GetSize::Response {
|
||||||
|
Vst3PluginInstance& instance =
|
||||||
|
object_instances.at(request.owner_instance_id);
|
||||||
|
|
||||||
// Melda plugins will refuse to open dialogs of this function is
|
// Melda plugins will refuse to open dialogs of this function is
|
||||||
// not run from the GUI thread
|
// not run from the GUI thread. Oh and they also deadlock if
|
||||||
|
// audio processing gets initialized at the same time as this
|
||||||
|
// function, not sure why.
|
||||||
|
std::lock_guard lock(instance.get_size_mutex);
|
||||||
|
|
||||||
Steinberg::ViewRect size{};
|
Steinberg::ViewRect size{};
|
||||||
const tresult result =
|
const tresult result =
|
||||||
do_mutual_recursion_on_gui_thread([&]() -> tresult {
|
do_mutual_recursion_on_gui_thread([&]() -> tresult {
|
||||||
return object_instances.at(request.owner_instance_id)
|
return instance.plug_view_instance->plug_view->getSize(
|
||||||
.plug_view_instance->plug_view->getSize(&size);
|
&size);
|
||||||
});
|
});
|
||||||
|
|
||||||
return YaPlugView::GetSizeResponse{.result = result,
|
return YaPlugView::GetSizeResponse{.result = result,
|
||||||
@@ -1419,9 +1426,18 @@ size_t Vst3Bridge::register_object_instance(
|
|||||||
},
|
},
|
||||||
[&](const YaAudioProcessor::SetProcessing& request)
|
[&](const YaAudioProcessor::SetProcessing& request)
|
||||||
-> YaAudioProcessor::SetProcessing::Response {
|
-> YaAudioProcessor::SetProcessing::Response {
|
||||||
return object_instances.at(request.instance_id)
|
Vst3PluginInstance& instance =
|
||||||
.interfaces.audio_processor->setProcessing(
|
object_instances.at(request.instance_id);
|
||||||
request.state);
|
|
||||||
|
// HACK: MeldaProduction plugins for some reason cannot
|
||||||
|
// handle it if this function is called from the
|
||||||
|
// audio thread while at the same time
|
||||||
|
// `IPlugView::getSize()` is being called from the
|
||||||
|
// GUI thread
|
||||||
|
std::lock_guard lock(instance.get_size_mutex);
|
||||||
|
|
||||||
|
return instance.interfaces.audio_processor
|
||||||
|
->setProcessing(request.state);
|
||||||
},
|
},
|
||||||
[&](MessageReference<YaAudioProcessor::Process>&
|
[&](MessageReference<YaAudioProcessor::Process>&
|
||||||
request_ref)
|
request_ref)
|
||||||
|
|||||||
@@ -216,6 +216,19 @@ struct Vst3PluginInstance {
|
|||||||
*/
|
*/
|
||||||
std::optional<Vst3PlugViewInterfaces> plug_view_instance;
|
std::optional<Vst3PlugViewInterfaces> plug_view_instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to make sure that `IPlugView::getSize()` can never be called at the
|
||||||
|
* same time as `IAudioProcessor::setProcessing()`.
|
||||||
|
*
|
||||||
|
* HACK: This really shouldn't be needed, but MeldaProduction plugins seem
|
||||||
|
* to deadlock when this happens. It's pretty tricky to reproduce the
|
||||||
|
* timing for making this happen (since opening the GUI also needs to
|
||||||
|
* be delayed slightly, like when opening a plugin from Bitwig's popup
|
||||||
|
* browser), but it seems like a good idea to make sure that this
|
||||||
|
* doesn't cause any freezes.
|
||||||
|
*/
|
||||||
|
std::mutex get_size_mutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This contains smart pointers to all VST3 plugin interfaces that can be
|
* This contains smart pointers to all VST3 plugin interfaces that can be
|
||||||
* casted from `object`.
|
* casted from `object`.
|
||||||
|
|||||||
Reference in New Issue
Block a user