CubicInterpolation interpolation;
- XMLNode* deprecated_io_node;
-
protected:
friend class Session;
extern uint64_t AudioPlayback;
extern uint64_t Panning;
extern uint64_t LV2;
+ extern uint64_t CaptureAlignment;
}
}
static void set_disk_io_chunk_frames (framecnt_t n) { disk_io_chunk_frames = n; }
/* Stateful */
- virtual XMLNode& get_state(void) = 0;
- virtual int set_state(const XMLNode&, int version) = 0;
+ virtual XMLNode& get_state(void);
+ virtual int set_state(const XMLNode&, int version);
virtual void monitor_input (bool) {}
PBD::ScopedConnection ic_connection;
Flag _flags;
+ XMLNode* deprecated_io_node;
void route_going_away ();
};
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
: Diskstream(sess, name, flag)
- , deprecated_io_node(NULL)
, channels (new ChannelList)
{
/* prevent any write sources from being created */
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
: Diskstream(sess, node)
- , deprecated_io_node(NULL)
, channels (new ChannelList)
{
in_set_state = true;
}
channels.flush ();
-
- delete deprecated_io_node;
}
void
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 {
XMLNode&
AudioDiskstream::get_state ()
{
- XMLNode* node = new XMLNode ("Diskstream");
+ XMLNode& node (Diskstream::get_state());
char buf[64] = "";
LocaleGuard lg (X_("POSIX"));
- boost::shared_ptr<ChannelList> c = channels.reader();
-
- node->add_property ("flags", enum_2_string (_flags));
+ boost::shared_ptr<ChannelList> c = channels.reader();
snprintf (buf, sizeof(buf), "%zd", c->size());
- node->add_property ("channels", buf);
-
- node->add_property ("playlist", _playlist->name());
-
- snprintf (buf, sizeof(buf), "%.12g", _visible_speed);
- node->add_property ("speed", buf);
-
- node->add_property("name", _name);
- id().print (buf, sizeof (buf));
- node->add_property("id", buf);
-
+ node.add_property ("channels", buf);
+
if (!capturing_sources.empty() && _session.get_record_enabled()) {
XMLNode* cs_child = new XMLNode (X_("CapturingSources"));
}
cs_child->add_property (X_("at"), buf);
- node->add_child_nocopy (*cs_child);
+ node.add_child_nocopy (*cs_child);
}
- if (_extra_xml) {
- node->add_child_copy (*_extra_xml);
- }
-
- return* node;
+ return node;
}
int
-AudioDiskstream::set_state (const XMLNode& node, int /*version*/)
+AudioDiskstream::set_state (const XMLNode& node, int version)
{
const XMLProperty* prop;
XMLNodeList nlist = node.children();
XMLNode* capture_pending_node = 0;
LocaleGuard lg (X_("POSIX"));
+ /* prevent write sources from being created */
+
in_set_state = true;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
}
}
- /* prevent write sources from being created */
-
- in_set_state = true;
-
- if ((prop = node.property ("name")) != 0) {
- _name = prop->value();
- }
-
- if (deprecated_io_node) {
- if ((prop = deprecated_io_node->property ("id")) != 0) {
- _id = prop->value ();
- }
- } else {
- if ((prop = node.property ("id")) != 0) {
- _id = prop->value ();
- }
- }
-
- if ((prop = node.property ("flags")) != 0) {
- _flags = Flag (string_2_enum (prop->value(), _flags));
- }
+ if (Diskstream::set_state (node, version)) {
+ return -1;
+ }
if ((prop = node.property ("channels")) != 0) {
nchans = atoi (prop->value().c_str());
remove_channel (_n_channels.n_audio() - nchans);
}
- if ((prop = node.property ("playlist")) == 0) {
- return -1;
- }
-
- {
- bool had_playlist = (_playlist != 0);
-
- if (find_and_use_playlist (prop->value())) {
- return -1;
- }
-
- if (!had_playlist) {
- _playlist->set_orig_diskstream_id (id());
- }
-
- if (!destructive() && capture_pending_node) {
- /* destructive streams have one and only one source per channel,
- and so they never end up in pending capture in any useful
- sense.
- */
- use_pending_capture_data (*capture_pending_node);
- }
-
- }
-
- if ((prop = node.property ("speed")) != 0) {
- double sp = atof (prop->value().c_str());
- if (realtime_set_speed (sp, false)) {
- non_realtime_set_speed ();
- }
- }
+
+ if (!destructive() && capture_pending_node) {
+ /* destructive streams have one and only one source per channel,
+ and so they never end up in pending capture in any useful
+ sense.
+ */
+ use_pending_capture_data (*capture_pending_node);
+ }
in_set_state = false;
uint64_t PBD::DEBUG::AudioPlayback = PBD::new_debug_bit ("audioplayback");
uint64_t PBD::DEBUG::Panning = PBD::new_debug_bit ("panning");
uint64_t PBD::DEBUG::LV2 = PBD::new_debug_bit ("lv2");
+uint64_t PBD::DEBUG::CaptureAlignment = PBD::new_debug_bit ("capturealignment");
, _persistent_alignment_style (ExistingMaterial)
, first_input_change (true)
, _flags (flag)
-
+ , deprecated_io_node (0)
{
}
, _persistent_alignment_style (ExistingMaterial)
, first_input_change (true)
, _flags (Recordable)
+ , deprecated_io_node (0)
{
}
if (_playlist) {
_playlist->release ();
}
+
+ delete deprecated_io_node;
}
void
}
_capture_offset = _io->latency();
+ DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using IO latency, capture offset set to %2\n", name(), _capture_offset));
}
void
return true;
}
+XMLNode&
+Diskstream::get_state ()
+{
+ XMLNode* node = new XMLNode ("Diskstream");
+ char buf[64];
+ LocaleGuard lg (X_("POSIX"));
+
+ node->add_property ("flags", enum_2_string (_flags));
+ node->add_property ("playlist", _playlist->name());
+ node->add_property("name", _name);
+ id().print (buf, sizeof (buf));
+ node->add_property("id", buf);
+ snprintf (buf, sizeof(buf), "%f", _visible_speed);
+ node->add_property ("speed", buf);
+
+ if (_extra_xml) {
+ node->add_child_copy (*_extra_xml);
+ }
+
+ return *node;
+}
+
+int
+Diskstream::set_state (const XMLNode& node, int /*version*/)
+{
+ const XMLProperty* prop;
+
+ if ((prop = node.property ("name")) != 0) {
+ _name = prop->value();
+ }
+
+ if (deprecated_io_node) {
+ if ((prop = deprecated_io_node->property ("id")) != 0) {
+ _id = prop->value ();
+ }
+ } else {
+ if ((prop = node.property ("id")) != 0) {
+ _id = prop->value ();
+ }
+ }
+
+ if ((prop = node.property ("flags")) != 0) {
+ _flags = Flag (string_2_enum (prop->value(), _flags));
+ }
+
+ if ((prop = node.property ("playlist")) == 0) {
+ return -1;
+ }
+
+ {
+ bool had_playlist = (_playlist != 0);
+
+ if (find_and_use_playlist (prop->value())) {
+ return -1;
+ }
+
+ if (!had_playlist) {
+ _playlist->set_orig_diskstream_id (id());
+ }
+ }
+
+ if ((prop = node.property ("speed")) != 0) {
+ double sp = atof (prop->value().c_str());
+
+ if (realtime_set_speed (sp, false)) {
+ non_realtime_set_speed ();
+ }
+ }
+
+ return 0;
+}
+
void
Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<framepos_t> > const & movements_frames, bool from_undo)
{
last_recordable_frame = max_framepos;
capture_start_frame = transport_frame;
+ DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 basic FRF = %2 LRF = %3 CSF = %4 CO = %5, WLO = %6\n",
+ name(), first_recordable_frame, last_recordable_frame, capture_start_frame,
+ _capture_offset,
+ _session.worst_output_latency(),
+ transport_frame));
+
+
+
if (change & transport_rolling) {
/* transport-change (started rolling) */
if (_alignment_style == ExistingMaterial) {
- /* there are two delays happening:
-
- 1) inbound, represented by _capture_offset
- 2) outbound, represented by _session.worst_output_latency()
-
- the first sample to record occurs when the larger of these
- two has elapsed, since they occur in parallel.
-
- since we've already added _capture_offset, just add the
- difference if _session.worst_output_latency() is larger.
+ /* audio played by ardour will take (up to) _session.worst_output_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.
*/
-
- if (_capture_offset < _session.worst_output_latency()) {
- first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
- }
+
+ first_recordable_frame += _session.worst_output_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));
}
} else {
if (_alignment_style == ExistingMaterial) {
- /* There are two kinds of punch:
-
- manual punch in happens at the correct transport frame
- because the user hit a button. but to get alignment correct
- we have to back up the position of the new region to the
- appropriate spot given the roll delay.
-
- autopunch toggles recording at the precise
- transport frame, and then the DS waits
- to start recording for a time that depends
- on the output latency.
-
- XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
-
- */
-
- if (_capture_offset < _session.worst_output_latency()) {
- /* see comment in ExistingMaterial block above */
- first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
- }
-
+ /* see comment in ExistingMaterial block above */
+ first_recordable_frame += _session.worst_output_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));
}
}
last_recordable_frame = transport_frame + _capture_offset;
if (_alignment_style == ExistingMaterial) {
- if (_session.worst_output_latency() > _capture_offset) {
- last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
- }
+ last_recordable_frame += _session.worst_input_latency();
} else {
last_recordable_frame += _roll_delay;
}
#include "ardour/audioengine.h"
#include "ardour/buffer.h"
+#include "ardour/debug.h"
#include "ardour/io.h"
#include "ardour/route.h"
#include "ardour/port.h"
}
}
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: max latency from %2 ports = %3\n",
+ name(), _ports.num_ports(), max_latency));
return max_latency;
}
XMLNode&
MidiDiskstream::get_state ()
{
- XMLNode* node = new XMLNode ("Diskstream");
+ XMLNode& node (Diskstream::get_state());
char buf[64];
LocaleGuard lg (X_("POSIX"));
- snprintf (buf, sizeof(buf), "0x%x", _flags);
- node->add_property ("flags", buf);
-
- node->add_property("channel-mode", enum_2_string(get_channel_mode()));
-
+ node.add_property("channel-mode", enum_2_string(get_channel_mode()));
snprintf (buf, sizeof(buf), "0x%x", get_channel_mask());
- node->add_property("channel-mask", buf);
-
- node->add_property ("playlist", _playlist->name());
-
- snprintf (buf, sizeof(buf), "%f", _visible_speed);
- node->add_property ("speed", buf);
-
- node->add_property("name", _name);
- id().print(buf, sizeof(buf));
- node->add_property("id", buf);
+ node.add_property("channel-mask", buf);
if (_write_source && _session.get_record_enabled()) {
}
cs_child->add_property (X_("at"), buf);
- node->add_child_nocopy (*cs_child);
+ node.add_child_nocopy (*cs_child);
}
- if (_extra_xml) {
- node->add_child_copy (*_extra_xml);
- }
-
- return* node;
+ return node;
}
int
-MidiDiskstream::set_state (const XMLNode& node, int /*version*/)
+MidiDiskstream::set_state (const XMLNode& node, int version)
{
const XMLProperty* prop;
XMLNodeList nlist = node.children();
XMLNode* capture_pending_node = 0;
LocaleGuard lg (X_("POSIX"));
+ /* prevent write sources from being created */
+
in_set_state = true;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- /*if ((*niter)->name() == IO::state_node_name) {
- deprecated_io_node = new XMLNode (**niter);
- }*/
assert ((*niter)->name() != IO::state_node_name);
if ((*niter)->name() == X_("CapturingSources")) {
}
}
- /* prevent write sources from being created */
-
- in_set_state = true;
-
- if ((prop = node.property ("name")) != 0) {
- _name = prop->value();
- }
-
- if ((prop = node.property ("id")) != 0) {
- _id = prop->value ();
- }
-
- if ((prop = node.property ("flags")) != 0) {
- _flags = Flag (string_2_enum (prop->value(), _flags));
- }
+ if (Diskstream::set_state (node, version)) {
+ return -1;
+ }
ChannelMode channel_mode = AllChannels;
if ((prop = node.property ("channel-mode")) != 0) {
}
}
- set_channel_mode(channel_mode, channel_mask);
- if ((prop = node.property ("playlist")) == 0) {
- return -1;
- }
-
- {
- bool had_playlist = (_playlist != 0);
+ if (capture_pending_node) {
+ use_pending_capture_data (*capture_pending_node);
+ }
- if (find_and_use_playlist (prop->value())) {
- return -1;
- }
-
- if (!had_playlist) {
- _playlist->set_orig_diskstream_id (id());
- }
-
- if (capture_pending_node) {
- use_pending_capture_data (*capture_pending_node);
- }
-
- }
-
- if ((prop = node.property ("speed")) != 0) {
- double sp = atof (prop->value().c_str());
-
- if (realtime_set_speed (sp, false)) {
- non_realtime_set_speed ();
- }
- }
+ set_channel_mode (channel_mode, channel_mask);
in_set_state = false;
return jack_port_get_total_latency (jack, _jack_port);
#else
- return 0;
+ 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
}
}
}
- DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: internal redirect latency = %2\n", _name, own_latency));
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: bus: internal redirect latency = %2\n", _name, own_latency));
_output->set_port_latency (own_latency);
void
Session::set_worst_io_latencies ()
{
+ if (_state_of_the_state & InitialConnecting) {
+ return;
+ }
+
_worst_output_latency = 0;
_worst_input_latency = 0;
_worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
_worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
}
+
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst output latency: %1 Worst input latency: %2\n",
+ _worst_output_latency, _worst_input_latency));
}
void
BootMessage (_("Compute I/O Latencies"));
- set_worst_io_latencies ();
-
if (_clicking) {
// XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
}
}
}
- /* catch up on send+insert cnts */
+ set_worst_io_latencies ();
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
_engine.update_total_latencies ();
}
- DEBUG_TRACE(DEBUG::Latency, string_compose("worst case latency was %1\n", _worst_track_latency));
+ 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);
}
}
-#undef DEBUG_LATENCY
-#ifdef DEBUG_LATENCY
- cerr << _name << ": internal redirect (final) latency = " << own_latency << endl;
-#endif
+ DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: track: internal redirect latency = %2\n", _name, own_latency));
_output->set_port_latency (own_latency);