Mute automation via normal mute button.
[ardour.git] / libs / ardour / route.cc
index b7a8d3cf48987cc48041363a7309a2960d3e6531..b9acae45eb13ab804ed2d83bfd2014d49fe254a7 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;
+
+       //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 (monitoring_state () == MonitoringSilence);
+       _main_outs->no_outs_cuz_we_no_monitor (silence);
 
        /* -------------------------------------------------------------------------------------------
           GLOBAL DECLICK (for transport changes etc.)
@@ -2027,6 +2038,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 +2312,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));
                }
        }
 
@@ -2604,8 +2622,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 +3395,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 +3443,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
@@ -3715,7 +3763,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 +3818,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 +4188,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 */