add Session::routes_solo_changed(), a plural method which makes changing many route...
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 27 Jul 2015 13:41:42 +0000 (09:41 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 27 Jul 2015 13:41:57 +0000 (09:41 -0400)
Code originally by Grygorii Zharun in Tracks

libs/ardour/ardour/session.h
libs/ardour/session.cc
libs/ardour/session_rtevents.cc

index f75e38cff657a2a182e3da733116b38b8b7cc8bc..5517f0e4e357cab426cf1b8cd1da3ea73f966bc6 100644 (file)
@@ -1522,6 +1522,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void route_listen_changed (void *src, 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 routes_solo_changed (boost::shared_ptr<RouteList> solo_change_routes);
        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 bff71f002be0f7e8436d8dec1ab850b312a8d46c..dfeb800abe9bf0d154e35acda0d40b688f03c3cf 100644 (file)
@@ -3528,6 +3528,120 @@ Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
        }
 }
 
+void
+Session::routes_solo_changed (boost::shared_ptr<RouteList> solo_change_routes)
+{
+       if (solo_update_disabled) {
+               // We know already
+               DEBUG_TRACE (DEBUG::Solo, "solo update disabled - changed ignored\n");
+               return;
+       }
+
+       if (solo_change_routes->empty() ) {
+               return;
+       }
+
+       boost::shared_ptr<RouteList> non_solo_change_routes (new RouteList);
+       boost::shared_ptr<RouteList> r = routes.reader ();
+       int32_t delta;
+
+       std::set_difference (r->begin(), r->end(),
+                            solo_change_routes->begin(), solo_change_routes->end(),
+                            std::back_inserter(*non_solo_change_routes) );
+
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("propagate solo change, delta = %1\n", delta));
+
+       solo_update_disabled = true;
+       RouteList uninvolved;
+
+       for (RouteList::iterator route = solo_change_routes->begin(); route != solo_change_routes->begin(); ++route) {
+
+               if ((*route)->self_soloed() ) {
+                       delta = 1;
+               } else {
+                       delta = -1;
+               }
+
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("%1\n", (*route)->name()));
+
+               for (RouteList::iterator i = non_solo_change_routes->begin(); i != non_solo_change_routes->end(); ++i) {
+                       bool via_sends_only;
+                       bool in_signal_flow;
+
+                       if ((*i) == *route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ) {
+                               continue;
+                       }
+
+                       in_signal_flow = false;
+
+                       DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed from %1\n", (*i)->name()));
+
+                       if ((*i)->feeds (*route, &via_sends_only)) {
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a feed from %1\n", (*i)->name()));
+                               if (!via_sends_only) {
+                                       if (!(*route)->soloed_by_others_upstream()) {
+                                               (*i)->mod_solo_by_others_downstream (delta);
+                                       }
+                               } else {
+                                       DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a send-only feed from %1\n", (*i)->name()));
+                               }
+                               in_signal_flow = true;
+                       } else {
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tno feed from %1\n", (*i)->name()));
+                       }
+
+                       DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed to %1\n", (*i)->name()));
+
+                       if ((*route)->feeds (*i, &via_sends_only)) {
+                               /* propagate solo upstream only if routing other than
+                                  sends is involved, but do consider the other route
+                                  (*i) to be part of the signal flow even if only
+                                  sends are involved.
+                               */
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 feeds %2 via sends only %3 sboD %4 sboU %5\n",
+                                                                         (*route)->name(),
+                                                                         (*i)->name(),
+                                                                         via_sends_only,
+                                                                         (*route)->soloed_by_others_downstream(),
+                                                                         (*route)->soloed_by_others_upstream()));
+                               if (!via_sends_only) {
+                                       if (!(*route)->soloed_by_others_downstream()) {
+                                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
+                                               (*i)->mod_solo_by_others_upstream (delta);
+                                       } else {
+                                               DEBUG_TRACE (DEBUG::Solo, "\talready soloed by others downstream\n");
+                                       }
+                               } else {
+                                       DEBUG_TRACE (DEBUG::Solo, string_compose ("\tfeed to %1 ignored, sends-only\n", (*i)->name()));
+                               }
+                               in_signal_flow = true;
+                       } else {
+                               DEBUG_TRACE (DEBUG::Solo, "\tno feed to\n");
+                       }
+
+                       if (!in_signal_flow) {
+                               uninvolved.push_back (*i);
+                       }
+               }
+       }
+       solo_update_disabled = false;
+       DEBUG_TRACE (DEBUG::Solo, "propagation complete\n");
+
+       update_route_solo_state ();
+
+       /* now notify that the mute state of the routes not involved in the signal
+          pathway of the just-solo-changed route may have altered.
+       */
+
+       for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1\n", (*i)->name() ));
+               (*i)->mute_changed (this);
+       }
+
+       SoloChanged (); /* EMIT SIGNAL */
+       set_dirty();
+}
+
 void
 Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_ptr<Route> wpr)
 {
index 11d8319c0d7b4cb0a8d709d37b17d1026ddc57e0..b00c4c1ebf79c484c01bc099ee4d68eafd1e02f0 100644 (file)
@@ -62,12 +62,17 @@ Session::set_solo (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeve
 void
 Session::rt_set_solo (boost::shared_ptr<RouteList> rl, bool yn, bool /* group_override */)
 {
+       solo_update_disabled = true;
+       
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                if (!(*i)->is_auditioner()) {
                        (*i)->set_solo (yn, this);
                }
        }
 
+       solo_update_disabled = false;
+       routes_solo_changed (rl);
+
        set_dirty();
 }