From 2129552777f989b5cc3171ef8da4baf0ce1c9ed9 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Fri, 20 May 2022 19:00:40 +0200 Subject: [PATCH] MixerScene: correctly restore controls with VCA master The master needs to be restored first, otherwise setting the master value with be propagated. Furthermore the actual value is saved at the time of VCA assignment. Restoring the vaule needs to scale by the master-reduced value. --- libs/ardour/ardour/mixer_scene.h | 9 +++-- libs/ardour/mixer_scene.cc | 61 ++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/libs/ardour/ardour/mixer_scene.h b/libs/ardour/ardour/mixer_scene.h index a7f80dbad2..8356e3866f 100644 --- a/libs/ardour/ardour/mixer_scene.h +++ b/libs/ardour/ardour/mixer_scene.h @@ -21,14 +21,15 @@ #include -#include "pbd/controllable.h" -#include "pbd/properties.h" #include "pbd/stateful.h" -#include "ardour/automation_control.h" #include "ardour/libardour_visibility.h" #include "ardour/session_handle.h" +namespace PBD { + class Controllable; +} + namespace ARDOUR { class LIBARDOUR_API MixerScene : public SessionHandleRef, public PBD::Stateful @@ -50,6 +51,8 @@ public: private: typedef std::map ControllableValueMap; + bool recurse_to_master (boost::shared_ptr, std::set &) const; + ControllableValueMap _ctrl_map; std::string _name; }; diff --git a/libs/ardour/mixer_scene.cc b/libs/ardour/mixer_scene.cc index c91048a0a9..5559e555b5 100644 --- a/libs/ardour/mixer_scene.cc +++ b/libs/ardour/mixer_scene.cc @@ -16,9 +16,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "pbd/controllable.h" #include "pbd/types_convert.h" +#include "ardour/automation_control.h" #include "ardour/mixer_scene.h" +#include "ardour/slavable_automation_control.h" #include "ardour/session.h" #include "pbd/i18n.h" @@ -56,24 +59,68 @@ MixerScene::snapshot () if (!boost::dynamic_pointer_cast (c)) { continue; } + if (c->flags () & Controllable::HiddenControl) { + continue; + } _ctrl_map[c->id ()] = c->get_save_value (); } _session.set_dirty (); } +bool +MixerScene::recurse_to_master (boost::shared_ptr c, std::set & done) const +{ + if (done.find (c->id()) != done.end ()) { + return false; + } + +#if 1 /* ignore controls in Write, or Touch + touching() state */ + auto ac = boost::dynamic_pointer_cast (c); + if (ac && ac->automation_write ()) { + done.insert (c->id ()); + return false; + } +#endif + + auto sc = boost::dynamic_pointer_cast (c); + if (sc && sc->slaved ()) { + /* first set masters, then set own value */ + for (auto const& m : sc->masters ()) { + recurse_to_master (m, done); + } + } + + ControllableValueMap::const_iterator it = _ctrl_map.find (c->id ()); + if (it == _ctrl_map.end ()) { + done.insert (c->id ()); + return false; + } + + if (sc && sc->slaved ()) { + double x = sc->reduce_by_masters (1.0); + if (x <= 0) { + c->set_value (0, Controllable::NoGroup); + } else { + c->set_value (it->second / x, Controllable::NoGroup); + } + } else { + c->set_value (it->second, Controllable::NoGroup); + } + + done.insert (it->first); + return true; +} + bool MixerScene::apply () const { bool rv = false; - // TODO special-case solo-iso, and solo (restore order, or ignore) + std::set done; + for (auto const& c : Controllable::registered_controllables ()) { - ControllableValueMap::const_iterator it = _ctrl_map.find (c->id ()); - if (it == _ctrl_map.end ()) { - continue; - } - rv = true; - c->set_value (it->second, Controllable::NoGroup); + rv |= recurse_to_master (c, done); } + return rv; }