fix --disable-plugins (bypass ‘em all)
[ardour.git] / libs / ardour / route.cc
index 8b1a183de5d26de55748ce4596e87caf7aece6fc..36adbfa148f6b4e9442a5bb5495a80e78703e3f3 100644 (file)
@@ -102,6 +102,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _order_key (0)
        , _has_order_key (false)
        , _remote_control_id (0)
+       , _track_number (0)
        , _in_configure_processors (false)
        , _initial_io_setup (false)
        , _custom_meter_position_noted (false)
@@ -144,10 +145,12 @@ Route::init ()
        _output->changed.connect_same_thread (*this, boost::bind (&Route::output_change_handler, this, _1, _2));
        _output->PortCountChanging.connect_same_thread (*this, boost::bind (&Route::output_port_count_changing, this, _1));
 
+#if 0 // not used - just yet
        if (!is_master() && !is_monitor() && !is_auditioner()) {
                _delayline.reset (new DelayLine (_session, _name));
                add_processor (_delayline, PreFader);
        }
+#endif
 
        /* add amp processor  */
 
@@ -430,7 +433,10 @@ Route::process_output_buffers (BufferSet& bufs,
        assert (!AudioEngine::instance()->process_lock().trylock());
 
        Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
-       assert(lm.locked());
+       if (!lm.locked()) {
+               bufs.silence (nframes, 0);
+               return;
+       }
 
        /* figure out if we're going to use gain automation */
        if (gain_automation_ok) {
@@ -447,8 +453,13 @@ Route::process_output_buffers (BufferSet& bufs,
           on a transition between monitoring states we get a de-clicking gain
           change in the _main_outs delivery.
        */
+       bool silence = monitoring_state () == MonitoringSilence;
 
-       _main_outs->no_outs_cuz_we_no_monitor (monitoring_state () == MonitoringSilence);
+       //but we override this in the case where we have an internal generator
+       if ( _have_internal_generator )
+               silence = false;
+
+       _main_outs->no_outs_cuz_we_no_monitor (silence);
 
        /* -------------------------------------------------------------------------------------------
           GLOBAL DECLICK (for transport changes etc.)
@@ -761,6 +772,11 @@ Route::set_solo (bool yn, void *src)
                return;
        }
 
+       if (is_master() || is_monitor() || is_auditioner()) {
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 ignore solo change (master, monitor or auditioner)\n", name()));
+               return;
+       }
+
        if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_solo()) {
                _route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, _route_group));
                return;
@@ -1206,8 +1222,18 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version)
                if (processor->set_state (node, version)) {
                        return false;
                }
+               
+               //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() )
+                                       processor->activate();
+                               else
+                                       processor->deactivate();
+                       }
+               }
 
-               return (add_processor (processor, placement) == 0);
+               return (add_processor (processor, placement, 0, false) == 0);
        }
 
        catch (failed_constructor &err) {
@@ -2027,6 +2053,10 @@ Route::state(bool full_state)
        node->add_child_nocopy (_mute_control->get_state ());
        node->add_child_nocopy (_mute_master->get_state ());
 
+       if (full_state) {
+               node->add_child_nocopy (Automatable::get_automation_xml_state ());
+       }
+
        XMLNode* remote_control_node = new XMLNode (X_("RemoteControl"));
        snprintf (buf, sizeof (buf), "%d", _remote_control_id);
        remote_control_node->add_property (X_("id"), buf);
@@ -2297,6 +2327,9 @@ Route::set_state (const XMLNode& node, int version)
 
                } else if (child->name() == X_("MuteMaster")) {
                        _mute_master->set_state (*child, version);
+
+               } else if (child->name() == Automatable::xml_node_name) {
+                       set_automation_xml_state (*child, Evoral::Parameter(NullAutomation));
                }
        }
 
@@ -2306,6 +2339,7 @@ Route::set_state (const XMLNode& node, int version)
 int
 Route::set_state_2X (const XMLNode& node, int version)
 {
+       LocaleGuard lg (X_("C"));
        XMLNodeList nlist;
        XMLNodeConstIterator niter;
        XMLNode *child;
@@ -2604,8 +2638,10 @@ Route::set_processor_state (const XMLNode& node)
                        _meter->set_state (**niter, Stateful::current_state_version);
                        new_order.push_back (_meter);
                } else if (prop->value() == "delay") {
-                       _delayline->set_state (**niter, Stateful::current_state_version);
-                       new_order.push_back (_delayline);
+                       if (_delayline) {
+                               _delayline->set_state (**niter, Stateful::current_state_version);
+                               new_order.push_back (_delayline);
+                       }
                } else if (prop->value() == "main-outs") {
                        _main_outs->set_state (**niter, Stateful::current_state_version);
                } else if (prop->value() == "intreturn") {
@@ -3375,18 +3411,21 @@ Route::set_latency_compensation (framecnt_t longest_session_latency)
 }
 
 Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
-       : AutomationControl (r->session(), Evoral::Parameter (SoloAutomation),
-                            boost::shared_ptr<AutomationList>(), name)
+       : AutomationControl (r->session(),
+                            Evoral::Parameter (SoloAutomation),
+                            ParameterDescriptor(Evoral::Parameter (SoloAutomation)),
+                            boost::shared_ptr<AutomationList>(), name)
        , _route (r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
+       gl->set_interpolation(Evoral::ControlList::Discrete);
        set_list (gl);
 }
 
 void
 Route::SoloControllable::set_value (double val)
 {
-       bool bval = ((val >= 0.5f) ? true: false);
+       const bool bval = ((val >= 0.5) ? true : false);
 
        boost::shared_ptr<RouteList> rl (new RouteList);
 
@@ -3420,39 +3459,64 @@ Route::SoloControllable::get_value () const
 }
 
 Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
-       : AutomationControl (r->session(), Evoral::Parameter (MuteAutomation),
-                            boost::shared_ptr<AutomationList>(), name)
+       : AutomationControl (r->session(),
+                            Evoral::Parameter (MuteAutomation),
+                            ParameterDescriptor (Evoral::Parameter (MuteAutomation)),
+                            boost::shared_ptr<AutomationList>(),
+                            name)
        , _route (r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
+       gl->set_interpolation(Evoral::ControlList::Discrete);
        set_list (gl);
 }
 
 void
-Route::MuteControllable::set_value (double val)
+Route::MuteControllable::set_superficial_value(bool muted)
 {
-       bool bval = ((val >= 0.5f) ? true: false);
+       /* Note we can not use AutomationControl::set_value here since it will emit
+          Changed(), but the value will not be correct to the observer. */
 
-       boost::shared_ptr<RouteList> rl (new RouteList);
+       bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
+
+       Control::set_double (muted, _session.transport_frame(), to_list);
+}
+
+void
+Route::MuteControllable::set_value (double val)
+{
+       const bool bval = ((val >= 0.5) ? true : false);
 
        boost::shared_ptr<Route> r = _route.lock ();
        if (!r) {
                return;
        }
 
-       rl->push_back (r);
-       _session.set_mute (rl, bval);
+       if (_list && ((AutomationList*)_list.get())->automation_playback()) {
+               // Playing back automation, set route mute directly
+               r->set_mute (bval, this);
+       } else {
+               // Set from user, queue mute event
+               boost::shared_ptr<RouteList> rl (new RouteList);
+               rl->push_back (r);
+               _session.set_mute (rl, bval, Session::rt_cleanup);
+       }
+
+       // Set superficial/automation value to drive controller (and possibly record)
+       set_superficial_value(bval);
 }
 
 double
 Route::MuteControllable::get_value () const
 {
-       boost::shared_ptr<Route> r = _route.lock ();
-       if (!r) {
-               return 0;
+       if (_list && ((AutomationList*)_list.get())->automation_playback()) {
+               // Playing back automation, get the value from the list
+               return AutomationControl::get_value();
        }
 
-       return r->muted() ? 1.0f : 0.0f;
+       // Not playing back automation, get the actual route mute value
+       boost::shared_ptr<Route> r = _route.lock ();
+       return (r && r->muted()) ? 1.0 : 0.0;
 }
 
 void
@@ -3562,14 +3626,14 @@ Route::save_as_template (const string& path, const string& name)
 bool
 Route::set_name (const string& str)
 {
-       bool ret;
-       string ioproc_name;
-       string name;
+       if (str == name()) {
+               return true;
+       }
 
-       name = Route::ensure_track_or_route_name (str, _session);
+       string name = Route::ensure_track_or_route_name (str, _session);
        SessionObject::set_name (name);
 
-       ret = (_input->set_name(name) && _output->set_name(name));
+       bool ret = (_input->set_name(name) && _output->set_name(name));
 
        if (ret) {
                /* rename the main outs. Leave other IO processors
@@ -3715,7 +3779,7 @@ Route::set_active (bool yn, void* src)
 void
 Route::meter ()
 {
-       Glib::Threads::RWLock::ReaderLock rm (_processor_lock, Glib::Threads::TRY_LOCK);
+       Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
 
        assert (_meter);
 
@@ -3770,7 +3834,7 @@ Route::get_control (const Evoral::Parameter& param)
 
                /* maybe one of our processors does or ... */
 
-               Glib::Threads::RWLock::ReaderLock rm (_processor_lock, Glib::Threads::TRY_LOCK);
+               Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
                for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                        if ((c = boost::dynamic_pointer_cast<AutomationControl>((*i)->control (param))) != 0) {
                                break;
@@ -4140,9 +4204,11 @@ Route::setup_invisible_processors ()
                }
        }
 
+#if 0 // not used - just yet
        if (!is_master() && !is_monitor() && !is_auditioner()) {
                new_processors.push_front (_delayline);
        }
+#endif
 
        /* MONITOR CONTROL */