From c55b659f391fba74704c474d7948a3976057c92a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 27 Jul 2015 09:41:42 -0400 Subject: add Session::routes_solo_changed(), a plural method which makes changing many route solo states much faster. Code originally by Grygorii Zharun in Tracks --- libs/ardour/ardour/session.h | 1 + libs/ardour/session.cc | 114 ++++++++++++++++++++++++++++++++++++++++ libs/ardour/session_rtevents.cc | 5 ++ 3 files changed, 120 insertions(+) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index f75e38cff6..5517f0e4e3 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1522,6 +1522,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop void route_listen_changed (void *src, boost::weak_ptr); void route_mute_changed (void *src); void route_solo_changed (bool self_solo_change, void *src, boost::weak_ptr); + void routes_solo_changed (boost::shared_ptr solo_change_routes); void route_solo_isolated_changed (void *src, boost::weak_ptr); void update_route_solo_state (boost::shared_ptr r = boost::shared_ptr()); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index bff71f002b..dfeb800abe 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3528,6 +3528,120 @@ Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr wpr) } } +void +Session::routes_solo_changed (boost::shared_ptr 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 non_solo_change_routes (new RouteList); + boost::shared_ptr 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 wpr) { diff --git a/libs/ardour/session_rtevents.cc b/libs/ardour/session_rtevents.cc index 11d8319c0d..b00c4c1ebf 100644 --- a/libs/ardour/session_rtevents.cc +++ b/libs/ardour/session_rtevents.cc @@ -62,12 +62,17 @@ Session::set_solo (boost::shared_ptr rl, bool yn, SessionEvent::RTeve void Session::rt_set_solo (boost::shared_ptr 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(); } -- cgit v1.2.3