fix various stuck-solo cases:
authorRobin Gareus <robin@gareus.org>
Sun, 4 Oct 2015 22:08:55 +0000 (00:08 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 4 Oct 2015 22:08:55 +0000 (00:08 +0200)
* solo groups
* cancel-solo
* SIP <> AFL/PFL changes

The optimized plural-form route_solo_changed() relied on the false
premise that solo-groups and port-connections are disjoint sets.

-=-

e.g. "cancel all solo" calls set_solo(get_routes(), false);
Since All routes are affected, the "non_solo_change" set is empty, and
no changes were propagated up/downstream.

Routes that indirectly change state as group-members, wrongly end up in
the "non_solo_change" list instead of the "solo_change" list.

If a route feeds another in the same group, no changes were propagated.

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

index 2bc992bb108538dc64b312196ebea422feccb1e8..2e6024badbe92691ff52d3395f429190bf8c60a3 100644 (file)
@@ -1536,12 +1536,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        /* mixer stuff */
 
-       bool solo_update_disabled;
-
        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 791c8d265670493ad58a3c5e4380a2c8a72342c9..fd7458fec98f09bcee52f8cd49b5c1664abd5446 100644 (file)
@@ -264,7 +264,6 @@ Session::Session (AudioEngine &eng,
        , _route_deletion_in_progress (false)
        , destructive_index (0)
        , _track_number_decimals(1)
-       , solo_update_disabled (false)
        , default_fade_steepness (0)
        , default_fade_msecs (0)
        , _total_free_4k_blocks (0)
@@ -3552,120 +3551,6 @@ 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->end(); ++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)
 {
@@ -3676,12 +3561,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                return;
        }
 
-       if (solo_update_disabled) {
-               // We know already
-               DEBUG_TRACE (DEBUG::Solo, "solo update disabled - changed ignored\n");
-               return;
-       }
-
        boost::shared_ptr<Route> route = wpr.lock ();
        assert (route);
 
@@ -3712,8 +3591,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
 
        DEBUG_TRACE (DEBUG::Solo, string_compose ("propagate solo change, delta = %1\n", delta));
 
-       solo_update_disabled = true;
-
        RouteList uninvolved;
 
        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1\n", route->name()));
@@ -3779,7 +3656,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                }
        }
 
-       solo_update_disabled = false;
        DEBUG_TRACE (DEBUG::Solo, "propagation complete\n");
 
        update_route_solo_state (r);
index 5e20421ccad8bc43f00853cb9d4900edc68abd0e..db334932f13216dde01590bd7013df454c880956 100644 (file)
@@ -62,18 +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();
+       /* XXX boost::shared_ptr<RouteList>  goes out of scope here and is likley free()ed in RT context
+        * because boost's shared_ptr does reference counting and free/delete in the dtor.
+        * (this also applies to other rt_  methods here)
+        */
 }
 
 void