summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-07-27 09:41:42 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2015-07-27 09:41:57 -0400
commitc55b659f391fba74704c474d7948a3976057c92a (patch)
tree44e349c2ba11021d59ca642408314018ad45a5f3
parent949a45b748546c125e69d794b0f73565f376ab60 (diff)
add Session::routes_solo_changed(), a plural method which makes changing many route solo states much faster.
Code originally by Grygorii Zharun in Tracks
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/session.cc114
-rw-r--r--libs/ardour/session_rtevents.cc5
3 files changed, 120 insertions, 0 deletions
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<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>());
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
@@ -3529,6 +3529,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)
{
DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
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<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();
}