diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 9fd1630d1e..09441c038e 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -355,7 +355,7 @@ public: virtual void apply_latency_compensation (); samplecnt_t set_private_port_latencies (bool playback) const; - void set_public_port_latencies (samplecnt_t, bool playback) const; + void set_public_port_latencies (samplecnt_t, bool playback, bool with_latcomp) const; samplecnt_t signal_latency() const { return _signal_latency; } samplecnt_t playback_latency (bool incl_downstream = false) const; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 50610cf90e..1244a9ffdf 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1432,6 +1432,7 @@ private: void remove_monitor_section (); void update_latency (bool playback); + void set_owned_port_public_latency (bool playback); bool update_route_latency (bool reverse, bool apply_to_delayline, bool* delayline_update_needed); void initialize_latencies (); void set_worst_output_latency (); diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index ee872ad125..25510a92ae 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -367,7 +367,7 @@ Port::set_public_latency_range (LatencyRange const& range, bool playback) const if (_port_handle) { LatencyRange r (range); - if (externally_connected () && 0 == (_flags & TransportSyncPort)) { + if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) { #if 0 r.min *= _speed_ratio; r.max *= _speed_ratio; @@ -399,10 +399,6 @@ Port::set_private_latency_range (LatencyRange& range, bool playback) _private_capture_latency.min, _private_capture_latency.max)); } - - /* push to public (port system) location so that everyone else can see it */ - - set_public_latency_range (range, playback); } const LatencyRange& @@ -426,14 +422,14 @@ Port::private_latency_range (bool playback) const } LatencyRange -Port::public_latency_range (bool /*playback*/) const +Port::public_latency_range (bool playback) const { /*Note: this method is no longer used. It exists purely for debugging reasons */ LatencyRange r; if (_port_handle) { - r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false); - if (externally_connected () && 0 == (_flags & TransportSyncPort)) { + r = port_engine.get_latency_range (_port_handle, playback); + if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) { #if 0 r.min /= _speed_ratio; r.max /= _speed_ratio; @@ -450,7 +446,7 @@ Port::public_latency_range (bool /*playback*/) const DEBUG_TRACE (DEBUG::LatencyIO, string_compose ( "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n", name(), r.min, r.max, - sends_output() ? "PLAYBACK" : "CAPTURE")); + playback ? "PLAYBACK" : "CAPTURE")); } return r; @@ -487,7 +483,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const if (remote_port) { lr = port_engine.get_latency_range (remote_port, playback); - if (externally_connected () && 0 == (_flags & TransportSyncPort)) { + if (externally_connected () && 0 == (_flags & TransportSyncPort) && sends_output () == playback) { #if 0 lr.min /= _speed_ratio; lr.max /= _speed_ratio; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 150019df94..092c8b72eb 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -4412,7 +4412,12 @@ Route::apply_latency_compensation () cout << "ROUTE " << name() << " delay for " << latcomp << " (c: " << latcomp_capt << ")" << endl; #endif - _delayline->set_delay (latcomp > 0 ? latcomp : 0); + if (_delayline->set_delay (latcomp > 0 ? latcomp : 0)) { + DEBUG_TRACE (DEBUG::LatencyRoute, string_compose ("%1: delay changed to %2\n", _name, latcomp)); + /* public port latency update is needed, + * Session::update_latency() calls this->set_public_port_latencies() + */ + } } void @@ -4975,7 +4980,7 @@ Route::set_private_port_latencies (bool playback) const } void -Route::set_public_port_latencies (samplecnt_t value, bool playback) const +Route::set_public_port_latencies (samplecnt_t value, bool playback, bool with_latcomp) const { /* publish private latencies */ Glib::Threads::RWLock::ReaderLock lm (_processor_lock); @@ -4985,9 +4990,10 @@ Route::set_public_port_latencies (samplecnt_t value, bool playback) const continue; } if (iop->input ()) { + assert (iop->input () != _input); // no delivery for Input iop->input ()->set_public_port_latencies (iop->input()->latency(), true); } - if (iop->output ()) { + if (iop->output () && iop->output () != _output) { iop->output ()->set_public_port_latencies (iop->output()->latency(), false); } } @@ -4995,8 +5001,20 @@ Route::set_public_port_latencies (samplecnt_t value, bool playback) const /* this is called to set the JACK-visible port latencies, which take * latency compensation into account. */ - _input->set_public_port_latencies (value, playback); - _output->set_public_port_latencies (value, playback); + if (playback) { + _output->set_public_port_latencies (_output->latency (), playback); + if (_delayline && with_latcomp) { + value += _delayline->delay (); + } + _input->set_public_port_latencies (value, playback); + } else { + _input->set_public_port_latencies (_input->latency(), playback); + if (_delayline && with_latcomp) { + value += _delayline->delay (); + } + _output->set_public_port_latencies (value, playback); + } + } /** Put the invisible processors in the right place in _processors. diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index bc20361e2f..3486d01198 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -6675,6 +6675,21 @@ restart: return changed; } +void +Session::set_owned_port_public_latency (bool playback) +{ + /* special routes or IO or ports owned by the session */ + if (auditioner) { + samplecnt_t latency = auditioner->set_private_port_latencies (playback); + auditioner->set_public_port_latencies (latency, playback, true); + } + _click_io->set_public_port_latencies (_click_io->connected_latency (playback), playback); + + if (_midi_ports) { + _midi_ports->set_public_latency (playback); + } +} + void Session::update_latency (bool playback) { @@ -6744,10 +6759,18 @@ Session::update_latency (bool playback) reverse (r->begin(), r->end()); } for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + /* private port latency includes plugin and I/O delay, + * but no latency compensation delaylines. + */ samplecnt_t latency = (*i)->set_private_port_latencies (playback); - (*i)->set_public_port_latencies (latency, playback); + /* However we also need to reset the latency of connected external + * ports, since those includes latency compensation delaylines. + */ + (*i)->set_public_port_latencies (latency, playback, false); } + set_owned_port_public_latency (playback); + if (playback) { /* Processing needs to be blocked while re-configuring delaylines. * @@ -6773,6 +6796,18 @@ Session::update_latency (bool playback) update_route_latency (false, false, NULL); } + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + /* Publish port latency. This includes latency-compensation + * delaylines in the direction of signal flow. + */ + samplecnt_t latency = (*i)->set_private_port_latencies (playback); + (*i)->set_public_port_latencies (latency, playback, true); + } + + /* now handle non-route ports that we are responsible for */ + set_owned_port_public_latency (playback); + + DEBUG_TRACE (DEBUG::LatencyCompensation, "Engine latency callback: DONE\n"); LatencyUpdated (playback); /* EMIT SIGNAL */ }