clear all solo state should affect VCAs too
[ardour.git] / libs / ardour / session.cc
index 7658ff270d066bff56a95af88285f31559a0e7bf..55cd1f9ae829df570ff3704c46e15c92344140bc 100644 (file)
 #include "ardour/user_bundle.h"
 #include "ardour/utils.h"
 #include "ardour/vca_manager.h"
+#include "ardour/vca.h"
 
 #include "midi++/port.h"
 #include "midi++/mmc.h"
@@ -324,6 +325,7 @@ Session::Session (AudioEngine &eng,
        pthread_cond_init (&_auto_connect_cond, 0);
 
        init_name_id_counter (1); // reset for new sessions, start at 1
+       VCA::set_next_vca_number (1); // reset for new sessions, start at 1
 
        pre_engine_init (fullpath);
 
@@ -3406,7 +3408,7 @@ 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->solo_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
+               r->solo_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2,wpr));
                r->solo_isolate_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
                r->mute_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
 
@@ -3701,12 +3703,14 @@ Session::route_listen_changed (Controllable::GroupControlDisposition group_overr
                return;
        }
 
-       if (route->listening_via_monitor ()) {
+       assert (Config->get_solo_control_is_listen_control());
+
+       if (route->solo_control()->soloed_by_self_or_masters()) {
 
                if (Config->get_exclusive_solo()) {
 
                        RouteGroup* rg = route->route_group ();
-                       const bool group_already_accounted_for = route->use_group (group_override, &RouteGroup::is_solo);
+                       const bool group_already_accounted_for = (group_override == Controllable::ForGroup);
 
                        boost::shared_ptr<RouteList> r = routes.reader ();
 
@@ -3772,11 +3776,9 @@ Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
 }
 
 void
-Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override,  boost::weak_ptr<Route> wpr)
+Session::route_solo_changed (bool self_solo_changed, Controllable::GroupControlDisposition group_override,  boost::weak_ptr<Route> wpr)
 {
-       cerr << "route solo change (self ? " << self_solo_change << endl;
-
-       DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_changed));
 
        boost::shared_ptr<Route> route (wpr.lock());
 
@@ -3789,20 +3791,27 @@ Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDi
                return;
        }
 
-       if (!self_solo_change) {
-               // session doesn't care about changes to soloed-by-others
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: self %2 masters %3 transition %4\n", route->name(), route->self_soloed(), route->solo_control()->get_masters_value(), route->solo_control()->transitioned_into_solo()));
+
+       if (route->solo_control()->transitioned_into_solo() == 0) {
+               /* route solo changed by upstream/downstream; not interesting
+                  to Session.
+               */
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 not self-soloed nor soloed by master (%2), ignoring\n", route->name(), route->solo_control()->get_masters_value()));
                return;
        }
 
-       boost::shared_ptr<RouteList> r = routes.reader ();
-       int32_t delta;
-
-       if (route->self_soloed()) {
-               delta = 1;
-       } else {
-               delta = -1;
+       if (route->solo_control()->transitioned_into_solo() == 0) {
+               /* reason for being soloed changed (e.g. master went away, we
+                * took over the master state), but actual status did
+                * not. nothing to do.
+                */
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: solo change was change in reason, not status\n", route->name()));
        }
 
+       boost::shared_ptr<RouteList> r = routes.reader ();
+       int32_t delta = route->solo_control()->transitioned_into_solo ();
+
        /* the route may be a member of a group that has shared-solo
         * semantics. If so, then all members of that group should follow the
         * solo of the changed route. But ... this is optional, controlled by a
@@ -3909,11 +3918,11 @@ Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDi
                           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()));
+                                                                 route->name(),
+                                                                 (*i)->name(),
+                                                                 via_sends_only,
+                                                                 route->soloed_by_others_downstream(),
+                                                                 route->soloed_by_others_upstream()));
                        if (!via_sends_only) {
                                //NB. Triggers Invert Push, which handles soloed by downstream
                                DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
@@ -3964,16 +3973,17 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
        }
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if ((*i)->can_solo() && (*i)->self_soloed()) {
-                       something_soloed = true;
-               }
-
-               if (!(*i)->is_auditioner() && (*i)->listening_via_monitor()) {
+               if ((*i)->can_solo()) {
                        if (Config->get_solo_control_is_listen_control()) {
-                               listeners++;
-                               something_listening = true;
+                               if ((*i)->self_soloed() || (*i)->solo_control()->get_masters_value()) {
+                                       listeners++;
+                                       something_listening = true;
+                               }
                        } else {
                                (*i)->set_listen (false);
+                               if ((*i)->can_solo() && ((*i)->self_soloed() || (*i)->solo_control()->get_masters_value())) {
+                                       something_soloed = true;
+                               }
                        }
                }
 
@@ -6118,8 +6128,16 @@ Session::listen_position_changed ()
 void
 Session::solo_control_mode_changed ()
 {
-       /* cancel all solo or all listen when solo control mode changes */
-       clear_all_solo_state (get_routes());
+       if (soloing() || listening()) {
+               /* We can't use ::clear_all_solo_state() here because during
+                  session loading at program startup, that will queue a call
+                  to rt_clear_all_solo_state() that will not execute until
+                  AFTER solo states have been established (thus throwing away
+                  the session's saved solo state). So just explicitly turn
+                  them all off.
+               */
+               set_controls (route_list_to_control_list (get_routes(), &Route::solo_control), 0.0, Controllable::NoGroup);
+       }
 }
 
 /** Called when a property of one of our route groups changes */