diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index c157c46439..2f270eb7d9 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -553,7 +553,7 @@ public: std::shared_ptr mapped_control (enum WellKnownCtrl, uint32_t band = 0) const; std::shared_ptr mapped_output (enum WellKnownData) const; - std::shared_ptr send_level_controllable (uint32_t n) const; + std::shared_ptr send_level_controllable (uint32_t n, bool locked = false) const; std::shared_ptr send_enable_controllable (uint32_t n) const; std::shared_ptr send_pan_azimuth_controllable (uint32_t n) const; std::shared_ptr send_pan_azimuth_enable_controllable (uint32_t n) const; diff --git a/libs/ardour/ardour/stripable.h b/libs/ardour/ardour/stripable.h index c21e9cc7f2..0af0f48ef5 100644 --- a/libs/ardour/ardour/stripable.h +++ b/libs/ardour/ardour/stripable.h @@ -158,7 +158,7 @@ class LIBARDOUR_API Stripable : public SessionObject, * In Ardour, these are user-created sends that connect to user-created * Aux busses. */ - virtual std::shared_ptr send_level_controllable (uint32_t n) const = 0; + virtual std::shared_ptr send_level_controllable (uint32_t n, bool locked = false) const = 0; virtual std::shared_ptr send_enable_controllable (uint32_t n) const = 0; virtual std::shared_ptr send_pan_azimuth_controllable (uint32_t n) const = 0; virtual std::shared_ptr send_pan_azimuth_enable_controllable (uint32_t n) const = 0; diff --git a/libs/ardour/ardour/vca.h b/libs/ardour/ardour/vca.h index 76885d2c8d..b660e6ffb8 100644 --- a/libs/ardour/ardour/vca.h +++ b/libs/ardour/ardour/vca.h @@ -134,7 +134,7 @@ class LIBARDOUR_API VCA : public Stripable, uint32_t eq_band_cnt () const { return 0; } std::string eq_band_name (uint32_t) const { return std::string(); } - std::shared_ptr send_level_controllable (uint32_t n) const { return std::shared_ptr(); } + std::shared_ptr send_level_controllable (uint32_t n, bool locked = false) const { return std::shared_ptr(); } std::shared_ptr send_enable_controllable (uint32_t n) const { return std::shared_ptr(); } std::shared_ptr send_pan_azimuth_controllable (uint32_t n) const { return std::shared_ptr(); } std::shared_ptr send_pan_azimuth_enable_controllable (uint32_t n) const { return std::shared_ptr(); } diff --git a/libs/ardour/ardour/vst3_plugin.h b/libs/ardour/ardour/vst3_plugin.h index 3ac40037b6..8a9d83fb1a 100644 --- a/libs/ardour/ardour/vst3_plugin.h +++ b/libs/ardour/ardour/vst3_plugin.h @@ -359,6 +359,10 @@ private: bool _no_kMono; /* work around yabridge threading */ bool _restart_component_is_synced; + /* work around PSL calls during set_owner, + * while the route holds a processor lock + */ + std::atomic _in_set_owner; }; } // namespace Steinberg diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index b47cea9aa0..2c0e187118 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -5927,8 +5927,15 @@ Route::send_pan_azimuth_controllable (uint32_t n) const } std::shared_ptr -Route::send_level_controllable (uint32_t n) const +Route::send_level_controllable (uint32_t n, bool locked) const { + if (locked) { + /* calling thread has a WriterLock (_processor_lock) + * we cannot call nth_send() + */ + return std::shared_ptr(); + } + std::shared_ptr s = std::dynamic_pointer_cast(nth_send (n)); if (s) { return s->gain_control (); diff --git a/libs/ardour/vst3_plugin.cc b/libs/ardour/vst3_plugin.cc index fedd9141de..10cb6a42f2 100644 --- a/libs/ardour/vst3_plugin.cc +++ b/libs/ardour/vst3_plugin.cc @@ -1195,6 +1195,7 @@ VST3PI::VST3PI (std::shared_ptr m, std::string unique_ , _rpc_queue (RouteProcessorChange::NoProcessorChange, false) , _no_kMono (false) , _restart_component_is_synced (false) + , _in_set_owner (false) { using namespace std; IPluginFactory* factory = m->factory (); @@ -1835,9 +1836,13 @@ VST3PI::set_owner (SessionObject* o) return; } + _in_set_owner.store (true); + if (!setup_psl_info_handler ()) { setup_info_listener (); } + + _in_set_owner.store (false); } void @@ -2809,7 +2814,7 @@ VST3PI::automation_state_changed (uint32_t port, AutoState s, std::weak_ptr -lookup_ac (SessionObject* o, FIDString id) +lookup_ac (SessionObject* o, FIDString id, bool locked = false) { Stripable* s = dynamic_cast (o); if (!s) { @@ -2842,8 +2847,8 @@ lookup_ac (SessionObject* o, FIDString id) * recurive locks (deadlock, or double unlock crash). */ int send_id = atoi (id + strlen (ContextInfo::kSendLevel)); - if (s->send_enable_controllable (send_id)) { - return s->send_level_controllable (send_id); + if (send_id >=0 && s->send_enable_controllable (send_id)) { + return s->send_level_controllable (send_id, locked); } #endif } @@ -2967,6 +2972,7 @@ VST3PI::getContextInfoValue (double& value, FIDString id) value = 2.0; // Config->get_max_gain(); #ifdef MIXBUS if (s->send_enable_controllable (0)) { + assert (s->send_level_controllable (0)); value = s->send_level_controllable (0)->upper (); // pow (10.0, .05 * 15.0); } #endif @@ -2983,11 +2989,12 @@ VST3PI::getContextInfoValue (double& value, FIDString id) value = 0.5; // center } } else if (0 == strncmp (id, ContextInfo::kSendLevel, strlen (ContextInfo::kSendLevel))) { - std::shared_ptr ac = lookup_ac (_owner, id); + std::shared_ptr ac = lookup_ac (_owner, id, _in_set_owner.load ()); if (ac) { value = ac->get_value (); // gain cofficient psl_subscribe_to (ac, id); } else { + value = 0; DEBUG_TRACE (DEBUG::VST3Callbacks, string_compose ("VST3PI::getContextInfoValue invalid AC %1\n", id)); return kInvalidArgument; // send index out of bounds } @@ -3023,7 +3030,7 @@ VST3PI::setContextInfoValue (FIDString id, double value) ac->set_value (ac->interface_to_internal (value, true), PBD::Controllable::NoGroup); } } else if (0 == strncmp (id, ContextInfo::kSendLevel, strlen (ContextInfo::kSendLevel))) { - std::shared_ptr ac = lookup_ac (_owner, id); + std::shared_ptr ac = lookup_ac (_owner, id, _in_set_owner.load ()); if (ac) { ac->set_value (value, Controllable::NoGroup); } else {