summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2011-03-11 02:55:52 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2011-03-11 02:55:52 +0000
commitd155f32039570e9e0cde11b42e395ca2bcc89ffd (patch)
tree160ca7969013b713d70f31f15f328e7a11a723dd
parente8060844021cdf5b4c6f3e284a892e70109787c3 (diff)
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
-rw-r--r--libs/ardour/ardour/audio_buffer.h2
-rw-r--r--libs/ardour/ardour/audio_port.h4
-rw-r--r--libs/ardour/ardour/audioengine.h3
-rw-r--r--libs/ardour/ardour/delivery.h2
-rw-r--r--libs/ardour/ardour/io.h4
-rw-r--r--libs/ardour/ardour/io_processor.h2
-rw-r--r--libs/ardour/ardour/midi_port.h4
-rw-r--r--libs/ardour/ardour/midi_track.h2
-rw-r--r--libs/ardour/ardour/port.h62
-rw-r--r--libs/ardour/ardour/route.h13
-rw-r--r--libs/ardour/ardour/session.h6
-rw-r--r--libs/ardour/ardour/track.h3
-rw-r--r--libs/ardour/audio_diskstream.cc14
-rw-r--r--libs/ardour/audio_port.cc7
-rw-r--r--libs/ardour/audio_track.cc1
-rw-r--r--libs/ardour/audioengine.cc26
-rw-r--r--libs/ardour/delivery.cc9
-rw-r--r--libs/ardour/diskstream.cc73
-rw-r--r--libs/ardour/io.cc39
-rw-r--r--libs/ardour/io_processor.cc8
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/midi_port.cc30
-rw-r--r--libs/ardour/midi_track.cc7
-rw-r--r--libs/ardour/port.cc121
-rw-r--r--libs/ardour/route.cc182
-rw-r--r--libs/ardour/session.cc23
-rw-r--r--libs/ardour/session_process.cc2
-rw-r--r--libs/ardour/session_transport.cc25
-rw-r--r--libs/ardour/track.cc28
-rw-r--r--libs/ardour/wscript6
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<std::string>&);
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<MuteMaster> _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<Route> other) const;
PBD::Signal2<void,IOProcessor*,bool> 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 <set>
#include <string>
#include <vector>
@@ -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<void,bool> 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<std::string> _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<void> active_changed;
PBD::Signal0<void> phase_invert_changed;
@@ -426,6 +430,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
boost::shared_ptr<IO> _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 <list>
#include <map>
#include <set>
@@ -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<Diskstream>);
- 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<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- RingBufferNPT<CaptureTransition>::rw_vector transvec;
- (*chan)->capture_transition_buf->get_write_vector(&transvec);
+ RingBufferNPT<CaptureTransition>::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<AudioEngine *> (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<Ports> 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)
@@ -1189,12 +1185,6 @@ AudioEngine::get_physical_outputs (DataType type, vector<string>& outs)
}
void
-AudioEngine::update_total_latency (const Port& port)
-{
- port.recompute_total_latency ();
-}
-
-void
AudioEngine::transport_stop ()
{
GET_PRIVATE_JACK_POINTER (_jack);
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> io, boost::shared_ptr<Pann
, _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)
@@ -81,7 +80,6 @@ Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> 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<Bundle> 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<Region>
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> 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<Processor>
}
}
- (*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<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*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<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (*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<RouteList> 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<RouteList> 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<FreezeRecordProcessorInfo*>::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 <jack/jack.h>\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 <jack/jack.h>\nint main(int argc, char **argv) { jack_port_type_get_buffer_size ((jack_client_t*)0, ""); }\n',
linkflags = ['-ljack'],