implement solo group override
authorRobin Gareus <robin@gareus.org>
Tue, 6 Oct 2015 23:44:02 +0000 (01:44 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 6 Oct 2015 23:44:02 +0000 (01:44 +0200)
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_rtevents.cc

index cf7ec90fd1dfe37d29d403fe25ba5b9dc1ecbea9..94d8837246ed2601189033e14bb7b76dafb23df2 100644 (file)
@@ -158,7 +158,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        /* controls use set_solo() to modify this route's solo state
         */
 
-       void set_solo (bool yn, void *src);
+       void set_solo (bool yn, void *src, bool group_override = false);
        bool soloed () const { return self_soloed () || soloed_by_others (); }
        void clear_all_solo_state ();
 
@@ -173,7 +173,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        void set_solo_safe (bool yn, void *src);
        bool solo_safe() const;
 
-       void set_listen (bool yn, void* src);
+       void set_listen (bool yn, void* src, bool group_override = false);
        bool listening_via_monitor () const;
        void enable_monitor_send ();
 
@@ -286,8 +286,8 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        PBD::Signal0<void>       active_changed;
        PBD::Signal0<void>       phase_invert_changed;
        PBD::Signal0<void>       denormal_protection_changed;
-       PBD::Signal1<void,void*> listen_changed;
-       PBD::Signal2<void,bool,void*> solo_changed;
+       PBD::Signal2<void,void*,bool> listen_changed;
+       PBD::Signal3<void,bool,void*,bool> solo_changed;
        PBD::Signal1<void,void*> solo_safe_changed;
        PBD::Signal1<void,void*> solo_isolated_changed;
        PBD::Signal1<void,void*> comment_changed;
index 144b3c8670923ebdd45a36901ecef1dfb3e3abb9..4e9be4d02e33d8cd4d02165c34b2eff725f6ef9d 100644 (file)
@@ -1536,9 +1536,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        /* mixer stuff */
 
-       void route_listen_changed (void *src, boost::weak_ptr<Route>);
+       void route_listen_changed (bool leave_group_alone, boost::weak_ptr<Route>);
        void route_mute_changed (void *src);
-       void route_solo_changed (bool self_solo_change, void *src, boost::weak_ptr<Route>);
+       void route_solo_changed (bool self_solo_change, bool leave_group_alone, boost::weak_ptr<Route>);
        void route_solo_isolated_changed (void *src, boost::weak_ptr<Route>);
        void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
 
index b3444e0b9085de09e11f0a4ace515e10780ee6e3..eb98a2388f367fdc61f29e18daaf3363420c51e2 100644 (file)
@@ -764,14 +764,19 @@ Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t
 }
 
 void
-Route::set_listen (bool yn, void* src)
+Route::set_listen (bool yn, void* src, bool group_override)
 {
        if (_solo_safe) {
                return;
        }
 
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_solo()) {
-               _route_group->foreach_route (boost::bind (&Route::set_listen, _1, yn, _route_group));
+       bool group_active = _route_group && _route_group->is_active() && _route_group->is_solo();
+       if (group_override && _route_group) {
+               group_active = !group_active;
+       }
+
+       if (_route_group && src != _route_group && group_active) {
+               _route_group->foreach_route (boost::bind (&Route::set_listen, _1, yn, _route_group, group_override));
                return;
        }
 
@@ -786,7 +791,7 @@ Route::set_listen (bool yn, void* src)
                        }
                        _mute_master->set_soloed_by_others (false);
 
-                       listen_changed (src); /* EMIT SIGNAL */
+                       listen_changed (src, group_active); /* EMIT SIGNAL */
                }
        }
 }
@@ -848,12 +853,12 @@ Route::clear_all_solo_state ()
 
        if (emit_changed) {
                set_mute_master_solo ();
-               solo_changed (false, this); /* EMIT SIGNAL */
+               solo_changed (false, this, false); /* EMIT SIGNAL */
        }
 }
 
 void
-Route::set_solo (bool yn, void *src)
+Route::set_solo (bool yn, void *src, bool group_override)
 {
        if (_solo_safe) {
                DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 ignore solo change due to solo-safe\n", name()));
@@ -865,8 +870,13 @@ Route::set_solo (bool yn, void *src)
                return;
        }
 
-       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_solo()) {
-               _route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, _route_group));
+       // explicit XOR
+       bool group_active = _route_group && _route_group->is_active() && _route_group->is_solo();
+       if (group_override && _route_group) {
+               group_active = !group_active;
+       }
+       if (_route_group && src != _route_group && group_active) {
+               _route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, _route_group, group_override));
                return;
        }
 
@@ -876,7 +886,7 @@ Route::set_solo (bool yn, void *src)
        if (self_soloed() != yn) {
                set_self_solo (yn);
                set_mute_master_solo ();
-               solo_changed (true, src); /* EMIT SIGNAL */
+               solo_changed (true, src, group_active); /* EMIT SIGNAL */
                _solo_control->Changed (); /* EMIT SIGNAL */
        }
 
@@ -953,7 +963,7 @@ Route::mod_solo_by_others_upstream (int32_t delta)
        }
 
        set_mute_master_solo ();
-       solo_changed (false, this); /* EMIT SIGNAL */
+       solo_changed (false, this, false); /* EMIT SIGNAL */
 }
 
 void
@@ -975,7 +985,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 ();
-       solo_changed (false, this); /* EMIT SIGNAL */
+       solo_changed (false, this, false); /* EMIT SIGNAL */
 }
 
 void
index 9d0c4f9662adcfc9cd723f41a5a30ffea46f93c7..e22fe57c993c0aed56df0d0bd4035c94e207fb3c 100644 (file)
@@ -3206,8 +3206,8 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                boost::weak_ptr<Route> wpr (*x);
                boost::shared_ptr<Route> r (*x);
 
-               r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
-               r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
+               r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _2, wpr));
+               r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _3, wpr));
                r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, _1, wpr));
                r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1));
                r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
@@ -3490,11 +3490,11 @@ Session::route_mute_changed (void* /*src*/)
 }
 
 void
-Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
+Session::route_listen_changed (bool leave_group_alone, boost::weak_ptr<Route> wpr)
 {
        boost::shared_ptr<Route> route = wpr.lock();
        if (!route) {
-               error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
+               error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_listen_changed")) << endmsg;
                return;
        }
 
@@ -3503,7 +3503,6 @@ Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
                if (Config->get_exclusive_solo()) {
                        /* new listen: disable all other listen, except solo-grouped channels */
                        RouteGroup* rg = route->route_group ();
-                       bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
                        boost::shared_ptr<RouteList> r = routes.reader ();
                        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                                if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() || (leave_group_alone && ((*i)->route_group() == rg))) {
@@ -3553,7 +3552,7 @@ Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
 }
 
 void
-Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_ptr<Route> wpr)
+Session::route_solo_changed (bool self_solo_change, bool leave_group_alone,  boost::weak_ptr<Route> wpr)
 {
        DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
 
@@ -3575,8 +3574,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
        }
 
        RouteGroup* rg = route->route_group ();
-       bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
-
        if (delta == 1 && Config->get_exclusive_solo()) {
 
                /* new solo: disable all other solos, but not the group if its solo-enabled */
index d001b239baa62c8c183d0fb1548d2aeb1296f9e1..2b24b59970175c4e581a3c38edf3ce85d1ae69ec 100644 (file)
@@ -77,13 +77,12 @@ Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeve
        queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo));
 }
 
-
 void
-Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool /* group_override */)
+Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner()) {
-                       (*i)->set_solo (yn, this);
+                       (*i)->set_solo (yn, this, group_override);
                }
        }
 
@@ -132,11 +131,11 @@ Session::set_listen (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTe
 }
 
 void
-Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool /*group_override*/ )
+Session::rt_set_listen (boost::shared_ptr<RouteList> rl, bool yn, bool group_override)
 {
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner()) {
-                       (*i)->set_listen (yn, this);
+                       (*i)->set_listen (yn, this, group_override);
                }
        }