Use normal Processor run_in_place interface on Meter.
[ardour.git] / libs / ardour / route.cc
index d8ecabb1c077f292ada7fc808d03aecded539e45..8193d4ed77ae38929c502dd5f710e254e3ebe301 100644 (file)
@@ -53,21 +53,21 @@ using namespace ARDOUR;
 using namespace PBD;
 
 uint32_t Route::order_key_cnt = 0;
-
+sigc::signal<void> Route::SyncOrderKeys;
 
 Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
        : IO (sess, name, input_min, input_max, output_min, output_max, default_type),
          _flags (flg),
-         _solo_control (X_("solo"), *this, ToggleControllable::SoloControl),
-         _mute_control (X_("mute"), *this, ToggleControllable::MuteControl)
+         _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)),
+         _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
 {
        init ();
 }
 
 Route::Route (Session& sess, const XMLNode& node, DataType default_type)
        : IO (sess, *node.child ("IO"), default_type),
-         _solo_control (X_("solo"), *this, ToggleControllable::SoloControl),
-         _mute_control (X_("mute"), *this, ToggleControllable::MuteControl)
+         _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl)),
+         _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
 {
        init ();
        _set_state (node, false);
@@ -89,6 +89,7 @@ Route::init ()
        _initial_delay = 0;
        _roll_delay = 0;
        _own_latency = 0;
+       _user_latency = 0;
        _have_internal_generator = false;
        _declickable = false;
        _pending_declick = true;
@@ -160,9 +161,34 @@ void
 Route::set_order_key (const char* name, long n)
 {
        order_keys[strdup(name)] = n;
+
+       if (Config->get_sync_all_route_ordering()) {
+               for (OrderKeys::iterator x = order_keys.begin(); x != order_keys.end(); ++x) {
+                       x->second = n;
+               }
+       } 
+
        _session.set_dirty ();
 }
 
+void
+Route::sync_order_keys ()
+{
+       uint32_t key;
+       
+       if (order_keys.empty()) {
+               return;
+       }
+       
+       OrderKeys::iterator x = order_keys.begin();
+       key = x->second;
+       ++x;
+
+       for (; x != order_keys.end(); ++x) {
+               x->second = key;
+       }
+}
+
 void
 Route::inc_gain (gain_t fraction, void *src)
 {
@@ -176,33 +202,33 @@ Route::set_gain (gain_t val, void *src)
                
                if (_mix_group->is_relative()) {
                        
-                       
-                       gain_t usable_gain  = gain();
+                       gain_t usable_gain = gain();
                        if (usable_gain < 0.000001f) {
-                               usable_gain=0.000001f;
+                               usable_gain = 0.000001f;
                        }
                                                
                        gain_t delta = val;
                        if (delta < 0.000001f) {
-                               delta=0.000001f;
+                               delta = 0.000001f;
                        }
 
                        delta -= usable_gain;
 
-                       if (delta == 0.0f) return;
+                       if (delta == 0.0f)
+                               return;
 
                        gain_t factor = delta / usable_gain;
 
                        if (factor > 0.0f) {
                                factor = _mix_group->get_max_factor(factor);
                                if (factor == 0.0f) {
-                                       gain_changed (src);
+                                       _gain_control->Changed(); /* EMIT SIGNAL */
                                        return;
                                }
                        } else {
                                factor = _mix_group->get_min_factor(factor);
                                if (factor == 0.0f) {
-                                       gain_changed (src);
+                                       _gain_control->Changed(); /* EMIT SIGNAL */
                                        return;
                                }
                        }
@@ -294,17 +320,17 @@ Route::process_output_buffers (BufferSet& bufs,
           -------------------------------------------------------------------------------------------------- */
 
        if (declick > 0) {
-               Amp::run (bufs, nframes, 0.0, 1.0, false);
+               Amp::run_in_place (bufs, nframes, 0.0, 1.0, false);
                _pending_declick = 0;
        } else if (declick < 0) {
-               Amp::run (bufs, nframes, 1.0, 0.0, false);
+               Amp::run_in_place (bufs, nframes, 1.0, 0.0, false);
                _pending_declick = 0;
        } else {
 
                /* no global declick */
 
                if (solo_gain != dsg) {
-                       Amp::run (bufs, nframes, solo_gain, dsg, false);
+                       Amp::run_in_place (bufs, nframes, solo_gain, dsg, false);
                        solo_gain = dsg;
                }
        }
@@ -315,11 +341,11 @@ Route::process_output_buffers (BufferSet& bufs,
           -------------------------------------------------------------------------------------------------- */
 
        if (meter && (_meter_point == MeterInput)) {
-               _meter->run(bufs, start_frame, end_frame, nframes, offset);
+               _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
        }
 
        if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
-               Amp::run (bufs, nframes, mute_gain, dmg, false);
+               Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
                mute_gain = dmg;
                mute_declick_applied = true;
        }
@@ -380,7 +406,7 @@ Route::process_output_buffers (BufferSet& bufs,
                                for (i = _processors.begin(); i != _processors.end(); ++i) {
                                        switch ((*i)->placement()) {
                                        case PreFader:
-                                               (*i)->run (bufs, start_frame, end_frame, nframes, offset);
+                                               (*i)->run_in_place (bufs, start_frame, end_frame, nframes, offset);
                                                break;
                                        case PostFader:
                                                post_fader_work = true;
@@ -406,7 +432,7 @@ Route::process_output_buffers (BufferSet& bufs,
        bufs.set_count(pre_fader_streams());
        
        if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
-               Amp::run (bufs, nframes, mute_gain, dmg, false);
+               Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
                mute_gain = dmg;
                mute_declick_applied = true;
        }
@@ -416,7 +442,7 @@ Route::process_output_buffers (BufferSet& bufs,
           -------------------------------------------------------------------------------------------------- */
 
        if (meter && (_meter_point == MeterPreFader)) {
-               _meter->run(bufs, start_frame, end_frame, nframes, offset);
+               _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
        }
 
        
@@ -459,13 +485,9 @@ Route::process_output_buffers (BufferSet& bufs,
                
            // OR recording 
                
-               // h/w monitoring not in use 
-               
-               (!Config->get_monitoring_model() == HardwareMonitoring && 
-
                 // AND software monitoring required
 
-                Config->get_monitoring_model() == SoftwareMonitoring)) { 
+               Config->get_monitoring_model() == SoftwareMonitoring) { 
                
                if (apply_gain_automation) {
                        
@@ -497,7 +519,7 @@ Route::process_output_buffers (BufferSet& bufs,
                        
                        if (_gain != dg) {
                                
-                               Amp::run (bufs, nframes, _gain, dg, _phase_invert);
+                               Amp::run_in_place (bufs, nframes, _gain, dg, _phase_invert);
                                _gain = dg;
                                
                        } else if (_gain != 0 && (_phase_invert || _gain != 1.0)) {
@@ -550,7 +572,7 @@ Route::process_output_buffers (BufferSet& bufs,
                                        case PreFader:
                                                break;
                                        case PostFader:
-                                               (*i)->run (bufs, start_frame, end_frame, nframes, offset);
+                                               (*i)->run_in_place (bufs, start_frame, end_frame, nframes, offset);
                                                break;
                                        }
                                }
@@ -569,7 +591,7 @@ Route::process_output_buffers (BufferSet& bufs,
        }
 
        if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) {
-               Amp::run (bufs, nframes, mute_gain, dmg, false);
+               Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
                mute_gain = dmg;
                mute_declick_applied = true;
        }
@@ -614,7 +636,7 @@ Route::process_output_buffers (BufferSet& bufs,
           ----------------------------------------------------------------------*/
 
        if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
-               Amp::run (bufs, nframes, mute_gain, dmg, false);
+               Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
                mute_gain = dmg;
                mute_declick_applied = true;
        }
@@ -676,7 +698,7 @@ Route::process_output_buffers (BufferSet& bufs,
                if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
                        _meter->reset();
                } else {
-                       _meter->run(output_buffers(), start_frame, end_frame, nframes, offset);
+                       _meter->run_in_place(output_buffers(), start_frame, end_frame, nframes, offset);
                }
        }
 }
@@ -697,7 +719,7 @@ Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
        collect_input (bufs, nframes, offset);
 
        if (meter_first) {
-               _meter->run(bufs, start_frame, end_frame, nframes, offset);
+               _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
                meter_first = false;
        }
                
@@ -725,7 +747,7 @@ Route::set_solo (bool yn, void *src)
        if (_soloed != yn) {
                _soloed = yn;
                solo_changed (src); /* EMIT SIGNAL */
-               _solo_control.Changed (); /* EMIT SIGNAL */
+               _solo_control->Changed (); /* EMIT SIGNAL */
        }
 }
 
@@ -762,7 +784,7 @@ Route::set_mute (bool yn, void *src)
                _muted = yn;
                mute_changed (src); /* EMIT SIGNAL */
                
-               _mute_control.Changed (); /* EMIT SIGNAL */
+               _mute_control->Changed (); /* EMIT SIGNAL */
                
                Glib::Mutex::Lock lm (declick_lock);
                desired_mute_gain = (yn?0.0f:1.0f);
@@ -812,6 +834,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
 
                processor->activate ();
                processor->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
+
+               _user_latency = 0;
        }
        
        if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
@@ -867,6 +891,8 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
                        (*i)->activate ();
                        (*i)->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
                }
+
+               _user_latency = 0;
        }
        
        if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
@@ -1098,6 +1124,8 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                                removed = true;
                                break;
                        }
+
+                       _user_latency = 0;
                }
 
                if (!removed) {
@@ -1214,6 +1242,8 @@ Route::apply_some_plugin_counts (list<ProcessorCount>& iclist)
 
        for (i = iclist.begin(); i != iclist.end(); ++i) {
                
+               cerr << "now applying for " << (*i).processor->name() << " in = " << (*i).in.n_audio() << " out = " << (*i).out.n_audio() << endl;
+
                if ((*i).processor->configure_io ((*i).in, (*i).out)) {
                        return -1;
                }
@@ -1242,6 +1272,9 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require
 
        for (i = iclist.begin(); i != iclist.end(); ++i) {
 
+
+               cerr << "Checking whether " << (*i).processor->name() << " can support " << required_inputs.n_audio() << " inputs\n";
+
                if ((*i).processor->can_support_input_configuration (required_inputs) < 0) {
                        if (err) {
                                err->index = index;
@@ -1253,6 +1286,8 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require
                (*i).in = required_inputs;
                (*i).out = (*i).processor->output_for_input_configuration (required_inputs);
 
+               cerr << "config looks like " << (*i).processor->name() << " in = " << (*i).in.n_audio() << " out = " << (*i).out.n_audio() << endl;
+
                required_inputs = (*i).out;
                
                ++index;
@@ -1337,6 +1372,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream
                        
                        /* SUCCESSFUL COPY ATTEMPT: delete the processors we removed pre-copy */
                        to_be_deleted.clear ();
+                       _user_latency = 0;
                }
        }
 
@@ -1437,7 +1473,7 @@ XMLNode&
 Route::state(bool full_state)
 {
        XMLNode *node = new XMLNode("Route");
-       ProcessorList:: iterator i;
+       ProcessorList::iterator i;
        char buf[32];
 
        if (_flags) {
@@ -1483,8 +1519,8 @@ Route::state(bool full_state)
        node->add_property ("order-keys", order_string);
 
        node->add_child_nocopy (IO::state (full_state));
-       node->add_child_nocopy (_solo_control.get_state ());
-       node->add_child_nocopy (_mute_control.get_state ());
+       node->add_child_nocopy (_solo_control->get_state ());
+       node->add_child_nocopy (_mute_control->get_state ());
 
        XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
        snprintf (buf, sizeof (buf), "%d", _remote_control_id);
@@ -1845,12 +1881,12 @@ Route::_set_state (const XMLNode& node, bool call_base)
                } else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) {
                        
                        if (prop->value() == "solo") {
-                               _solo_control.set_state (*child);
-                               _session.add_controllable (&_solo_control);
+                               _solo_control->set_state (*child);
+                               _session.add_controllable (_solo_control);
                        }
                        else if (prop->value() == "mute") {
-                               _mute_control.set_state (*child);
-                               _session.add_controllable (&_mute_control);
+                               _mute_control->set_state (*child);
+                               _session.add_controllable (_mute_control);
                        }
                }
                else if (child->name() == X_("remote_control")) {
@@ -2030,7 +2066,7 @@ Route::set_control_outs (const vector<string>& ports)
                _control_outs = 0;
        }
 
-       if (control() || master()) {
+       if (is_control() || is_master()) {
                /* no control outs for these two special busses */
                return 0;
        }
@@ -2059,7 +2095,7 @@ Route::set_control_outs (const vector<string>& ports)
        /* now connect to the named ports */
        
        for (size_t n = 0; n < limit; ++n) {
-               if (_control_outs->connect_output (_control_outs->output (n), ports[n], this)) {
+               if (_control_outs->connect_output (_control_outs->output (n), ports[n % ports.size()], this)) {
                        error << string_compose (_("could not connect %1 to %2"), _control_outs->output(n)->name(), ports[n]) << endmsg;
                        return -1;
                }
@@ -2300,7 +2336,7 @@ Route::pans_required () const
                return 0;
        }
        
-       return max (n_inputs ().n_audio(), static_cast<size_t>(processor_max_outs.n_audio()));
+       return max (n_inputs ().n_audio(), processor_max_outs.n_audio());
 }
 
 int 
@@ -2385,10 +2421,9 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nfra
                
                if (am.locked() && _session.transport_rolling()) {
                        
-                       ARDOUR::AutomationList& gain_auto = gain_automation();
-                       
-                       if (gain_auto.automation_playback()) {
-                               apply_gain_automation = gain_auto.curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
+                       if (_gain_control->list()->automation_playback()) {
+                               apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector (
+                                               start_frame, end_frame, _session.gain_automation_buffer(), nframes);
                        }
                }
        }
@@ -2470,32 +2505,62 @@ Route::set_meter_point (MeterPoint p, void *src)
 nframes_t
 Route::update_total_latency ()
 {
-       _own_latency = 0;
+       nframes_t old = _own_latency;
 
-       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-               if ((*i)->active ()) {
-                       _own_latency += (*i)->latency ();
+       if (_user_latency) {
+               _own_latency = _user_latency;
+       } else {
+               _own_latency = 0;
+
+               for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+                       if ((*i)->active ()) {
+                               _own_latency += (*i)->signal_latency ();
+                       }
                }
        }
 
        set_port_latency (_own_latency);
+       
+       if (!_user_latency) {
+               /* this (virtual) function is used for pure Routes,
+                  not derived classes like AudioTrack.  this means
+                  that the data processed here comes from an input
+                  port, not prerecorded material, and therefore we
+                  have to take into account any input latency.
+               */
 
-       /* this (virtual) function is used for pure Routes,
-          not derived classes like AudioTrack.  this means
-          that the data processed here comes from an input
-          port, not prerecorded material, and therefore we
-          have to take into account any input latency.
-       */
 
-       _own_latency += input_latency ();
+               _own_latency += input_latency ();
+       }
 
+       if (old != _own_latency) {
+               signal_latency_changed (); /* EMIT SIGNAL */
+       }
+       
        return _own_latency;
 }
 
+void
+Route::set_user_latency (nframes_t nframes)
+{
+       Latent::set_user_latency (nframes);
+       _session.update_latency_compensation (false, false);
+}
+
 void
 Route::set_latency_delay (nframes_t longest_session_latency)
 {
-       _initial_delay = longest_session_latency - _own_latency;
+       nframes_t old = _initial_delay;
+
+       if (_own_latency < longest_session_latency) {
+               _initial_delay = longest_session_latency - _own_latency;
+       } else {
+               _initial_delay = 0;
+       }
+
+       if (_initial_delay != old) {
+               initial_delay_changed (); /* EMIT SIGNAL */
+       }
 
        if (_session.transport_stopped()) {
                _roll_delay = _initial_delay;