From 81d401f06a0d3908dbac0785dd2475545f43f8fa Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 30 Jan 2021 23:26:57 +0100 Subject: [PATCH] Add mutexes for the VST3 data caches Since the restart will always be called from another thread, and when a plugin asks for a restart during initialization this can quickly lead to issues. --- .../bridges/vst3-impls/plugin-proxy.cpp | 148 +++++++++++------- src/plugin/bridges/vst3-impls/plugin-proxy.h | 2 + 2 files changed, 94 insertions(+), 56 deletions(-) diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp index 1d41d6c5..30481880 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp @@ -145,10 +145,13 @@ tresult PLUGIN_API Vst3PluginProxyImpl::setProcessing(TBool state) { // REAPER will repeatedly query the plugin for its bus information on every // processing cycle. Because this really adds up in terms of latency we // sadly have to deviate from yabridge's principles and implement a cache - if (state) { - processing_bus_cache.emplace(); - } else { - processing_bus_cache.reset(); + { + std::lock_guard lock(processing_bus_cache_mutex); + if (state) { + processing_bus_cache.emplace(); + } else { + processing_bus_cache.reset(); + } } return bridge.send_audio_processor_message(YaAudioProcessor::SetProcessing{ @@ -225,23 +228,31 @@ Vst3PluginProxyImpl::getBusCount(Steinberg::Vst::MediaType type, // issue in REAPER std::tuple args{ type, dir}; - if (processing_bus_cache) { - if (auto it = processing_bus_cache->bus_count.find(args); - it != processing_bus_cache->bus_count.end()) { - const bool log_response = bridge.logger.log_request(true, request); - if (log_response) { - bridge.logger.log_response( - true, YaComponent::GetBusCount::Response(it->second), true); - } + { + std::lock_guard lock(processing_bus_cache_mutex); + if (processing_bus_cache) { + if (auto it = processing_bus_cache->bus_count.find(args); + it != processing_bus_cache->bus_count.end()) { + const bool log_response = + bridge.logger.log_request(true, request); + if (log_response) { + bridge.logger.log_response( + true, YaComponent::GetBusCount::Response(it->second), + true); + } - return it->second; + return it->second; + } } } const int32 result = bridge.send_audio_processor_message(request); - if (processing_bus_cache) { - processing_bus_cache->bus_count[args] = result; + { + std::lock_guard lock(processing_bus_cache_mutex); + if (processing_bus_cache) { + processing_bus_cache->bus_count[args] = result; + } } return result; @@ -262,21 +273,26 @@ Vst3PluginProxyImpl::getBusInfo(Steinberg::Vst::MediaType type, // issue in REAPER std::tuple args{type, dir, index}; - if (processing_bus_cache) { - if (auto it = processing_bus_cache->bus_info.find(args); - it != processing_bus_cache->bus_info.end()) { - const bool log_response = bridge.logger.log_request(true, request); - if (log_response) { - bridge.logger.log_response(true, - YaComponent::GetBusInfo::Response{ - .result = Steinberg::kResultOk, - .updated_bus = it->second}, - true); + { + std::lock_guard lock(processing_bus_cache_mutex); + if (processing_bus_cache) { + if (auto it = processing_bus_cache->bus_info.find(args); + it != processing_bus_cache->bus_info.end()) { + const bool log_response = + bridge.logger.log_request(true, request); + if (log_response) { + bridge.logger.log_response( + true, + YaComponent::GetBusInfo::Response{ + .result = Steinberg::kResultOk, + .updated_bus = it->second}, + true); + } + + bus = it->second; + + return Steinberg::kResultOk; } - - bus = it->second; - - return Steinberg::kResultOk; } } @@ -284,8 +300,12 @@ Vst3PluginProxyImpl::getBusInfo(Steinberg::Vst::MediaType type, bridge.send_audio_processor_message(request); bus = response.updated_bus; - if (processing_bus_cache) { - processing_bus_cache->bus_info[args] = response.updated_bus; + + { + std::lock_guard lock(processing_bus_cache_mutex); + if (processing_bus_cache) { + processing_bus_cache->bus_info[args] = response.updated_bus; + } } return response.result; @@ -440,22 +460,28 @@ int32 PLUGIN_API Vst3PluginProxyImpl::getParameterCount() { // We'll cache this information to work around an issue in REAPER, see // `parameter_info_cache` - if (parameter_info_cache.parameter_count) { - const bool log_response = bridge.logger.log_request(true, request); - if (log_response) { - bridge.logger.log_response( - true, - YaEditController::GetParameterCount::Response( - *parameter_info_cache.parameter_count), - true); - } + { + std::lock_guard lock(parameter_info_cache_mutex); + if (parameter_info_cache.parameter_count) { + const bool log_response = bridge.logger.log_request(true, request); + if (log_response) { + bridge.logger.log_response( + true, + YaEditController::GetParameterCount::Response( + *parameter_info_cache.parameter_count), + true); + } - return *parameter_info_cache.parameter_count; + return *parameter_info_cache.parameter_count; + } } const int32 result = bridge.send_message(request); - parameter_info_cache.parameter_count = result; + { + std::lock_guard lock(parameter_info_cache_mutex); + parameter_info_cache.parameter_count = result; + } return result; } @@ -468,26 +494,34 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getParameterInfo( // We'll cache this information to work around an issue in REAPER, see // `parameter_info_cache` - if (auto it = parameter_info_cache.parameter_info.find(paramIndex); - it != parameter_info_cache.parameter_info.end()) { - const bool log_response = bridge.logger.log_request(true, request); - if (log_response) { - bridge.logger.log_response( - true, - YaEditController::GetParameterInfo::Response{ - .result = Steinberg::kResultOk, .updated_info = it->second}, - true); + { + std::lock_guard lock(parameter_info_cache_mutex); + if (auto it = parameter_info_cache.parameter_info.find(paramIndex); + it != parameter_info_cache.parameter_info.end()) { + const bool log_response = bridge.logger.log_request(true, request); + if (log_response) { + bridge.logger.log_response( + true, + YaEditController::GetParameterInfo::Response{ + .result = Steinberg::kResultOk, + .updated_info = it->second}, + true); + } + + info = it->second; + + return Steinberg::kResultOk; } - - info = it->second; - - return Steinberg::kResultOk; } const GetParameterInfoResponse response = bridge.send_message(request); info = response.updated_info; - parameter_info_cache.parameter_info[paramIndex] = response.updated_info; + + { + std::lock_guard lock(parameter_info_cache_mutex); + parameter_info_cache.parameter_info[paramIndex] = response.updated_info; + } return response.result; } @@ -1158,11 +1192,13 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getXmlRepresentationStream( } void Vst3PluginProxyImpl::clear_bus_cache() { + std::lock_guard lock(processing_bus_cache_mutex); if (processing_bus_cache) { processing_bus_cache.emplace(); } } void Vst3PluginProxyImpl::clear_parameter_cache() { + std::lock_guard lock(parameter_info_cache_mutex); parameter_info_cache = ParameterInfoCache{}; } diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.h b/src/plugin/bridges/vst3-impls/plugin-proxy.h index 83c61b7e..0198ccc8 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.h +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.h @@ -487,6 +487,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { * does that. */ std::optional processing_bus_cache; + std::mutex processing_bus_cache_mutex; /** * A cache for `IEditController::getParameterCount()` and @@ -513,4 +514,5 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy { * information four times per second. */ ParameterInfoCache parameter_info_cache; + std::mutex parameter_info_cache_mutex; };