[3.0P] dont dump chain(1) in session.cc
[ardour.git] / libs / ardour / route.cc
index 287e3c219bd0cd97d77d5b836c931ae4c69aa826..4dcdcf1898a621d4a2018c08386e1565a4a82f24 100644 (file)
@@ -58,6 +58,7 @@
 #include "ardour/session.h"
 #include "ardour/timestamps.h"
 #include "ardour/utils.h"
+#include "ardour/graph.h"
 
 #include "i18n.h"
 
@@ -72,6 +73,7 @@ PBD::Signal0<void> Route::RemoteControlIDChange;
 Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        : SessionObject (sess, name)
        , AutomatableControls (sess)
+       , GraphNode( sess.route_graph )
         , _active (true)
         , _initial_delay (0)
         , _roll_delay (0)
@@ -90,11 +92,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _solo_control (new SoloControllable (X_("solo"), *this))
        , _mute_control (new MuteControllable (X_("mute"), *this))
        , _mute_master (new MuteMaster (sess, name))
-        , _mute_points (MuteMaster::AllPoints)
-        , _path_muted_by_others (false)
         , _have_internal_generator (false)
-        , _physically_connected (false)
-        , _graph_level (-1)
         , _solo_safe (false)
        , _default_type (default_type)
         , _remote_control_id (0)
@@ -125,7 +123,7 @@ Route::init ()
 
        /* add amp processor  */
 
-       _amp.reset (new Amp (_session, _mute_master));
+       _amp.reset (new Amp (_session));
        add_processor (_amp, PostFader);
 
        /* add standard processors: meter, main outs, monitor out */
@@ -276,7 +274,7 @@ Route::ensure_track_or_route_name(string name, Session &session)
        string newname = name;
 
        while (!session.io_name_is_legal (newname)) {
-               newname = bump_name_once (newname);
+               newname = bump_name_once (newname, '.');
        }
 
        return newname;
@@ -452,25 +450,17 @@ Route::process_output_buffers (BufferSet& bufs,
           and go ....
           ----------------------------------------------------------------------------------------- */
 
-       Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
-
-       if (rm.locked()) {
-                //cerr << name() << " upstream solo " << _soloed_by_others_upstream
-                // << " downstream solo " << _soloed_by_others_downstream
-                // << " self " << _self_solo
-                //<< endl;
-               for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-
-                       if (bufs.count() != (*i)->input_streams()) {
-                               cerr << _name << " bufs = " << bufs.count()
-                                    << " input for " << (*i)->name() << " = " << (*i)->input_streams()
-                                    << endl;
-                       }
-                       assert (bufs.count() == (*i)->input_streams());
+       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
 
-                       (*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back());
-                       bufs.set_count ((*i)->output_streams());
+               if (bufs.count() != (*i)->input_streams()) {
+                       cerr << _name << " bufs = " << bufs.count()
+                            << " input for " << (*i)->name() << " = " << (*i)->input_streams()
+                            << endl;
                }
+               assert (bufs.count() == (*i)->input_streams());
+               
+               (*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back());
+               bufs.set_count ((*i)->output_streams());
        }
 }
 
@@ -490,7 +480,7 @@ Route::passthru (sframes_t start_frame, sframes_t end_frame, nframes_t nframes,
        assert (bufs.available() >= input_streams());
 
        if (_input->n_ports() == ChanCount::ZERO) {
-               silence (nframes);
+               silence_unlocked (nframes);
        }
 
        bufs.set_count (input_streams());
@@ -540,8 +530,10 @@ Route::set_listen (bool yn, void* src)
                if (yn != _monitor_send->active()) {
                        if (yn) {
                                _monitor_send->activate ();
-                       } else {
+                                _mute_master->set_soloed (true);
+                        } else {
                                _monitor_send->deactivate ();
+                                _mute_master->set_soloed (false);
                        }
 
                        listen_changed (src); /* EMIT SIGNAL */
@@ -607,6 +599,8 @@ Route::mod_solo_by_others_upstream (int32_t delta)
                 return;
         }
 
+        uint32_t old_sbu = _soloed_by_others_upstream;
+
        if (delta < 0) {
                if (_soloed_by_others_upstream >= (uint32_t) abs (delta)) {
                        _soloed_by_others_upstream += delta;
@@ -617,14 +611,36 @@ Route::mod_solo_by_others_upstream (int32_t delta)
                _soloed_by_others_upstream += delta;
        }
 
+        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbU delta %2 = %3 old = %4 sbd %5 ss %6 exclusive %7\n",
+                                                  name(), delta, _soloed_by_others_upstream, old_sbu, 
+                                                  _soloed_by_others_downstream, _self_solo, Config->get_exclusive_solo()));
+
         /* push the inverse solo change to everything that feeds us. 
+           
+           This is important for solo-within-group. When we solo 1 track out of N that
+           feed a bus, that track will cause mod_solo_by_upstream (+1) to be called
+           on the bus. The bus then needs to call mod_solo_by_downstream (-1) on all
+           tracks that feed it. This will silence them if they were audible because
+           of a bus solo, but the newly soloed track will still be audible (because 
+           it is self-soloed).
+           
+           but .. do this only when we are being told to solo-by-upstream (i.e delta = +1),
+           not in reverse.
          */
 
-        for (FedBy::iterator i = _fed_by.begin(); i != _fed_by.end(); ++i) {
-                boost::shared_ptr<Route> sr = i->r.lock();
-                if (sr) {
-                        sr->mod_solo_by_others_downstream (-delta);
-                }
+        if ((_self_solo || _soloed_by_others_downstream) &&
+            ((old_sbu == 0 && _soloed_by_others_upstream > 0) || 
+             (old_sbu > 0 && _soloed_by_others_upstream == 0))) {
+                
+                if (delta > 0 || !Config->get_exclusive_solo()) {
+                        DEBUG_TRACE (DEBUG::Solo, "\t ... INVERT push\n");
+                        for (FedBy::iterator i = _fed_by.begin(); i != _fed_by.end(); ++i) {
+                                boost::shared_ptr<Route> sr = i->r.lock();
+                                if (sr) {
+                                        sr->mod_solo_by_others_downstream (-delta);
+                                }
+                        }
+                } 
         }
 
         set_mute_master_solo ();
@@ -638,7 +654,7 @@ Route::mod_solo_by_others_downstream (int32_t delta)
                 return;
         }
 
-       if (delta < 0) {
+        if (delta < 0) {
                if (_soloed_by_others_downstream >= (uint32_t) abs (delta)) {
                        _soloed_by_others_downstream += delta;
                } else {
@@ -648,6 +664,8 @@ Route::mod_solo_by_others_downstream (int32_t delta)
                _soloed_by_others_downstream += delta;
        }
 
+        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream));
+
         set_mute_master_solo ();
         solo_changed (false, this);
 }
@@ -655,19 +673,7 @@ Route::mod_solo_by_others_downstream (int32_t delta)
 void
 Route::set_mute_master_solo ()
 {
-        SoloLevel level;
-
-        if (self_soloed()) {
-                level = SelfSoloed;
-        } else if (soloed_by_others_upstream()) {
-                level = UpstreamSoloed;
-        } else if (soloed_by_others_downstream()) {
-                level = DownstreamSoloed;
-        } else {
-                level = NotSoloed;
-        }
-
-        _mute_master->set_solo_level (level);
+        _mute_master->set_soloed (self_soloed() || soloed_by_others_downstream() || soloed_by_others_upstream());
 }
 
 void
@@ -701,22 +707,27 @@ Route::set_solo_isolated (bool yn, void *src)
 
         /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
 
+        bool changed = false;
+
        if (yn) {
                 if (_solo_isolated == 0) {
                         _mute_master->set_solo_ignore (true);
+                        changed = true;
                 }
                _solo_isolated++;
-                solo_isolated_changed (src);
        } else {
                if (_solo_isolated > 0) {
                        _solo_isolated--;
                         if (_solo_isolated == 0) {
                                 _mute_master->set_solo_ignore (false);
+                                changed = true;
                         }
-                        solo_isolated_changed (src);
                }
        }
 
+        if (changed) {
+                solo_isolated_changed (src);
+        }
 }
 
 bool
@@ -728,11 +739,10 @@ Route::solo_isolated () const
 void
 Route::set_mute_points (MuteMaster::MutePoint mp)
 {
-        _mute_points = mp;
-        _mute_master->set_mute_points (MuteMaster::AllPoints);
+        _mute_master->set_mute_points (mp);
         mute_points_changed (); /* EMIT SIGNAL */
         
-        if (_mute_master->muted()) {
+        if (_mute_master->muted_by_self()) {
                 mute_changed (this); /* EMIT SIGNAL */
         }
 }
@@ -745,8 +755,8 @@ Route::set_mute (bool yn, void *src)
                return;
        }
 
-       if (self_muted() != yn) {
-                _mute_master->set_self_muted (yn);
+       if (muted() != yn) {
+                _mute_master->set_muted_by_self (yn);
                mute_changed (src); /* EMIT SIGNAL */
        }
 }
@@ -754,47 +764,7 @@ Route::set_mute (bool yn, void *src)
 bool
 Route::muted () const
 {
-        return self_muted() || muted_by_others();
-}
-
-bool
-Route::self_muted() const
-{
-       return _mute_master->self_muted ();
-}
-
-bool
-Route::muted_by_others() const
-{
-       return _mute_master->muted_by_others ();
-}
-
-void
-Route::mod_muted_by_others (int delta)
-{
-        if (_solo_isolated) {
-                return;
-        }
-
-        bool old = muted ();
-        _mute_master->mod_muted_by_others (delta);
-        if (old != muted()) {
-                mute_changed (this);
-        }
-}
-
-void
-Route::mod_path_muted_by_others (int32_t delta)
-{
-       if (delta < 0) {
-               if (_path_muted_by_others >= (uint32_t) abs (delta)) {
-                       _path_muted_by_others += delta;
-               } else {
-                       _path_muted_by_others = 0;
-               }
-       } else {
-               _path_muted_by_others += delta;
-       }
+        return _mute_master->muted_by_self();
 }
 
 #if 0
@@ -913,6 +883,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
        }
 
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       set_processor_positions ();
 
        return 0;
 }
@@ -1057,6 +1028,7 @@ Route::add_processors (const ProcessorList& others, ProcessorList::iterator iter
        }
 
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       set_processor_positions ();
 
        return 0;
 }
@@ -1257,6 +1229,7 @@ Route::clear_processors (Placement p)
        processor_max_streams.reset();
        _have_internal_generator = false;
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       set_processor_positions ();
 
        if (!already_deleting) {
                _session.clear_deletion_in_progress();
@@ -1348,6 +1321,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
 
        processor->drop_references ();
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       set_processor_positions ();
 
        return 0;
 }
@@ -1439,6 +1413,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
        }
 
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       set_processor_positions ();
 
        return 0;
 }
@@ -1479,18 +1454,16 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
        uint32_t index = 0;
 
        DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configure processors\n", _name));
-#ifndef NDEBUG
        DEBUG_TRACE (DEBUG::Processors, "{\n");
        for (list<boost::shared_ptr<Processor> >::const_iterator p = _processors.begin(); p != _processors.end(); ++p) {
                DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID = %2\n", (*p)->name(), (*p)->id()));
        }
        DEBUG_TRACE (DEBUG::Processors, "}\n");
-#endif
 
        for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
 
                if ((*p)->can_support_io_configuration(in, out)) {
-                       DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1in = %2 out = %3\n",(*p)->name(), in, out));
+                       DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 in = %2 out = %3\n",(*p)->name(), in, out));
                        configuration.push_back(make_pair(in, out));
                        in = out;
                } else {
@@ -1523,6 +1496,8 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
                _session.ensure_buffers (n_process_buffers ());
        }
 
+       DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configuration complete\n", _name));
+
        _in_configure_processors = false;
        return 0;
 }
@@ -1684,6 +1659,7 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
 
         if (true) {
                 processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+               set_processor_positions ();
         }
 
        return 0;
@@ -2331,6 +2307,7 @@ Route::set_processor_state (const XMLNode& node)
         }
 
         processors_changed (RouteProcessorChange ());
+       set_processor_positions ();
 }
 
 void
@@ -2343,31 +2320,37 @@ Route::curve_reallocate ()
 void
 Route::silence (nframes_t nframes)
 {
-       if (!_silent) {
-
-               _output->silence (nframes);
-
-               {
-                       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       if (!lm.locked()) {
+               return;
+       }
 
-                       if (lm.locked()) {
-                               for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-                                       boost::shared_ptr<PluginInsert> pi;
+       silence_unlocked (nframes);
+}
 
-                                       if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
-                                               // skip plugins, they don't need anything when we're not active
-                                               continue;
-                                       }
+void
+Route::silence_unlocked (nframes_t nframes)
+{
+       /* Must be called with the processor lock held */
+       
+       if (!_silent) {
 
-                                       (*i)->silence (nframes);
-                               }
+               _output->silence (nframes);
 
-                               if (nframes == _session.get_block_size()) {
-                                       // _silent = true;
-                               }
+               for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+                       boost::shared_ptr<PluginInsert> pi;
+                       
+                       if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
+                               // skip plugins, they don't need anything when we're not active
+                               continue;
                        }
+                       
+                       (*i)->silence (nframes);
+               }
+               
+               if (nframes == _session.get_block_size()) {
+                       // _silent = true;
                }
-
        }
 }
 
@@ -2604,12 +2587,6 @@ Route::direct_feeds (boost::shared_ptr<Route> other, bool* only_send)
        return false;
 }
 
-void
-Route::check_physical_connections ()
-{
-        _physically_connected = _output->physically_connected ();
-}
-
 void
 Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors)
 {
@@ -2669,12 +2646,17 @@ int
 Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
                bool session_state_changing, bool /*can_record*/, bool /*rec_monitors_input*/)
 {
+       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       if (!lm.locked()) {
+               return 0;
+       }
+
        if (n_outputs().n_total() == 0) {
                return 0;
        }
 
        if (!_active || n_inputs() == ChanCount::ZERO)  {
-               silence (nframes);
+               silence_unlocked (nframes);
                return 0;
        }
        if (session_state_changing) {
@@ -2684,7 +2666,7 @@ Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
                           
                           XXX note the absurdity of ::no_roll() being called when we ARE rolling!
                        */
-                       silence (nframes);
+                       silence_unlocked (nframes);
                        return 0;
                }
                /* we're really not rolling, so we're either delivery silence or actually
@@ -2704,14 +2686,14 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame)
        if (_roll_delay > nframes) {
 
                _roll_delay -= nframes;
-               silence (nframes);
+               silence_unlocked (nframes);
                /* transport frame is not legal for caller to use */
                return 0;
 
        } else if (_roll_delay > 0) {
 
                nframes -= _roll_delay;
-               silence (_roll_delay);
+               silence_unlocked (_roll_delay);
                /* we've written _roll_delay of samples into the
                   output ports, so make a note of that for
                   future reference.
@@ -2729,22 +2711,19 @@ int
 Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int declick,
             bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */)
 {
-       {
-               // automation snapshot can also be called from the non-rt context
-               // and it uses the processor list, so we try to acquire the lock here
-               Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
-
-               if (lm.locked()) {
-                       automation_snapshot (_session.transport_frame(), false);
-               }
+       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       if (!lm.locked()) {
+               return 0;
        }
+       
+       automation_snapshot (_session.transport_frame(), false);
 
        if (n_outputs().n_total() == 0) {
                return 0;
        }
 
        if (!_active || n_inputs().n_total() == 0) {
-               silence (nframes);
+               silence_unlocked (nframes);
                return 0;
        }
 
@@ -3069,7 +3048,7 @@ Route::MuteControllable::set_value (float val)
 float
 Route::MuteControllable::get_value (void) const
 {
-       return route.self_muted() ? 1.0f : 0.0f;
+       return route.muted() ? 1.0f : 0.0f;
 }
 
 void
@@ -3381,8 +3360,22 @@ Route::has_io_processor_named (const string& name)
         return false;
 }
 
+MuteMaster::MutePoint
+Route::mute_points () const
+{
+       return _mute_master->mute_points ();
+}
+
 void
-Route::set_graph_level (int32_t l)
+Route::set_processor_positions ()
 {
-        _graph_level = l;
+       Glib::RWLock::ReaderLock lm (_processor_lock);
+
+       bool had_amp = false;
+       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+               (*i)->set_pre_fader (!had_amp);
+               if (boost::dynamic_pointer_cast<Amp> (*i)) {
+                       had_amp = true;
+               }
+       }
 }