change API of Controllable::Changed signal to include (from_self, GroupControlDisposi...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 11 Mar 2016 15:34:51 +0000 (10:34 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 31 May 2016 19:30:40 +0000 (15:30 -0400)
This allows the signal to convey more information, which may be required by some handlers of a control's Changed signal

12 files changed:
libs/ardour/ardour/monitor_processor.h
libs/ardour/ardour/proxy_controllable.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/automation_control.cc
libs/ardour/monitor_processor.cc
libs/ardour/route.cc
libs/ardour/route_controls.cc
libs/ardour/session.cc
libs/ardour/session_state.cc
libs/ardour/track.cc
libs/pbd/pbd/controllable.h

index e971d0a01819eb05eae4bc9423e14a96f66af533..cef12b33d93def01959bc55695d82285022f1769 100644 (file)
@@ -54,11 +54,11 @@ public:
 
        /* Controllable API */
 
-       void set_value (double v, PBD::Controllable::GroupControlDisposition group_override) {
+       void set_value (double v, PBD::Controllable::GroupControlDisposition gcd) {
                T newval = (T) v;
                if (newval != _value) {
                        _value = std::max (_lower, std::min (_upper, newval));
-                       Changed(); /* EMIT SIGNAL */
+                       Changed (true, gcd); /* EMIT SIGNAL */
                }
        }
 
@@ -84,7 +84,7 @@ public:
        MPControl& operator=(const T& v) {
                if (v != _value) {
                        _value = std::max (_lower, std::min (_upper, v));
-                       Changed (); /* EMIT SIGNAL */
+                       Changed (true, PBD::Controllable::UseGroup); /* EMIT SIGNAL */
                }
                return *this;
        }
index c60f5f1b74770756ce084bc5094cf34301cf3ede..22761d7dba1ce49d229592b6c491da1ef1828998 100644 (file)
@@ -40,7 +40,7 @@ class LIBARDOUR_API ProxyControllable : public PBD::Controllable {
                , _getter (getter)
        {}
 
-       void set_value (double v, PBD::Controllable::GroupControlDisposition /*group_override*/) { if (_setter (v)) { Changed(); /* EMIT SIGNAL */ } }
+       void set_value (double v, PBD::Controllable::GroupControlDisposition gcd) { if (_setter (v)) { Changed (true, gcd); /* EMIT SIGNAL */ } }
        double get_value () const { return _getter (); }
 
        double internal_to_user (double i) const { return accurate_coefficient_to_dB (i);}
index b976e63c694069ad4fd94c5ae8f400f3dbcaf2b0..0afafe82eb22fa0e40cd3c06526e4a6352d9e51e 100644 (file)
@@ -526,7 +526,6 @@ public:
 
                /* Pretend to change value, but do not affect actual route mute. */
                void set_superficial_value(bool muted);
-
        private:
                boost::weak_ptr<Route> _route;
                void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
index b3852b631d0821c53cb4d5ea0d755f0d473f311f..18507ee5d9d59dc465ce64472699da54a516f5df 100644 (file)
@@ -67,7 +67,6 @@
 #include "ardour/rc_configuration.h"
 #include "ardour/session_configuration.h"
 #include "ardour/session_event.h"
-#include "ardour/session_solo_notifications.h"
 #include "ardour/interpolation.h"
 #include "ardour/plugin.h"
 #include "ardour/route.h"
@@ -166,7 +165,7 @@ private:
 };
 
 /** Ardour Session */
-class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager, public SessionSoloNotifications<Session>
+class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
 {
   public:
        enum RecordState {
@@ -1684,13 +1683,12 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void reassign_track_numbers ();
        uint32_t _track_number_decimals;
 
-       /* solo/mute/notifications (see SessionSoloNotifications object) */
+       /* solo/mute/notifications */
 
-       friend class SessionSoloNotifications;
-       void _route_listen_changed (PBD::Controllable::GroupControlDisposition, boost::shared_ptr<Route>);
-       void _route_mute_changed ();
-       void _route_solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition group_override, boost::shared_ptr<Route>);
-       void _route_solo_isolated_changed (boost::shared_ptr<Route>);
+       void route_listen_changed (PBD::Controllable::GroupControlDisposition, boost::weak_ptr<Route>);
+       void route_mute_changed ();
+       void route_solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route>);
+       void route_solo_isolated_changed (boost::weak_ptr<Route>);
 
        void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
 
index d7b645d8ae06a806d17d6ebc9db649fb44d242fa..2ac6574528b1cbdb34a803aafdc6db539e23d43d 100644 (file)
@@ -113,20 +113,22 @@ AutomationControl::get_value() const
  *  @param value `user' value
  */
 void
-AutomationControl::set_value (double value, PBD::Controllable::GroupControlDisposition /* group_override */)
+AutomationControl::set_value (double value, PBD::Controllable::GroupControlDisposition gcd)
 {
        bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
 
        Control::set_double (value, _session.transport_frame(), to_list);
 
-       Changed(); /* EMIT SIGNAL */
+       cerr << "AC was set to " << value << endl;
+
+       Changed (true, gcd);
 }
 
 void
 AutomationControl::set_list (boost::shared_ptr<Evoral::ControlList> list)
 {
        Control::set_list (list);
-       Changed();  /* EMIT SIGNAL */
+       Changed (true, Controllable::NoGroup);
 }
 
 void
@@ -268,6 +270,7 @@ void
 AutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
 {
        double current_value;
+       double new_value;
        std::pair<Masters::iterator,bool> res;
 
        {
@@ -291,15 +294,28 @@ AutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
 
                        /* Store the connection inside the MasterRecord, so that when we destroy it, the connection is destroyed
                           and we no longer hear about changes to the AutomationControl.
+
+                          Note that we fix the "from_self" argument that will
+                          be given to our own Changed signal to "false",
+                          because the change came from the master.
                        */
 
-                       m->Changed.connect_same_thread (res.first->second.connection, boost::bind (&PBD::Signal0<void>::operator(), &Changed));
+
+                       m->Changed.connect_same_thread (res.first->second.connection, boost::bind (&PBD::Signal2<void,bool,Controllable::GroupControlDisposition>::operator(), &Changed, false, _2));
                }
+
+               new_value = get_value_locked ();
        }
 
        if (res.second) {
                MasterStatusChange (); /* EMIT SIGNAL */
        }
+
+       if (new_value != current_value) {
+               /* effective value changed by master */
+               Changed (false, Controllable::NoGroup);
+       }
+
 }
 
 void
@@ -315,6 +331,7 @@ void
 AutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
 {
        double current_value;
+       double new_value;
        Masters::size_type erased = 0;
 
        {
@@ -324,29 +341,43 @@ AutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
                if (erased) {
                        recompute_masters_ratios (current_value);
                }
+               new_value = get_value_locked ();
        }
 
        if (erased) {
                MasterStatusChange (); /* EMIT SIGNAL */
        }
+
+       if (new_value != current_value) {
+               Changed (false, Controllable::NoGroup);
+       }
 }
 
 void
 AutomationControl::clear_masters ()
 {
+       double current_value;
+       double new_value;
        bool had_masters = false;
 
        {
                Glib::Threads::RWLock::WriterLock lm (master_lock);
+               current_value = get_value_locked ();
                if (!_masters.empty()) {
                        had_masters = true;
                }
                _masters.clear ();
+               new_value = get_value_locked ();
        }
 
        if (had_masters) {
                MasterStatusChange (); /* EMIT SIGNAL */
        }
+
+       if (new_value != current_value) {
+               Changed (false, Controllable::NoGroup);
+       }
+
 }
 
 bool
index c7a79ee2f533b9993ea44bafc3196d6b51533ff2..e5c58009af764fccd9b0f6e3302039ca8e8b4779 100644 (file)
@@ -37,11 +37,11 @@ using namespace std;
 /* specialize for bool because of set_value() semantics */
 
 namespace ARDOUR {
-       template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition /*group_override*/) {
+       template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition gcd) {
                 bool newval = fabs (v) >= 0.5;
                 if (newval != _value) {
                         _value = newval;
-                        Changed(); /* EMIT SIGNAL */
+                        Changed (true, gcd); /* EMIT SIGNAL */
                 }
         }
 }
index 569f00fbc770c020e8d2798f0994dbfd3695491f..c9b9aff3ac1a16875291462bed8b1e424a9d8a96 100644 (file)
@@ -416,9 +416,9 @@ Route::inc_gain (gain_t factor)
 }
 
 void
-Route::set_gain (gain_t val, Controllable::GroupControlDisposition group_override)
+Route::set_gain (gain_t val, Controllable::GroupControlDisposition gcd)
 {
-       if (use_group (group_override, &RouteGroup::is_gain)) {
+       if (use_group (gcd, &RouteGroup::is_gain)) {
 
                if (_route_group->is_relative()) {
 
@@ -442,13 +442,13 @@ Route::set_gain (gain_t val, Controllable::GroupControlDisposition group_overrid
                        if (factor > 0.0f) {
                                factor = _route_group->get_max_factor(factor);
                                if (factor == 0.0f) {
-                                       _amp->gain_control()->Changed(); /* EMIT SIGNAL */
+                                       _amp->gain_control()->Changed (true, gcd); /* EMIT SIGNAL */
                                        return;
                                }
                        } else {
                                factor = _route_group->get_min_factor(factor);
                                if (factor == 0.0f) {
-                                       _amp->gain_control()->Changed(); /* EMIT SIGNAL */
+                                       _amp->gain_control()->Changed (true, gcd); /* EMIT SIGNAL */
                                        return;
                                }
                        }
@@ -830,8 +830,8 @@ Route::set_listen (bool yn, Controllable::GroupControlDisposition group_override
                        }
                        _mute_master->set_soloed_by_others (false);
 
-                       _session.listen_changed (group_override, shared_from_this());
-                       _solo_control->Changed(); /* EMIT SIGNAL */
+                       /* first argument won't matter because solo <=> listen right now */
+                       _solo_control->Changed (false, group_override); /* EMIT SIGNAL */
                }
        }
 }
@@ -847,11 +847,11 @@ Route::listening_via_monitor () const
 }
 
 void
-Route::set_solo_safe (bool yn, Controllable::GroupControlDisposition /* group_override */)
+Route::set_solo_safe (bool yn, Controllable::GroupControlDisposition gcd)
 {
        if (_solo_safe != yn) {
                _solo_safe = yn;
-               _solo_safe_control->Changed(); /* EMIT SIGNAL */
+               _solo_safe_control->Changed (true, gcd); /* EMIT SIGNAL */
        }
 }
 
@@ -893,8 +893,7 @@ Route::clear_all_solo_state ()
 
        if (emit_changed) {
                set_mute_master_solo ();
-               _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
-               _solo_control->Changed (); /* EMIT SIGNAL */
+               _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
        }
 }
 
@@ -921,8 +920,7 @@ Route::set_solo (bool yn, Controllable::GroupControlDisposition group_override)
 
        if (self_soloed() != yn) {
                set_self_solo (yn);
-               _session.solo_changed (true, group_override, shared_from_this());
-               _solo_control->Changed (); /* EMIT SIGNAL */
+               _solo_control->Changed (true, group_override); /* EMIT SIGNAL */
        }
 
        assert (Config->get_solo_control_is_listen_control() || !_monitor_send || !_monitor_send->active());
@@ -999,8 +997,7 @@ Route::mod_solo_by_others_upstream (int32_t delta)
        }
 
        set_mute_master_solo ();
-       _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
-       _solo_control->Changed (); /* EMIT SIGNAL */
+       _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
 }
 
 void
@@ -1022,8 +1019,7 @@ Route::mod_solo_by_others_downstream (int32_t delta)
        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream));
 
        set_mute_master_solo ();
-       _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
-       _solo_control->Changed (); /* EMIT SIGNAL */
+       _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
 }
 
 void
@@ -1053,8 +1049,7 @@ Route::mod_solo_isolated_by_upstream (bool yn)
        if (solo_isolated() != old) {
                /* solo isolated status changed */
                _mute_master->set_solo_ignore (solo_isolated());
-               _session.solo_isolated_changed (shared_from_this());
-               _solo_isolate_control->Changed(); /* EMIT SIGNAL */
+               _solo_isolate_control->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
        }
 }
 
@@ -1110,8 +1105,7 @@ Route::set_solo_isolated (bool yn, Controllable::GroupControlDisposition group_o
 
        /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
 
-       _session.solo_isolated_changed (shared_from_this());
-       _solo_isolate_control->Changed(); /* EMIT SIGNAL */
+       _solo_isolate_control->Changed (true, group_override); /* EMIT SIGNAL */
 }
 
 bool
@@ -1127,8 +1121,7 @@ Route::set_mute_points (MuteMaster::MutePoint mp)
        mute_points_changed (); /* EMIT SIGNAL */
 
        if (_mute_master->muted_by_self()) {
-               _session.mute_changed ();
-               _mute_control->Changed (); /* EMIT SIGNAL */
+               _mute_control->Changed (true, Controllable::UseGroup); /* EMIT SIGNAL */
        }
 }
 
@@ -1147,8 +1140,7 @@ Route::set_mute (bool yn, Controllable::GroupControlDisposition group_override)
                */
                act_on_mute ();
                /* tell everyone else */
-               _session.mute_changed ();
-               _mute_control->Changed (); /* EMIT SIGNAL */
+               _mute_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */
        }
 }
 
@@ -4647,7 +4639,7 @@ Route::set_phase_invert (uint32_t c, bool yn)
 {
        if (_phase_invert[c] != yn) {
                _phase_invert[c] = yn;
-               _phase_control->Changed(); /* EMIT SIGNAL */
+               _phase_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */
                _session.set_dirty ();
        }
 }
@@ -4657,7 +4649,7 @@ Route::set_phase_invert (boost::dynamic_bitset<> p)
 {
        if (_phase_invert != p) {
                _phase_invert = p;
-               _phase_control->Changed (); /* EMIT SIGNAL */
+               _phase_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */
                _session.set_dirty ();
        }
 }
index 0e6edec758f36b8ef964b6ffdb2d90679fff474b..59920145634c1359324246b5a0dec5c568335fa3 100644 (file)
@@ -158,9 +158,13 @@ Route::SoloControllable::set_value_unchecked (double val)
 double
 Route::SoloControllable::get_value () const
 {
+       std::cerr << "RSC get value\n";
+
        if (slaved()) {
+               std::cerr << "slaved solo control, get master value ... ";
                Glib::Threads::RWLock::ReaderLock lm (master_lock);
-               return get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+               double v = get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+               std::cerr << v << std::endl;
        }
 
        if (_list && ((AutomationList*)_list.get())->automation_playback()) {
@@ -385,4 +389,3 @@ Route::SoloSafeControllable::get_value () const
 
        return r->solo_safe() ? 1.0 : 0.0;
 }
-
index 417edf83b76ef04bb0b7476983111c1c4ca82e00..ee70d2a40f14810f2d5686bab9d5798082781905 100644 (file)
@@ -3411,12 +3411,10 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                boost::weak_ptr<Route> wpr (*x);
                boost::shared_ptr<Route> r (*x);
 
-               /* we don't connect to control Changed signals for
-                * solo/mute/listen. The Route calls back to use, via
-                * the SessionSoloNotifications API, passing us more
-                * information than would be available from a control Changed signal.
-                */
-               
+               r->solo_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
+               r->solo_isolate_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
+               r->mute_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
+
                r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
                r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
 
@@ -3694,14 +3692,20 @@ Session::remove_route (boost::shared_ptr<Route> route)
 }
 
 void
-Session::_route_mute_changed ()
+Session::route_mute_changed ()
 {
        set_dirty ();
 }
 
 void
-Session::_route_listen_changed (Controllable::GroupControlDisposition group_override, boost::shared_ptr<Route> route)
+Session::route_listen_changed (Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
 {
+       boost::shared_ptr<Route> route (wpr.lock());
+
+       if (!route) {
+               return;
+       }
+
        if (route->listening_via_monitor ()) {
 
                if (Config->get_exclusive_solo()) {
@@ -3745,8 +3749,14 @@ Session::_route_listen_changed (Controllable::GroupControlDisposition group_over
 }
 
 void
-Session::_route_solo_isolated_changed (boost::shared_ptr<Route> route)
+Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
 {
+       boost::shared_ptr<Route> route (wpr.lock());
+
+       if (!route) {
+               return;
+       }
+
        bool send_changed = false;
 
        if (route->solo_isolated()) {
@@ -3767,10 +3777,23 @@ Session::_route_solo_isolated_changed (boost::shared_ptr<Route> route)
 }
 
 void
-Session::_route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override,  boost::shared_ptr<Route> route)
+Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override,  boost::weak_ptr<Route> wpr)
 {
+       cerr << "route solo change (self ? " << self_solo_change << endl;
+
        DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
 
+       boost::shared_ptr<Route> route (wpr.lock());
+
+       if (!route) {
+               return;
+       }
+
+       if (Config->get_solo_control_is_listen_control()) {
+               route_listen_changed (group_override, wpr);
+               return;
+       }
+
        if (!self_solo_change) {
                // session doesn't care about changes to soloed-by-others
                return;
@@ -3924,7 +3947,7 @@ Session::_route_solo_changed (bool self_solo_change, Controllable::GroupControlD
        for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
                DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1, which neither feeds or is fed by %2\n", (*i)->name(), route->name()));
                (*i)->act_on_mute ();
-               (*i)->mute_control()->Changed (); /* EMIT SIGNAL */
+               (*i)->mute_control()->Changed (false, Controllable::NoGroup);
        }
 
        SoloChanged (); /* EMIT SIGNAL */
index 45d6f6efcedc6040099eea9d85afc45a9e173e4e..4d5ffbffa74ae5d93080238092f1f633e566072c 100644 (file)
@@ -3875,7 +3875,7 @@ Session::config_changed (std::string p, bool ours)
        } else if (p == "solo-control-is-listen-control") {
                solo_control_mode_changed ();
        } else if (p == "solo-mute-gain") {
-               _solo_cut_control->Changed();
+               _solo_cut_control->Changed (true, Controllable::NoGroup);
        } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
                last_timecode_valid = false;
        } else if (p == "playback-buffer-seconds") {
index 414f545f72813fb0e980b856e8c0e25c6e89513e..8aebf0925901aa38ec199d16fced11c91da576ed 100644 (file)
@@ -291,7 +291,7 @@ Track::prep_record_enabled (bool yn, Controllable::GroupControlDisposition group
 }
 
 void
-Track::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_override)
+Track::set_record_enabled (bool yn, Controllable::GroupControlDisposition gcd)
 {
        if (_diskstream->record_safe ()) {
            return;
@@ -305,14 +305,14 @@ Track::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_
                return;
        }
 
-       if (use_group (group_override, &RouteGroup::is_recenable)) {
+       if (use_group (gcd, &RouteGroup::is_recenable)) {
                _route_group->apply (&Track::set_record_enabled, yn, Controllable::NoGroup);
                return;
        }
 
        _diskstream->set_record_enabled (yn);
 
-       _rec_enable_control->Changed ();
+       _rec_enable_control->Changed (true, gcd);
 }
 
 bool
@@ -1151,7 +1151,7 @@ Track::set_monitoring (MonitorChoice mc, Controllable::GroupControlDisposition g
                }
 
                MonitoringChanged (); /* EMIT SIGNAL */
-               _monitoring_control->Changed (); /* EMIT SIGNAL */
+               _monitoring_control->Changed (true, gcd);
        }
 }
 
index cd26ff019f09ca3924c2eeb1c9dd22e07193bbfe..078671c91b4bf5318237437f90970e3b06f041a5 100644 (file)
@@ -126,7 +126,7 @@ class LIBPBD_API Controllable : public PBD::StatefulDestructible {
 
        static PBD::Signal1<void,Controllable*> Destroyed;
 
-       PBD::Signal0<void> Changed;
+       PBD::Signal2<void,bool,PBD::Controllable::GroupControlDisposition> Changed;
 
        int set_state (const XMLNode&, int version);
        XMLNode& get_state ();