merge fix
[ardour.git] / libs / ardour / route.cc
index 4b4e450c34bacd2053a24b45e69893db85edd774..34d92b7a7e30605d5ae9def5288614c32bd615ee 100644 (file)
@@ -60,6 +60,7 @@
 #include "ardour/port.h"
 #include "ardour/port_insert.h"
 #include "ardour/processor.h"
+#include "ardour/profile.h"
 #include "ardour/route.h"
 #include "ardour/route_group.h"
 #include "ardour/send.h"
@@ -96,6 +97,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _soloed_by_others_upstream (0)
        , _soloed_by_others_downstream (0)
        , _solo_isolated (0)
+       , _solo_isolated_by_upstream (0)
        , _denormal_protection (false)
        , _recordable (true)
        , _silent (false)
@@ -112,15 +114,22 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _initial_io_setup (false)
        , _custom_meter_position_noted (false)
 {
-       if (is_master()) {
-               _meter_type = MeterK20;
-       }
        processor_max_streams.reset();
 }
 
 int
 Route::init ()
 {
+       /* set default meter type */
+       if (is_master()) {
+               _meter_type = Config->get_meter_type_master ();
+       }
+       else if (dynamic_cast<Track*>(this)) {
+               _meter_type = Config->get_meter_type_track ();
+       } else {
+               _meter_type = Config->get_meter_type_bus ();
+       }
+
        /* add standard controls */
 
        _solo_control.reset (new SoloControllable (X_("solo"), shared_from_this ()));
@@ -833,6 +842,14 @@ Route::set_solo (bool yn, void *src)
                solo_changed (true, src); /* EMIT SIGNAL */
                _solo_control->Changed (); /* EMIT SIGNAL */
        }
+
+       /* XXX TRACKS DEVELOPERS: THIS LOGIC SUGGESTS THAT YOU ARE NOT AWARE OF
+          Config->get_solo_mute_overrride().
+       */
+
+       if (yn && Profile->get_trx()) {
+               set_mute (false, src);
+       }
 }
 
 void
@@ -935,6 +952,28 @@ Route::set_mute_master_solo ()
        _mute_master->set_soloed (self_soloed() || soloed_by_others_downstream() || soloed_by_others_upstream());
 }
 
+void
+Route::mod_solo_isolated_by_upstream (bool yn, void* src)
+{
+       bool old = solo_isolated ();
+
+       if (!yn) {
+               if (_solo_isolated_by_upstream >= 1) {
+                       _solo_isolated_by_upstream--;
+               } else {
+                       _solo_isolated_by_upstream = 0;
+               }
+       } else {
+               _solo_isolated_by_upstream++;
+       }
+
+       if (solo_isolated() != old) {
+               /* solo isolated status changed */
+               _mute_master->set_solo_ignore (yn);
+               solo_isolated_changed (src);
+       }
+}
+
 void
 Route::set_solo_isolated (bool yn, void *src)
 {
@@ -947,25 +986,6 @@ Route::set_solo_isolated (bool yn, void *src)
                return;
        }
 
-       /* forward propagate solo-isolate status to everything fed by this route, but not those via sends only */
-
-       boost::shared_ptr<RouteList> routes = _session.get_routes ();
-       for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
-
-               if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
-                       continue;
-               }
-
-               bool sends_only;
-               bool does_feed = direct_feeds_according_to_graph (*i, &sends_only); // we will recurse anyway, so don't use ::feeds()
-
-               if (does_feed && !sends_only) {
-                       (*i)->set_solo_isolated (yn, (*i)->route_group());
-               }
-       }
-
-       /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
-
        bool changed = false;
 
        if (yn) {
@@ -984,15 +1004,37 @@ Route::set_solo_isolated (bool yn, void *src)
                }
        }
 
-       if (changed) {
-               solo_isolated_changed (src);
+       
+       if (!changed) {
+               return;
+       }
+       
+       /* forward propagate solo-isolate status to everything fed by this route, but not those via sends only */
+
+       boost::shared_ptr<RouteList> routes = _session.get_routes ();
+       for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
+               
+               if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+                       continue;
+               }
+               
+               bool sends_only;
+               bool does_feed = feeds (*i, &sends_only);
+               
+               if (does_feed && !sends_only) {
+                       (*i)->mod_solo_isolated_by_upstream (yn, src);
+               }
        }
+       
+       /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
+
+       solo_isolated_changed (src);
 }
 
 bool
 Route::solo_isolated () const
 {
-       return _solo_isolated > 0;
+       return (_solo_isolated > 0) || (_solo_isolated_by_upstream > 0);
 }
 
 void
@@ -1033,6 +1075,17 @@ Route::muted () const
        return _mute_master->muted_by_self();
 }
 
+bool
+Route::muted_by_others () const
+{
+       //master is never muted by others
+       if (is_master())
+               return false;
+               
+       //now check to see if something is soloed (and I am not)
+       return (_session.soloing() && !self_soloed() && !solo_isolated());
+}
+
 #if 0
 static void
 dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
@@ -1188,7 +1241,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
 
                }
 
-               if (activation_allowed && !_session.get_disable_all_loaded_plugins()) {
+               if (activation_allowed && (!_session.get_disable_all_loaded_plugins () || !processor->display_to_user ())) {
                        processor->activate ();
                }
 
@@ -1268,7 +1321,7 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version)
                //A2 uses the "active" flag in the toplevel redirect node, not in the child plugin/IO
                if (i != children.end()) {
                        if ((prop = (*i)->property (X_("active"))) != 0) {
-                               if ( string_is_affirmative (prop->value()) && !_session.get_disable_all_loaded_plugins() )
+                               if ( string_is_affirmative (prop->value()) && (!_session.get_disable_all_loaded_plugins () || !processor->display_to_user () ) )
                                        processor->activate();
                                else
                                        processor->deactivate();
@@ -1896,6 +1949,14 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
                (*p)->configure_io(c->first, c->second);
                processor_max_streams = ChanCount::max(processor_max_streams, c->first);
                processor_max_streams = ChanCount::max(processor_max_streams, c->second);
+
+               boost::shared_ptr<PluginInsert> pi;
+               if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
+                       /* plugins connected via Split Match may have more channels.
+                        * route/scratch buffers are needed for all of them*/
+                       processor_max_streams = ChanCount::max(processor_max_streams, pi->input_streams());
+                       processor_max_streams = ChanCount::max(processor_max_streams, pi->natural_input_streams());
+               }
                out = c->second;
 
                if (boost::dynamic_pointer_cast<Delivery> (*p)
@@ -4140,7 +4201,7 @@ Route::set_processor_positions ()
        bool had_amp = false;
        for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->set_pre_fader (!had_amp);
-               if (boost::dynamic_pointer_cast<Amp> (*i)) {
+               if (*i == _amp) {
                        had_amp = true;
                }
        }
@@ -4335,7 +4396,7 @@ Route::setup_invisible_processors ()
        /* find the amp */
 
        ProcessorList::iterator amp = new_processors.begin ();
-       while (amp != new_processors.end() && boost::dynamic_pointer_cast<Amp> (*amp) == 0) {
+       while (amp != new_processors.end() && *amp != _amp) {
                ++amp;
        }
 
@@ -4468,6 +4529,12 @@ Route::setup_invisible_processors ()
 
        _processors = new_processors;
 
+       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+               if (!(*i)->display_to_user () && !(*i)->active ()) {
+                       (*i)->activate ();
+               }
+       }
+
        DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: setup_invisible_processors\n", _name));
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1\n", (*i)->name ()));