From d155f32039570e9e0cde11b42e395ca2bcc89ffd Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 11 Mar 2011 02:55:52 +0000 Subject: sorta-kinda working latency compensation, latency reporting and capture alignment ... working except that we report the wrong information to JACK and i've noticed a couple of odd circumstances where turning on a latent plugin caused punch recording to fail git-svn-id: svn://localhost/ardour2/branches/3.0@9121 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/audio_buffer.h | 2 +- libs/ardour/ardour/audio_port.h | 4 +- libs/ardour/ardour/audioengine.h | 3 - libs/ardour/ardour/delivery.h | 2 - libs/ardour/ardour/io.h | 4 +- libs/ardour/ardour/io_processor.h | 2 + libs/ardour/ardour/midi_port.h | 4 +- libs/ardour/ardour/midi_track.h | 2 - libs/ardour/ardour/port.h | 62 +++++++------ libs/ardour/ardour/route.h | 13 ++- libs/ardour/ardour/session.h | 6 +- libs/ardour/ardour/track.h | 3 +- libs/ardour/audio_diskstream.cc | 14 +-- libs/ardour/audio_port.cc | 7 +- libs/ardour/audio_track.cc | 1 + libs/ardour/audioengine.cc | 26 ++---- libs/ardour/delivery.cc | 9 -- libs/ardour/diskstream.cc | 73 ++++++--------- libs/ardour/io.cc | 39 ++++---- libs/ardour/io_processor.cc | 8 ++ libs/ardour/midi_diskstream.cc | 2 +- libs/ardour/midi_port.cc | 30 ++++--- libs/ardour/midi_track.cc | 7 -- libs/ardour/port.cc | 121 +++++++++++++------------ libs/ardour/route.cc | 182 ++++++++++++++++++++++---------------- libs/ardour/session.cc | 23 ++--- libs/ardour/session_process.cc | 2 +- libs/ardour/session_transport.cc | 25 +++--- libs/ardour/track.cc | 28 +----- libs/ardour/wscript | 6 +- 30 files changed, 350 insertions(+), 360 deletions(-) diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h index 0f71a00982..10f5f27ec3 100644 --- a/libs/ardour/ardour/audio_buffer.h +++ b/libs/ardour/ardour/audio_buffer.h @@ -166,7 +166,7 @@ public: return _data + offset; } - void prepare () { _written = false; } + void prepare () { _written = false; _silent = false; } bool written() const { return _written; } private: diff --git a/libs/ardour/ardour/audio_port.h b/libs/ardour/ardour/audio_port.h index ffd1f8d9b0..1d107dfe73 100644 --- a/libs/ardour/ardour/audio_port.h +++ b/libs/ardour/ardour/audio_port.h @@ -41,11 +41,11 @@ class AudioPort : public Port size_t raw_buffer_size (pframes_t nframes) const; - Buffer& get_buffer (framecnt_t nframes) { + Buffer& get_buffer (pframes_t nframes) { return get_audio_buffer (nframes); } - AudioBuffer& get_audio_buffer (framecnt_t nframes); + AudioBuffer& get_audio_buffer (pframes_t nframes); protected: friend class AudioEngine; diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index de179d71a6..e025169f0a 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -187,7 +187,6 @@ class AudioEngine : public SessionHandlePtr void get_physical_inputs (DataType type, std::vector&); void update_total_latencies (); - void update_total_latency (const Port&); Port *get_port_by_name (const std::string &); @@ -320,10 +319,8 @@ _ the regular process() call to session->process() is not made. void set_jack_callbacks (); -#ifdef HAVE_JACK_NEW_LATENCY static void _latency_callback (jack_latency_callback_mode_t, void*); void jack_latency_callback (jack_latency_callback_mode_t); -#endif int connect_to_jack (std::string client_name, std::string session_uuid); diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h index 99893976ba..cf6b0fe9ea 100644 --- a/libs/ardour/ardour/delivery.h +++ b/libs/ardour/ardour/delivery.h @@ -75,7 +75,6 @@ public: void flush_buffers (framecnt_t nframes, framepos_t time); void no_outs_cuz_we_no_monitor(bool); void cycle_start (pframes_t); - void increment_output_offset (framecnt_t); void transport_stopped (framepos_t frame); BufferSet& output_buffers() { return *_output_buffers; } @@ -105,7 +104,6 @@ public: Role _role; BufferSet* _output_buffers; gain_t _current_gain; - framecnt_t _output_offset; bool _no_outs_cuz_we_no_monitor; boost::shared_ptr _mute_master; bool no_panner_reset; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 8a3884b95f..90544450ef 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -90,6 +90,7 @@ class IO : public SessionObject, public Latent bool set_name (const std::string& str); virtual void silence (framecnt_t); + void increment_port_buffer_offset (pframes_t offset); int ensure_io (ChanCount cnt, bool clear, void *src); @@ -111,9 +112,6 @@ class IO : public SessionObject, public Latent framecnt_t signal_latency () const { return _own_latency; } framecnt_t latency () const; - void set_port_latency (framecnt_t); - - void update_port_total_latencies (); PortSet& ports() { return _ports; } const PortSet& ports() const { return _ports; } diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h index cb80b74351..40a974156c 100644 --- a/libs/ardour/ardour/io_processor.h +++ b/libs/ardour/ardour/io_processor.h @@ -65,6 +65,8 @@ class IOProcessor : public Processor void silence (framecnt_t nframes); void disconnect (); + void increment_port_buffer_offset (pframes_t); + virtual bool feeds (boost::shared_ptr other) const; PBD::Signal2 AutomationPlaybackChanged; diff --git a/libs/ardour/ardour/midi_port.h b/libs/ardour/ardour/midi_port.h index b7c80e0c01..d95296ef76 100644 --- a/libs/ardour/ardour/midi_port.h +++ b/libs/ardour/ardour/midi_port.h @@ -46,11 +46,11 @@ class MidiPort : public Port { size_t raw_buffer_size (pframes_t nframes) const; - Buffer& get_buffer (framecnt_t nframes) { + Buffer& get_buffer (pframes_t nframes) { return get_midi_buffer (nframes); } - MidiBuffer& get_midi_buffer (framecnt_t nframes); + MidiBuffer& get_midi_buffer (pframes_t nframes); protected: friend class AudioEngine; diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 0e36a6d9cb..2308f3cdc6 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -52,8 +52,6 @@ public: return DataType::MIDI; } - void set_latency_delay (framecnt_t); - int export_stuff (BufferSet& bufs, framecnt_t nframes, framepos_t end_frame); void freeze_me (InterThreadInfo&); diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h index 300ecc24af..45595be422 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -20,6 +20,8 @@ #ifndef __ardour_port_h__ #define __ardour_port_h__ +#include "libardour-config.h" + #include #include #include @@ -45,9 +47,6 @@ public: virtual ~Port (); - static void set_buffer_size (pframes_t sz) { - _buffer_size = sz; - } static void set_connecting_blocked( bool yn ) { _connecting_blocked = yn; } @@ -93,16 +92,22 @@ public: void ensure_monitor_input (bool); bool monitoring_input () const; - framecnt_t total_latency () const; int reestablish (); int reconnect (); void request_monitor_input (bool); - void set_latency (framecnt_t); -#ifdef HAVE_JACK_NEW_LATENCY + bool last_monitor() const { return _last_monitor; } + void set_last_monitor (bool yn) { _last_monitor = yn; } + + jack_port_t* jack_port() const { return _jack_port; } + void get_connected_latency_range (jack_latency_range_t& range, bool playback) const; - void set_latency_range (jack_latency_range_t& range, bool playback) const; -#endif + + void set_private_latency_range (jack_latency_range_t& range, bool playback); + const jack_latency_range_t& private_latency_range (bool playback) const; + + void set_public_latency_range (jack_latency_range_t& range, bool playback) const; + jack_latency_range_t public_latency_range (bool playback) const; virtual void reset (); @@ -110,10 +115,10 @@ public: virtual size_t raw_buffer_size (pframes_t nframes) const = 0; virtual DataType type () const = 0; - virtual void cycle_start (pframes_t) = 0; + virtual void cycle_start (pframes_t); virtual void cycle_end (pframes_t) = 0; virtual void cycle_split () = 0; - virtual Buffer& get_buffer (framecnt_t nframes) = 0; + virtual Buffer& get_buffer (pframes_t nframes) = 0; virtual void flush_buffers (pframes_t nframes, framepos_t /*time*/) {} virtual void transport_stopped () {} @@ -124,41 +129,44 @@ public: PBD::Signal1 MonitorInputChanged; - static framecnt_t port_offset() { return _port_offset; } - - static void set_port_offset (framecnt_t off) { - _port_offset = off; + static void set_cycle_framecnt (pframes_t n) { + _cycle_nframes = n; + } + static framecnt_t port_offset() { return _global_port_buffer_offset; } + static void set_global_port_buffer_offset (pframes_t off) { + _global_port_buffer_offset = off; } - - static void increment_port_offset (framecnt_t n) { - _port_offset += n; + static void increment_global_port_buffer_offset (pframes_t n) { + _global_port_buffer_offset += n; } + virtual void increment_port_buffer_offset (pframes_t n); + protected: Port (std::string const &, DataType, Flags); jack_port_t* _jack_port; ///< JACK port - static pframes_t _buffer_size; static bool _connecting_blocked; - static framecnt_t _port_offset; + static pframes_t _global_port_buffer_offset; /* access only from process() tree */ + static pframes_t _cycle_nframes; /* access only from process() tree */ + + framecnt_t _port_buffer_offset; /* access only from process() tree */ + + jack_latency_range_t _private_playback_latency; + jack_latency_range_t _private_capture_latency; static AudioEngine* _engine; ///< the AudioEngine private: - friend class AudioEngine; - - void recompute_total_latency () const; - - /* XXX */ - bool _last_monitor; - std::string _name; ///< port short name Flags _flags; ///< flags + bool _last_monitor; /** ports that we are connected to, kept so that we can - reconnect to JACK when required */ + reconnect to JACK when required + */ std::set _connections; }; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 3b45020727..3c9d206760 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -250,11 +250,15 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, void all_processors_flip(); void all_processors_active (Placement, bool state); - void set_latency_ranges (bool playback) const; - virtual framecnt_t update_total_latency(); - void set_latency_delay (framecnt_t); + framecnt_t set_private_port_latencies (bool playback) const; + void set_public_port_latencies (framecnt_t, bool playback) const; + + framecnt_t update_signal_latency(); + virtual void set_latency_compensation (framecnt_t); + void set_user_latency (framecnt_t); framecnt_t initial_delay() const { return _initial_delay; } + framecnt_t signal_latency() const { return _signal_latency; } PBD::Signal0 active_changed; PBD::Signal0 phase_invert_changed; @@ -426,6 +430,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, boost::shared_ptr _output; bool _active; + framecnt_t _signal_latency; framecnt_t _initial_delay; framecnt_t _roll_delay; @@ -517,7 +522,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, void set_mute_master_solo (); void set_processor_positions (); - void update_port_latencies (const PortSet& ports, const PortSet& feeders, bool playback, framecnt_t) const; + framecnt_t update_port_latencies (const PortSet& ports, const PortSet& feeders, bool playback, framecnt_t) const; void setup_invisible_processors (); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 47285088ff..f5b6db4448 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -20,6 +20,8 @@ #ifndef __ardour_session_h__ #define __ardour_session_h__ +#include "libardour-config.h" + #include #include #include @@ -818,7 +820,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi protected: friend class Route; void schedule_curve_reallocation (); - void update_latency_compensation (bool, bool); + void update_latency_compensation (bool, bool, bool force=false); private: int create (const std::string& mix_template, BusProfile*); @@ -1364,9 +1366,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void reset_jack_connection (jack_client_t* jack); void process_rtop (SessionEvent*); -#ifdef HAVE_JACK_NEW_LATENCY void update_latency (bool playback); -#endif XMLNode& state(bool); diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index aadc2f7797..f92d11ab4c 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -67,8 +67,7 @@ class Track : public Route, public PublicDiskstream virtual void use_new_diskstream () = 0; virtual void set_diskstream (boost::shared_ptr); - framecnt_t update_total_latency(); - void set_latency_delay (framecnt_t); + void set_latency_compensation (framecnt_t); enum FreezeState { NoFreeze, diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index dd4310294b..5eba4cb822 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -390,12 +390,12 @@ AudioDiskstream::prepare_record_status(framepos_t capture_start_frame) boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - RingBufferNPT::rw_vector transvec; - (*chan)->capture_transition_buf->get_write_vector(&transvec); + RingBufferNPT::rw_vector transitions; + (*chan)->capture_transition_buf->get_write_vector (&transitions); - if (transvec.len[0] > 0) { - transvec.buf[0]->type = CaptureStart; - transvec.buf[0]->capture_val = capture_start_frame; + if (transitions.len[0] > 0) { + transitions.buf[0]->type = CaptureStart; + transitions.buf[0]->capture_val = capture_start_frame; (*chan)->capture_transition_buf->increment_write_ptr(1); } else { // bad! @@ -1481,7 +1481,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo RegionFactory::region_name (region_name, whole_file_region_name, false); - cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl; + // cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl; try { @@ -1548,7 +1548,7 @@ AudioDiskstream::transport_looped (framepos_t transport_frame) capture_captured += _capture_offset; if (_alignment_style == ExistingMaterial) { - capture_captured += _session.worst_playback_latency(); + capture_captured += _session.worst_output_latency(); } else { capture_captured += _roll_delay; } diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc index 9deda7a861..e01f4a89e6 100644 --- a/libs/ardour/audio_port.cc +++ b/libs/ardour/audio_port.cc @@ -45,6 +45,8 @@ AudioPort::cycle_start (pframes_t nframes) { /* caller must hold process lock */ + Port::cycle_start (nframes); + if (sends_output()) { _buffer->prepare (); } @@ -67,10 +69,11 @@ AudioPort::cycle_split () } AudioBuffer& -AudioPort::get_audio_buffer (framecnt_t nframes) +AudioPort::get_audio_buffer (pframes_t nframes) { /* caller must hold process lock */ - _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + _port_offset, nframes); + _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, _cycle_nframes) + + _global_port_buffer_offset + _port_buffer_offset, nframes); return *_buffer; } diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 41a8d4c7f0..026e11c225 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -387,6 +387,7 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram playback distance to zero, thus causing diskstream::commit to do nothing. */ + cerr << name() << " Can't operate at " << transport_frame << " since roll delay is only " << _roll_delay << endl; return diskstream->process (transport_frame, 0, can_record, rec_monitors_input, need_butler); } diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 815b847294..ffa55e453d 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -190,11 +190,10 @@ AudioEngine::set_jack_callbacks () if( jack_set_session_callback) jack_set_session_callback (_priv_jack, _session_callback, this); #endif -#if HAVE_JACK_NEW_LATENCY + if (jack_set_latency_callback) { jack_set_latency_callback (_priv_jack, _latency_callback, this); } -#endif jack_set_error_function (ardour_jack_error); } @@ -389,13 +388,11 @@ AudioEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* a ae->PortRegisteredOrUnregistered (); /* EMIT SIGNAL */ } -#ifdef HAVE_JACK_NEW_LATENCY void AudioEngine::_latency_callback (jack_latency_callback_mode_t mode, void* arg) { return static_cast (arg)->jack_latency_callback (mode); } -#endif void AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg) @@ -413,9 +410,9 @@ AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int co boost::shared_ptr pr = ae->ports.reader (); Ports::iterator i = pr->begin (); while (i != pr->end() && (port_a == 0 || port_b == 0)) { - if (jack_port_a == (*i)->_jack_port) { + if (jack_port_a == (*i)->jack_port()) { port_a = *i; - } else if (jack_port_b == (*i)->_jack_port) { + } else if (jack_port_b == (*i)->jack_port()) { port_b = *i; } ++i; @@ -429,7 +426,7 @@ AudioEngine::split_cycle (pframes_t offset) { /* caller must hold process lock */ - AudioPort::increment_port_offset (offset); + Port::increment_global_port_buffer_offset (offset); /* tell all Ports that we're going to start a new (split) cycle */ @@ -512,7 +509,8 @@ AudioEngine::process_callback (pframes_t nframes) /* tell all relevant objects that we're starting a new cycle */ Delivery::CycleStart (nframes); - AudioPort::set_port_offset (0); + Port::set_global_port_buffer_offset (0); + Port::set_cycle_framecnt (nframes); InternalReturn::CycleStart (nframes); /* tell all Ports that we're starting a new cycle */ @@ -560,8 +558,8 @@ AudioEngine::process_callback (pframes_t nframes) Port *port = (*i); bool x; - if (port->_last_monitor != (x = port->monitoring_input ())) { - port->_last_monitor = x; + if (port->last_monitor() != (x = port->monitoring_input ())) { + port->set_last_monitor (x); /* XXX I think this is dangerous, due to a likely mutex in the signal handlers ... */ @@ -621,7 +619,6 @@ AudioEngine::jack_sample_rate_callback (pframes_t nframes) return 0; } -#ifdef HAVE_JACK_NEW_LATENCY void AudioEngine::jack_latency_callback (jack_latency_callback_mode_t mode) { @@ -629,7 +626,6 @@ AudioEngine::jack_latency_callback (jack_latency_callback_mode_t mode) _session->update_latency (mode == JackPlaybackLatency); } } -#endif int AudioEngine::_bufsize_callback (pframes_t nframes, void *arg) @@ -1188,12 +1184,6 @@ AudioEngine::get_physical_outputs (DataType type, vector& outs) get_physical (type, JackPortIsInput, outs); } -void -AudioEngine::update_total_latency (const Port& port) -{ - port.recompute_total_latency (); -} - void AudioEngine::transport_stop () { diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc index 157d8a285d..dfc38d761d 100644 --- a/libs/ardour/delivery.cc +++ b/libs/ardour/delivery.cc @@ -59,7 +59,6 @@ Delivery::Delivery (Session& s, boost::shared_ptr io, boost::shared_ptr pannable, boost::sha , _role (r) , _output_buffers (new BufferSet()) , _current_gain (1.0) - , _output_offset (0) , _no_outs_cuz_we_no_monitor (false) , _mute_master (mm) , no_panner_reset (false) @@ -123,16 +121,9 @@ Delivery::display_name () const void Delivery::cycle_start (pframes_t /*nframes*/) { - _output_offset = 0; _no_outs_cuz_we_no_monitor = false; } -void -Delivery::increment_output_offset (framecnt_t n) -{ - _output_offset += n; -} - bool Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) const { diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 647d62e00f..ae4a8ada3e 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -640,6 +640,9 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) if (possibly_recording == last_possibly_recording) { return; } + + framecnt_t existing_material_offset = _session.worst_playback_latency(); + if (possibly_recording == fully_rec_enabled) { if (last_possibly_recording == fully_rec_enabled) { @@ -650,52 +653,30 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) first_recordable_frame = transport_frame + _capture_offset; last_recordable_frame = max_framepos; - capture_start_frame = transport_frame; + capture_start_frame = _session.transport_frame(); - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 basic FRF = %2 LRF = %3 CSF = %4 CO = %5, WPL = %6\n", + /* in theory, we should be offsetting by _session.worst_playback_latency() when we adjust + for ExistingMaterial alignment. But that number includes the worst processor latency + across all routes, and each track will already be roll-delay adjusted to handle that. + so don't use worst_playback_latency(), just worst_output_latency() which covers + only downstream latency from IO ports. + */ + + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 basic FRF = %2 CSF = %4 CO = %5, EMO = %6 RD = %8\n", name(), first_recordable_frame, last_recordable_frame, capture_start_frame, _capture_offset, - _session.worst_playback_latency(), - transport_frame)); - - - - if (change & transport_rolling) { - - /* transport-change (started rolling) */ - - if (_alignment_style == ExistingMaterial) { - - /* audio played by ardour will take (up to) _session.worst_playback_latency() ("WOL") to - appear at the speakers; audio played at the time when it does appear at - the speakers will take _capture_offset to arrive back here. we've - already added _capture_offset, so now add WOL. - */ - - first_recordable_frame += _session.worst_playback_latency(); - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tROLL: shift FRF by delta between WOL %1\n", - first_recordable_frame)); - } else { - first_recordable_frame += _roll_delay; - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tROLL: shift FRF by roll delay of %1 to %2\n", - _roll_delay, first_recordable_frame)); - } - + existing_material_offset, + transport_frame, + _roll_delay)); + + if (_alignment_style == ExistingMaterial) { + first_recordable_frame += existing_material_offset; + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tshift FRF by EMO %1\n", + first_recordable_frame)); } else { - - /* punch in */ - - if (_alignment_style == ExistingMaterial) { - - /* see comment in ExistingMaterial block above */ - first_recordable_frame += _session.worst_playback_latency(); - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tMANUAL PUNCH: shift FRF by delta between WOL and CO to %1\n", - first_recordable_frame)); - } else { - capture_start_frame -= _roll_delay; - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tPUNCH: shift CSF by roll delay of %1 to %2\n", - _roll_delay, capture_start_frame)); - } + capture_start_frame += _roll_delay; + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tshift CFS by roll delay of %1 to %2\n", + _roll_delay, capture_start_frame)); } prepare_record_status (capture_start_frame); @@ -707,7 +688,11 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) /* we were recording last time */ if (change & transport_rolling) { - /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop() */ + + /* transport-change (stopped rolling): last_recordable_frame was set in ::prepare_to_stop(). We + had to set it there because we likely rolled past the stopping point to declick out, + and then backed up. + */ } else { /* punch out */ @@ -715,7 +700,7 @@ Diskstream::check_record_status (framepos_t transport_frame, bool can_record) last_recordable_frame = transport_frame + _capture_offset; if (_alignment_style == ExistingMaterial) { - last_recordable_frame += _session.worst_input_latency(); + last_recordable_frame += existing_material_offset; } else { last_recordable_frame += _roll_delay; } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index fce6a669f9..4cb1cca5b6 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -96,6 +96,18 @@ IO::~IO () } } +void +IO::increment_port_buffer_offset (pframes_t offset) +{ + /* io_lock, not taken: function must be called from Session::process() calltree */ + + if (_direction == Output) { + for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { + i->increment_port_buffer_offset (offset); + } + } +} + void IO::silence (framecnt_t nframes) { @@ -1133,16 +1145,6 @@ IO::set_name (const string& requested_name) return r; } -void -IO::set_port_latency (framecnt_t nframes) -{ - Glib::Mutex::Lock lm (io_lock); - - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - i->set_latency (nframes); - } -} - framecnt_t IO::latency () const { @@ -1154,26 +1156,17 @@ IO::latency () const /* io lock not taken - must be protected by other means */ for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - if ((latency = i->total_latency ()) > max_latency) { + if ((latency = i->public_latency_range (_direction == Output).max) > max_latency) { max_latency = latency; } } - DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: max latency from %2 ports = %3\n", - name(), _ports.num_ports(), max_latency)); + DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: max %4 latency from %2 ports = %3\n", + name(), _ports.num_ports(), max_latency, + ((_direction == Output) ? "PLAYBACK" : "CAPTURE"))); return max_latency; } -void -IO::update_port_total_latencies () -{ - /* io_lock, not taken: function must be called from Session::process() calltree */ - - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - _session.engine().update_total_latency (*i); - } -} - int IO::connect_ports_to_bundle (boost::shared_ptr c, void* src) { diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc index 8cad0ba6cb..a0c78f07b5 100644 --- a/libs/ardour/io_processor.cc +++ b/libs/ardour/io_processor.cc @@ -249,6 +249,14 @@ IOProcessor::silence (framecnt_t nframes) } } +void +IOProcessor::increment_port_buffer_offset (pframes_t offset) +{ + if (_own_output && _output) { + _output->increment_port_buffer_offset (offset); + } +} + ChanCount IOProcessor::natural_output_streams() const { diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index e2233fa418..3dddbb54f5 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -1104,7 +1104,7 @@ MidiDiskstream::transport_looped (framepos_t transport_frame) capture_captured += _capture_offset; if (_alignment_style == ExistingMaterial) { - capture_captured += _session.worst_playback_latency(); + capture_captured += _session.worst_output_latency(); } else { capture_captured += _roll_delay; } diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 75fd269cde..52aa7e6005 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -41,7 +41,10 @@ MidiPort::~MidiPort() void MidiPort::cycle_start (pframes_t nframes) { + Port::cycle_start (nframes); + _buffer->clear (); + assert (_buffer->size () == 0); if (sends_output ()) { @@ -50,7 +53,7 @@ MidiPort::cycle_start (pframes_t nframes) } MidiBuffer & -MidiPort::get_midi_buffer (framecnt_t nframes) +MidiPort::get_midi_buffer (pframes_t nframes) { if (_has_been_mixed_down) { return *_buffer; @@ -59,7 +62,7 @@ MidiPort::get_midi_buffer (framecnt_t nframes) if (receives_input ()) { void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); - const pframes_t event_count = jack_midi_get_event_count(jack_buffer); + const pframes_t event_count = jack_midi_get_event_count (jack_buffer); assert (event_count < _buffer->capacity()); @@ -78,17 +81,18 @@ MidiPort::get_midi_buffer (framecnt_t nframes) continue; } - if (ev.time >= _port_offset && ev.time < (_port_offset + nframes)) { + /* check that the event is in the acceptable time range */ + + if ((ev.time >= (_global_port_buffer_offset + _port_buffer_offset)) && + (ev.time < (_global_port_buffer_offset + _port_buffer_offset + nframes))) { _buffer->push_back (ev); } else { - cerr << "Dropping incoming MIDI at time " << ev.time << "; offset=" << _port_offset << " limit=" << (_port_offset + nframes) << "\n"; + cerr << "Dropping incoming MIDI at time " << ev.time << "; offset=" + << _global_port_buffer_offset << " limit=" + << (_global_port_buffer_offset + _port_buffer_offset + nframes) << "\n"; } } - if (nframes) { - _has_been_mixed_down = true; - } - } else { _buffer->silence (nframes); } @@ -137,14 +141,16 @@ MidiPort::flush_buffers (pframes_t nframes, framepos_t time) // event times are in frames, relative to cycle start - assert (ev.time() < (nframes + _port_offset)); + assert (ev.time() < (nframes + _global_port_buffer_offset + _port_buffer_offset)); - if (ev.time() >= _port_offset) { + if (ev.time() >= _global_port_buffer_offset + _port_buffer_offset) { if (jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()) != 0) { - cerr << "write failed, drop flushed note off on the floor, time " << ev.time() << " > " << _port_offset << endl; + cerr << "write failed, drop flushed note off on the floor, time " + << ev.time() << " > " << _global_port_buffer_offset + _port_buffer_offset << endl; } } else { - cerr << "drop flushed event on the floor, time " << ev.time() << " < " << _port_offset << endl; + cerr << "drop flushed event on the floor, time " << ev.time() + << " < " << _global_port_buffer_offset + _port_buffer_offset << endl; } } } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index b57f548cdc..c91f1435fa 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -464,13 +464,6 @@ MidiTrack::export_stuff (BufferSet& /*bufs*/, framecnt_t /*nframes*/, framepos_t return -1; } -void -MidiTrack::set_latency_delay (framecnt_t longest_session_latency) -{ - Route::set_latency_delay (longest_session_latency); - _diskstream->set_roll_delay (_roll_delay); -} - boost::shared_ptr MidiTrack::bounce (InterThreadInfo& /*itt*/) { diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index 6165196b9d..959336f701 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -40,15 +40,16 @@ using namespace ARDOUR; using namespace PBD; AudioEngine* Port::_engine = 0; -pframes_t Port::_buffer_size = 0; bool Port::_connecting_blocked = false; -framecnt_t Port::_port_offset = 0; +pframes_t Port::_global_port_buffer_offset = 0; +pframes_t Port::_cycle_nframes = 0; /** @param n Port short name */ Port::Port (std::string const & n, DataType t, Flags f) - : _last_monitor (false) + : _port_buffer_offset (0) , _name (n) , _flags (f) + , _last_monitor (false) { /* Unfortunately we have to pass the DataType into this constructor so that we can @@ -217,41 +218,79 @@ void Port::reset () { _last_monitor = false; - - // XXX - // _metering = 0; - // reset_meters (); } void -Port::recompute_total_latency () const +Port::cycle_start (pframes_t nframes) { -#ifndef HAVE_JACK_NEW_LATENCY -#ifdef HAVE_JACK_RECOMPUTE_LATENCY - jack_client_t* jack = _engine->jack(); - - if (!jack) { - return; - } - - jack_recompute_total_latency (jack, _jack_port); -#endif -#endif + _port_buffer_offset = 0; } -#ifdef HAVE_JACK_NEW_LATENCY void -Port::set_latency_range (jack_latency_range_t& range, bool playback) const +Port::increment_port_buffer_offset (pframes_t nframes) { + _port_buffer_offset += nframes; +} + +void +Port::set_public_latency_range (jack_latency_range_t& range, bool playback) const +{ + /* this sets the visible latency that the rest of JACK sees. because we do latency + compensation, all (most) of our visible port latency values are identical. + */ + if (!jack_port_set_latency_range) { return; } + DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1 %4 latency now [%2 - %3]\n", name(), + range.min, + range.max, + (playback ? "PLAYBACK" : "CAPTURE")));; + jack_port_set_latency_range (_jack_port, (playback ? JackPlaybackLatency : JackCaptureLatency), &range); } -#endif -#ifdef HAVE_JACK_NEW_LATENCY +void +Port::set_private_latency_range (jack_latency_range_t& range, bool playback) +{ + if (playback) { + _private_playback_latency = range; + DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1 playback latency now [%2 - %3]\n", name(), + _private_playback_latency.min, + _private_playback_latency.max)); + } else { + _private_capture_latency = range; + DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1 capture latency now [%2 - %3]\n", name(), + _private_playback_latency.min, + _private_playback_latency.max)); + } +} + +const jack_latency_range_t& +Port::private_latency_range (bool playback) const +{ + if (playback) { + return _private_playback_latency; + } else { + return _private_capture_latency; + } +} + +jack_latency_range_t +Port::public_latency_range (bool playback) const +{ + jack_latency_range_t r; + + jack_port_get_latency_range (_jack_port, + sends_output() ? JackPlaybackLatency : JackCaptureLatency, + &r); + DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1: %4 public latency range %2 .. %3\n", + name(), r.min, r.max, + sends_output() ? "PLAYBACK" : "CAPTURE")); + return r; +} + void Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) const { @@ -280,11 +319,9 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c jack_port_t* remote_port = jack_port_by_name (_engine->jack(), (*c).c_str()); jack_latency_range_t lr; - DEBUG_TRACE (DEBUG::Latency, string_compose ("\t%1 connected to %2\n", name(), *c)); - if (remote_port) { jack_port_get_latency_range (remote_port, (playback ? JackPlaybackLatency : JackCaptureLatency), &lr); - DEBUG_TRACE (DEBUG::Latency, string_compose ("\t\tremote has latency range %1 .. %2\n", lr.min, lr.max)); + DEBUG_TRACE (DEBUG::Latency, string_compose ("\t\%1 has latency range %2 .. %3\n", *c, lr.min, lr.max)); range.min = min (range.min, lr.min); range.max = max (range.max, lr.max); } @@ -296,29 +333,6 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c range.max = 0; } } -#endif /* HAVE_JACK_NEW_LATENCY */ - -framecnt_t -Port::total_latency () const -{ -#ifndef HAVE_JACK_NEW_LATENCY - jack_client_t* jack = _engine->jack(); - - if (!jack) { - return 0; - } - - return jack_port_get_total_latency (jack, _jack_port); -#else - jack_latency_range_t r; - jack_port_get_latency_range (_jack_port, - sends_output() ? JackPlaybackLatency : JackCaptureLatency, - &r); - DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1: latency range %2 .. %3\n", - name(), r.min, r.max)); - return r.max; -#endif -} int Port::reestablish () @@ -329,7 +343,6 @@ Port::reestablish () return -1; } - cerr << "RE-REGISTER: " << _name.c_str() << endl; _jack_port = jack_port_register (jack, _name.c_str(), type().to_jack_type(), _flags, 0); if (_jack_port == 0) { @@ -380,14 +393,6 @@ Port::request_monitor_input (bool yn) jack_port_request_monitor (_jack_port, yn); } -void -Port::set_latency (framecnt_t n) -{ -#ifndef HAVE_JACK_NEW_LATENCY - jack_port_set_latency (_jack_port, n); -#endif -} - bool Port::physically_connected () const { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 535fde2ca0..a1516dd0ae 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -84,6 +84,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , Automatable (sess) , GraphNode( sess.route_graph ) , _active (true) + , _signal_latency (0) , _initial_delay (0) , _roll_delay (0) , _flags (flg) @@ -919,7 +920,7 @@ Route::add_processor (boost::shared_ptr processor, ProcessorList::ite processor->activate (); } - processor->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false)); + processor->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false, false)); _output->set_user_latency (0); } @@ -1056,7 +1057,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr } } - (*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false)); + (*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false, false)); } for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { @@ -2420,6 +2421,9 @@ Route::set_processor_state (const XMLNode& node) } for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + + (*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false, false)); + boost::shared_ptr pi; if ((pi = boost::dynamic_pointer_cast(*i)) != 0) { @@ -2837,16 +2841,24 @@ Route::check_initial_delay (framecnt_t nframes, framecnt_t& transport_frame) nframes -= _roll_delay; silence_unlocked (_roll_delay); - /* we've written _roll_delay of samples into the - output ports, so make a note of that for - future reference. - */ - - _main_outs->increment_output_offset (_roll_delay); transport_frame += _roll_delay; + /* shuffle all the port buffers for things that lead "out" of this Route + to reflect that we just wrote _roll_delay frames of silence. + */ + + Glib::RWLock::ReaderLock lm (_processor_lock); + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + boost::shared_ptr iop = boost::dynamic_pointer_cast (*i); + if (iop) { + iop->increment_port_buffer_offset (_roll_delay); + } + } + _output->increment_port_buffer_offset (_roll_delay); + _roll_delay = 0; - } + + } return nframes; } @@ -3040,41 +3052,24 @@ Route::add_export_point() } framecnt_t -Route::update_total_latency () +Route::update_signal_latency () { - framecnt_t old = _output->effective_latency(); - framecnt_t own_latency = _output->user_latency(); + framecnt_t l = _output->user_latency(); for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { if ((*i)->active ()) { - own_latency += (*i)->signal_latency (); + l += (*i)->signal_latency (); } } - DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: bus: internal redirect latency = %2\n", _name, own_latency)); - - _output->set_port_latency (own_latency); - - if (_output->user_latency() == 0) { - - /* 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->signal_latency (); - } + DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal signal latency = %2\n", _name, l)); - if (old != own_latency) { - _output->set_latency_delay (own_latency); + if (_signal_latency != l) { + _signal_latency = l; signal_latency_changed (); /* EMIT SIGNAL */ } - DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: input latency = %2 total = %3\n", _name, _input->signal_latency(), own_latency)); - - return _output->effective_latency (); + return _signal_latency; } void @@ -3085,16 +3080,19 @@ Route::set_user_latency (framecnt_t nframes) } void -Route::set_latency_delay (framecnt_t longest_session_latency) +Route::set_latency_compensation (framecnt_t longest_session_latency) { framecnt_t old = _initial_delay; - if (_output->effective_latency() < longest_session_latency) { - _initial_delay = longest_session_latency - _output->effective_latency(); + if (_signal_latency < longest_session_latency) { + _initial_delay = longest_session_latency - _signal_latency; } else { _initial_delay = 0; } + DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: compensate for maximum latency of %2, given own latency of %3, using initial delay of %4\n", + name(), longest_session_latency, _signal_latency, _initial_delay)); + if (_initial_delay != old) { initial_delay_changed (); /* EMIT SIGNAL */ } @@ -3595,33 +3593,10 @@ Route::unknown_processors () const return p; } -void -Route::set_latency_ranges (bool playback) const -{ - framecnt_t own_latency = 0; - - /* Processor list not protected by lock: MUST BE CALLED FROM PROCESS THREAD OR - LATENCY CALLBACK - */ - - for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { - if ((*i)->active ()) { - own_latency += (*i)->signal_latency (); - } - } - - if (playback) { - update_port_latencies (_input->ports (), _output->ports (), true, own_latency); - } else { - update_port_latencies (_output->ports (), _input->ports (), false, own_latency); - } -} -void -Route::update_port_latencies (const PortSet& operands, const PortSet& feeders, bool playback, framecnt_t our_latency) const +framecnt_t +Route::update_port_latencies (const PortSet& from, const PortSet& to, bool playback, framecnt_t our_latency) const { -#ifdef HAVE_JACK_NEW_LATENCY - /* we assume that all our input ports feed all our output ports. its not universally true, but the alternative is way too corner-case to worry about. */ @@ -3631,11 +3606,11 @@ Route::update_port_latencies (const PortSet& operands, const PortSet& feeders, b all_connections.min = ~((jack_nframes_t) 0); all_connections.max = 0; - /* iterate over all feeder ports and determine their relevant latency, taking - the maximum and minimum across all of them. + /* iterate over all "from" ports and determine the latency range for all of their + connections to the "outside" (outside of this Route). */ - for (PortSet::const_iterator p = feeders.begin(); p != feeders.end(); ++p) { + for (PortSet::const_iterator p = from.begin(); p != from.end(); ++p) { jack_latency_range_t range; @@ -3644,24 +3619,81 @@ Route::update_port_latencies (const PortSet& operands, const PortSet& feeders, b all_connections.min = min (all_connections.min, range.min); all_connections.max = max (all_connections.max, range.max); } + + /* set the "from" port latencies to the max/min range of all their connections */ + for (PortSet::const_iterator p = from.begin(); p != from.end(); ++p) { + p->set_public_latency_range (all_connections, playback); + } + + /* set the ports "in the direction of the flow" to the same value as above plus our own signal latency */ + all_connections.min += our_latency; all_connections.max += our_latency; + + for (PortSet::const_iterator p = to.begin(); p != to.end(); ++p) { + p->set_public_latency_range (all_connections, playback); + } + + return all_connections.max; +} - for (PortSet::const_iterator p = operands.begin(); p != operands.end(); ++p) { - - p->set_latency_range (all_connections, playback); - - DEBUG_TRACE (DEBUG::Latency, string_compose ("Port %1 %5 latency range %2 .. %3 (including route latency of %4)\n", - p->name(), - all_connections.min, - all_connections.max, - our_latency, - (playback ? "PLAYBACK" : "CAPTURE"))); +framecnt_t +Route::set_private_port_latencies (bool playback) const +{ + framecnt_t own_latency = 0; + + /* Processor list not protected by lock: MUST BE CALLED FROM PROCESS THREAD OR + LATENCY CALLBACK. + + This is called (early) from the latency callback. It computes the REAL latency associated + with each port and stores the result as the "private" latency of the port. A later + call to Route::set_public_port_latencies() sets all ports to the same value to reflect + the fact that we do latency compensation and so all signals are delayed by the + same amount as they flow through ardour. + */ + + for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) { + if ((*i)->active ()) { + own_latency += (*i)->signal_latency (); + } + } + + if (playback) { + /* playback: propagate latency from "outside the route" to outputs to inputs */ + return update_port_latencies (_output->ports (), _input->ports (), true, own_latency); + } else { + /* capture: propagate latency from "outside the route" to inputs to outputs */ + return update_port_latencies (_input->ports (), _output->ports (), false, own_latency); } -#endif } +void +Route::set_public_port_latencies (framecnt_t value, bool playback) const +{ + /* this is called to set the JACK-visible port latencies, which take latency compensation + into account. + */ + + jack_latency_range_t range; + + range.min = value; + range.max = value; + + { + const PortSet& ports (_input->ports()); + for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) { + p->set_public_latency_range (range, playback); + } + } + + { + const PortSet& ports (_output->ports()); + for (PortSet::const_iterator p = ports.begin(); p != ports.end(); ++p) { + p->set_public_latency_range (range, playback); + } + } +} /** Put the invisible processors in the right place in _processors. * Must be called with a writer lock on _processor_lock held. diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 787de5993c..48d2f3f0c2 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -649,16 +649,14 @@ Session::when_engine_running () } } - set_worst_io_latencies (); - _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty)); /* hook us up to the engine */ BootMessage (_("Connect to engine")); - _engine.set_session (this); - _engine.update_total_latencies (); + + update_latency_compensation (false, false, true); } void @@ -4153,13 +4151,13 @@ Session::unknown_processors () const return p; } -#ifdef HAVE_JACK_NEW_LATENCY void Session::update_latency (bool playback) { - DEBUG_TRACE (DEBUG::Latency, "JACK latency callback\n"); + DEBUG_TRACE (DEBUG::Latency, string_compose ("\n\nJACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE"))); boost::shared_ptr r = routes.reader (); + framecnt_t max_latency = 0; if (playback) { /* reverse the list so that we work backwards from the last route to run to the first */ @@ -4167,9 +4165,14 @@ Session::update_latency (bool playback) } for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - DEBUG_TRACE (DEBUG::Latency, string_compose ("------------- Working on latency for %1\n", (*i)->name())); - (*i)->set_latency_ranges (playback); - DEBUG_TRACE (DEBUG::Latency, string_compose ("------------- Done working on latency for %1\n\n", (*i)->name())); + max_latency = max (max_latency, (*i)->set_private_port_latencies (playback)); + } + +#if 0 + DEBUG_TRACE (DEBUG::Latency, string_compose ("Set public port latencies to %1\n", max_latency)); + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + (*i)->set_public_port_latencies (max_latency, playback); } -} #endif +} diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 5181cfb46a..c81a66755b 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -932,7 +932,7 @@ Session::maybe_sync_start (pframes_t & nframes) no_roll (sync_offset); nframes -= sync_offset; - AudioPort::increment_port_offset (sync_offset); + Port::increment_global_port_buffer_offset (sync_offset); waiting_for_sync_offset = false; if (nframes == 0) { diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index f06e34849b..26a4592f0e 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -1466,7 +1466,7 @@ Session::route_processors_changed (RouteProcessorChange c) } void -Session::update_latency_compensation (bool with_stop, bool abort) +Session::update_latency_compensation (bool with_stop, bool abort, bool force_whole_graph) { bool update_jack = false; PostTransportWork ptw; @@ -1478,7 +1478,7 @@ Session::update_latency_compensation (bool with_stop, bool abort) _worst_track_latency = 0; ptw = post_transport_work(); - DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency\n\n") + DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n") boost::shared_ptr r = routes.reader (); @@ -1488,30 +1488,28 @@ Session::update_latency_compensation (bool with_stop, bool abort) (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush)); } - framecnt_t old_latency = (*i)->output()->signal_latency (); - framecnt_t track_latency = (*i)->update_total_latency (); + framecnt_t old_latency = (*i)->signal_latency (); + framecnt_t new_latency = (*i)->update_signal_latency (); - if (old_latency != track_latency) { -#ifndef HAVE_JACK_NEW_LATENCY - (*i)->input()->update_port_total_latencies (); - (*i)->output()->update_port_total_latencies (); -#endif + if (old_latency != new_latency) { update_jack = true; } if (!(*i)->is_hidden() && ((*i)->active())) { - _worst_track_latency = max (_worst_track_latency, track_latency); + _worst_track_latency = max (_worst_track_latency, new_latency); } } - if (update_jack) { + if (force_whole_graph || update_jack) { + /* trigger a full recompute of latency numbers for the graph + */ _engine.update_total_latencies (); - } + } DEBUG_TRACE(DEBUG::Latency, string_compose("worst case route internal latency was %1\n", _worst_track_latency)); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - (*i)->set_latency_delay (_worst_track_latency); + (*i)->set_latency_compensation (_worst_track_latency); } set_worst_io_latencies (); @@ -1526,6 +1524,7 @@ Session::update_latency_compensation (bool with_stop, bool abort) tr->set_capture_offset (); } } + DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n") } void diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index d51344eb0d..1ac3d69dd9 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -85,30 +85,6 @@ Track::toggle_monitor_input () } } -ARDOUR::framecnt_t -Track::update_total_latency () -{ - framecnt_t old = _output->effective_latency(); - framecnt_t own_latency = _output->user_latency(); - - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - if ((*i)->active ()) { - own_latency += (*i)->signal_latency (); - } - } - - DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: track: internal redirect latency = %2\n", _name, own_latency)); - - _output->set_port_latency (own_latency); - - if (old != own_latency) { - _output->set_latency_delay (own_latency); - signal_latency_changed (); /* EMIT SIGNAL */ - } - - return _output->effective_latency(); -} - Track::FreezeRecord::~FreezeRecord () { for (vector::iterator i = processor_info.begin(); i != processor_info.end(); ++i) { @@ -218,9 +194,9 @@ Track::set_name (const string& str) } void -Track::set_latency_delay (framecnt_t longest_session_latency) +Track::set_latency_compensation (framecnt_t longest_session_latency) { - Route::set_latency_delay (longest_session_latency); + Route::set_latency_compensation (longest_session_latency); _diskstream->set_roll_delay (_roll_delay); } diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 924a7df9b7..46ad56ed70 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -273,9 +273,9 @@ def configure(conf): conf.check_cc(fragment = "#include \nint main(int argc, char **argv) { jack_port_t* p; jack_latency_range_t r; jack_port_set_latency_range (p, JackCaptureLatency, &r); return 0; }\n", linkflags = ['-ljack'], msg = 'Checking for new JACK latency API', - define_name = 'HAVE_JACK_NEW_LATENCY', - uselib_store = "JACK_NEW_LATENCY", - okmsg = 'present') + okmsg = 'present', + mandatory = True, + errmsg = 'missing - a version of JACK that supports jack_port_set_latency_range() is required to compile Ardour3') conf.check_cc(fragment = '#include \nint main(int argc, char **argv) { jack_port_type_get_buffer_size ((jack_client_t*)0, ""); }\n', linkflags = ['-ljack'], -- cgit v1.2.3