rearrange AutomationControl and RouteAutomationControl to get more shared logic and...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 9 Mar 2016 15:26:09 +0000 (10:26 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 31 May 2016 19:30:40 +0000 (15:30 -0400)
libs/ardour/ardour/automation_control.h
libs/ardour/ardour/route.h
libs/ardour/automation_control.cc
libs/ardour/route.cc
libs/ardour/route_controls.cc

index de476288f0f6d6f75608d0476fd9f6fc44edd14a..9462a79748636d12c5388f0a6ea24e90f0855720 100644 (file)
@@ -158,6 +158,7 @@ public:
 
        void master_going_away (boost::weak_ptr<AutomationControl>);
        virtual void recompute_masters_ratios (double val) { /* do nothing by default */}
+       virtual double get_masters_value_locked () const;
        double get_value_locked() const;
 };
 
index f819ddac63458b654bcd1bc9fa54df0c0a8ed195..89026651700c57f4338b8655dab06fa262b996ba 100644 (file)
@@ -477,6 +477,18 @@ public:
                boost::weak_ptr<Route> _route;
        };
 
+       class BooleanRouteAutomationControl : public RouteAutomationControl {
+       public:
+               BooleanRouteAutomationControl (const std::string& name,
+                                              AutomationType atype,
+                                              boost::shared_ptr<AutomationList> alist,
+                                              boost::shared_ptr<Route> route)
+                       : RouteAutomationControl (name, atype, alist, route) {}
+       protected:
+               double get_masters_value_locked() const;
+
+       };
+
        class GainControllable : public GainControl  {
        public:
                GainControllable (Session& session,
@@ -501,7 +513,7 @@ public:
                boost::weak_ptr<Route> _route;
        };
 
-       class SoloControllable : public RouteAutomationControl {
+       class SoloControllable : public BooleanRouteAutomationControl {
        public:
                SoloControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@@ -511,7 +523,7 @@ public:
                void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
-       struct MuteControllable : public RouteAutomationControl {
+       struct MuteControllable : public BooleanRouteAutomationControl {
        public:
                MuteControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@@ -526,7 +538,7 @@ public:
                void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
-       class LIBARDOUR_API PhaseControllable : public RouteAutomationControl {
+       class LIBARDOUR_API PhaseControllable : public BooleanRouteAutomationControl {
        public:
                PhaseControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@@ -539,7 +551,7 @@ public:
                void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
-       class LIBARDOUR_API SoloIsolateControllable : public RouteAutomationControl {
+       class LIBARDOUR_API SoloIsolateControllable : public BooleanRouteAutomationControl {
        public:
                SoloIsolateControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@@ -549,7 +561,7 @@ public:
                void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
        };
 
-       class LIBARDOUR_API SoloSafeControllable : public RouteAutomationControl {
+       class LIBARDOUR_API SoloSafeControllable : public BooleanRouteAutomationControl {
        public:
                SoloSafeControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
index 4317a187884d30b3a45edd3b0e66206861fde543..d7b645d8ae06a806d17d6ebc9db649fb44d242fa 100644 (file)
@@ -69,18 +69,17 @@ AutomationControl::writable() const
        return true;
 }
 
-/** Get the current effective `user' value based on automation state */
 double
-AutomationControl::get_value() const
+AutomationControl::get_masters_value_locked () const
 {
-       bool from_list = _list && ((AutomationList*)_list.get())->automation_playback();
+       gain_t v = 1.0;
 
-       if (!from_list) {
-               Glib::Threads::RWLock::ReaderLock lm (master_lock);
-               return get_value_locked ();
-       } else {
-               return Control::get_double (from_list, _session.transport_frame());
+       for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
+               /* get current master value, scale by our current ratio with that master */
+               v *= mr->second.master()->get_value () * mr->second.ratio();
        }
+
+       return min (_desc.upper, v);
 }
 
 double
@@ -92,17 +91,22 @@ AutomationControl::get_value_locked() const
                return Control::get_double (false, _session.transport_frame());
        }
 
-       gain_t v = 1.0;
-
-       for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
-               /* get current master value, scale by our current ratio with that master */
-               v *= mr->second.master()->get_value () * mr->second.ratio();
-       }
-
-       return min (_desc.upper, v);
+       return get_masters_value_locked ();
 }
 
+/** Get the current effective `user' value based on automation state */
+double
+AutomationControl::get_value() const
+{
+       bool from_list = _list && ((AutomationList*)_list.get())->automation_playback();
 
+       if (!from_list) {
+               Glib::Threads::RWLock::ReaderLock lm (master_lock);
+               return get_value_locked ();
+       } else {
+               return Control::get_double (from_list, _session.transport_frame());
+       }
+}
 
 /** Set the value and do the right thing based on automation state
  *  (e.g. record if necessary, etc.)
@@ -358,4 +362,3 @@ AutomationControl::slaved () const
        Glib::Threads::RWLock::ReaderLock lm (master_lock);
        return !_masters.empty();
 }
-
index 641bc8ef8329afc0adc2fc103739319533c87ddd..94111e602eb47e7b3026bb9d68c6fb16d90ef286 100644 (file)
@@ -5899,8 +5899,8 @@ void
 Route::vca_assign (boost::shared_ptr<VCA> vca)
 {
        _gain_control->add_master (vca->gain_control());
-       vca->add_solo_target (shared_from_this());
-       vca->add_mute_target (shared_from_this());
+       _solo_control->add_master (vca->solo_control());
+       _mute_control->add_master (vca->mute_control());
 }
 
 void
@@ -5909,10 +5909,12 @@ Route::vca_unassign (boost::shared_ptr<VCA> vca)
        if (!vca) {
                /* unassign from all */
                _gain_control->clear_masters ();
-               /* XXXX need to remove from solo/mute target lists */
+               _solo_control->clear_masters ();
+               _mute_control->clear_masters ();
        } else {
                _gain_control->remove_master (vca->gain_control());
-               vca->remove_solo_target (shared_from_this());
-               vca->remove_mute_target (shared_from_this());
+               _solo_control->remove_master (vca->solo_control());
+               _mute_control->remove_master (vca->mute_control());
+
        }
 }
index 5ab7524f84d016319100e56cf47ae405aae85cff..0e6edec758f36b8ef964b6ffdb2d90679fff474b 100644 (file)
@@ -94,6 +94,26 @@ Route::RouteAutomationControl::RouteAutomationControl (const std::string& name,
 {
 }
 
+double
+Route::BooleanRouteAutomationControl::get_masters_value_locked () const
+{
+       /* masters (read/write) lock must be held */
+
+       /* if any master is enabled (val > 0.0) then we consider the master
+          value to be 1.0
+       */
+
+       for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
+               if (mr->second.master()->get_value()) {
+                       return 1.0;
+               }
+       }
+
+       return 0.0;
+}
+
+
+
 Route::GainControllable::GainControllable (Session& s, AutomationType atype, boost::shared_ptr<Route> r)
        : GainControl (s, Evoral::Parameter(atype))
        , _route (r)
@@ -102,7 +122,7 @@ Route::GainControllable::GainControllable (Session& s, AutomationType atype, boo
 }
 
 Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
-       : RouteAutomationControl (name, SoloAutomation, boost::shared_ptr<AutomationList>(), r)
+       : BooleanRouteAutomationControl (name, SoloAutomation, boost::shared_ptr<AutomationList>(), r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
        gl->set_interpolation(Evoral::ControlList::Discrete);
@@ -138,7 +158,18 @@ Route::SoloControllable::set_value_unchecked (double val)
 double
 Route::SoloControllable::get_value () const
 {
+       if (slaved()) {
+               Glib::Threads::RWLock::ReaderLock lm (master_lock);
+               return get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+       }
+
+       if (_list && ((AutomationList*)_list.get())->automation_playback()) {
+               // Playing back automation, get the value from the list
+               return AutomationControl::get_value();
+       }
+
        boost::shared_ptr<Route> r = _route.lock ();
+
        if (!r) {
                return 0;
        }
@@ -151,7 +182,7 @@ Route::SoloControllable::get_value () const
 }
 
 Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
-       : RouteAutomationControl (name, MuteAutomation, boost::shared_ptr<AutomationList>(), r)
+       : BooleanRouteAutomationControl (name, MuteAutomation, boost::shared_ptr<AutomationList>(), r)
        , _route (r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
@@ -221,6 +252,11 @@ Route::MuteControllable::_set_value (double val, Controllable::GroupControlDispo
 double
 Route::MuteControllable::get_value () const
 {
+       if (slaved()) {
+               Glib::Threads::RWLock::ReaderLock lm (master_lock);
+               return get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+       }
+
        if (_list && ((AutomationList*)_list.get())->automation_playback()) {
                // Playing back automation, get the value from the list
                return AutomationControl::get_value();
@@ -232,7 +268,7 @@ Route::MuteControllable::get_value () const
 }
 
 Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr<Route> r)
-       : RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr<AutomationList>(), r)
+       : BooleanRouteAutomationControl (name, PhaseAutomation, boost::shared_ptr<AutomationList>(), r)
        , _current_phase (0)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(PhaseAutomation)));
@@ -276,7 +312,7 @@ Route::PhaseControllable::channel () const
 }
 
 Route::SoloIsolateControllable::SoloIsolateControllable (std::string name, boost::shared_ptr<Route> r)
-       : RouteAutomationControl (name, SoloIsolateAutomation, boost::shared_ptr<AutomationList>(), r)
+       : BooleanRouteAutomationControl (name, SoloIsolateAutomation, boost::shared_ptr<AutomationList>(), r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloIsolateAutomation)));
        gl->set_interpolation(Evoral::ControlList::Discrete);
@@ -314,7 +350,7 @@ Route::SoloIsolateControllable::_set_value (double val, PBD::Controllable::Group
 }
 
 Route::SoloSafeControllable::SoloSafeControllable (std::string name, boost::shared_ptr<Route> r)
-       : RouteAutomationControl (name, SoloSafeAutomation, boost::shared_ptr<AutomationList>(), r)
+       : BooleanRouteAutomationControl (name, SoloSafeAutomation, boost::shared_ptr<AutomationList>(), r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloSafeAutomation)));
        gl->set_interpolation(Evoral::ControlList::Discrete);