more fun and games with latency compensation, and so forth ... not done yet

git-svn-id: svn://localhost/ardour2/branches/3.0@9149 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2011-03-14 20:33:47 +00:00
parent 06b4092ad0
commit 1e4c1388c3
7 changed files with 279 additions and 158 deletions

View File

@ -820,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, bool force=false);
void update_latency_compensation (bool force = false);
private:
int create (const std::string& mix_template, BusProfile*);
@ -880,9 +880,13 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
bool _was_seamless;
void set_worst_io_latencies ();
void set_worst_playback_latency ();
void set_worst_capture_latency ();
void set_worst_io_latencies_x (IOChange, void *) {
set_worst_io_latencies ();
}
void post_capture_latency ();
void post_playback_latency ();
void update_latency_compensation_proxy (void* ignored);
@ -1208,7 +1212,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
SerializedRCUManager<RouteList> routes;
void add_routes (RouteList&, bool save);
void add_routes (RouteList&, bool auto_connect, bool save);
uint32_t destructive_index;
boost::shared_ptr<Route> XMLRouteFactory (const XMLNode&, int);
@ -1218,14 +1222,24 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
bool find_route_name (std::string const &, uint32_t& id, char* name, size_t name_len, bool);
void count_existing_route_channels (ChanCount& in, ChanCount& out);
void auto_connect_route (
Route* route,
ChanCount& existing_inputs,
ChanCount& existing_outputs,
bool connect_inputs = true,
ChanCount input_start = ChanCount (),
ChanCount output_start = ChanCount ()
);
void auto_connect_route (Route*,
ChanCount& existing_inputs,
ChanCount& existing_outputs,
bool with_lock,
bool connect_inputs = true,
ChanCount input_start = ChanCount (),
ChanCount output_start = ChanCount ());
void auto_connect_route (boost::shared_ptr<Route> route,
ChanCount& existing_inputs,
ChanCount& existing_outputs,
bool with_lock,
bool connect_inputs = true,
ChanCount input_start = ChanCount (),
ChanCount output_start = ChanCount ()) {
auto_connect_route (route.get(), existing_inputs, existing_outputs, with_lock, connect_inputs, input_start, output_start);
}
/* mixer stuff */

View File

@ -174,11 +174,11 @@ AudioDiskstream::non_realtime_input_change ()
remove_channel_from (c, _n_channels.n_audio() - _io->n_ports().n_audio());
}
}
get_input_sources ();
set_capture_offset ();
set_align_style_from_io ();
input_change_pending = IOChange::NoChange;
/* implicit unlock */
@ -223,8 +223,11 @@ AudioDiskstream::get_input_sources ()
connections.clear ();
cerr << "Getting Nth connection from io " << n << " = " << _io->nth(n) << endl;
if (_io->nth (n)->get_connections (connections) == 0) {
cerr << "\tThere were NO connections, apparently ...\n";
if ((*chan)->source) {
// _source->disable_metering ();
}
@ -232,6 +235,7 @@ AudioDiskstream::get_input_sources ()
(*chan)->source = 0;
} else {
cerr << "\tThere were some connections, apparently ... to " << connections[0] << endl;
(*chan)->source = dynamic_cast<AudioPort*>(_session.engine().get_port_by_name (connections[0]) );
}
}
@ -2012,12 +2016,17 @@ AudioDiskstream::set_align_style_from_io ()
boost::shared_ptr<ChannelList> c = channels.reader();
cerr << "Checking " << c->size() << " for physical connections\n";
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
cerr << "Channel connected via " << (*chan)->source << endl;
if ((*chan)->source && (*chan)->source->flags() & JackPortIsPhysical) {
cerr << "\tchannel has physical connection to " << (*chan)->source->name() << endl;
have_physical = true;
break;
}
}
cerr << "\tphysical? " << have_physical << endl;
if (have_physical) {
set_align_style (ExistingMaterial);

View File

@ -51,6 +51,10 @@ Port::Port (std::string const & n, DataType t, Flags f)
, _flags (f)
, _last_monitor (false)
{
_private_playback_latency.min = 0;
_private_playback_latency.max = 0;
_private_capture_latency.min = 0;
_private_capture_latency.max = 0;
/* Unfortunately we have to pass the DataType into this constructor so that we can
create the right kind of JACK port; aside from this we'll use the virtual function type ()
@ -242,8 +246,8 @@ Port::set_public_latency_range (jack_latency_range_t& range, bool playback) cons
if (!jack_port_set_latency_range) {
return;
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("PORT %1 %4 latency now [%2 - %3]\n", name(),
DEBUG_TRACE (DEBUG::Latency, string_compose ("SET PORT %1 %4 PUBLIC latency now [%2 - %3]\n", name(),
range.min,
range.max,
(playback ? "PLAYBACK" : "CAPTURE")));;
@ -256,14 +260,14 @@ 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(),
DEBUG_TRACE (DEBUG::Latency, string_compose ("SET PORT %1 playback PRIVATE 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));
DEBUG_TRACE (DEBUG::Latency, string_compose ("SET PORT %1 capture PRIVATE latency now [%2 - %3]\n", name(),
_private_capture_latency.min,
_private_capture_latency.max));
}
/* push to public (JACK) location so that everyone else can see it */
@ -275,8 +279,14 @@ const jack_latency_range_t&
Port::private_latency_range (bool playback) const
{
if (playback) {
return _private_playback_latency;
DEBUG_TRACE (DEBUG::Latency, string_compose ("GET PORT %1 playback PRIVATE latency now [%2 - %3]\n", name(),
_private_playback_latency.min,
_private_playback_latency.max));
return _private_playback_latency;
} else {
DEBUG_TRACE (DEBUG::Latency, string_compose ("GET PORT %1 capture PRIVATE latency now [%2 - %3]\n", name(),
_private_playback_latency.min,
_private_playback_latency.max));
return _private_capture_latency;
}
}
@ -289,7 +299,7 @@ Port::public_latency_range (bool playback) const
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",
DEBUG_TRACE (DEBUG::Latency, string_compose ("GET PORT %1: %4 PUBLIC latency range %2 .. %3\n",
name(), r.min, r.max,
sends_output() ? "PLAYBACK" : "CAPTURE"));
return r;
@ -320,14 +330,19 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c
range.max = 0;
for (vector<string>::iterator c = connections.begin(); c != connections.end(); ++c) {
cerr << "Connection between " << name() << " and " << *c << endl;
jack_port_t* remote_port = jack_port_by_name (_engine->jack(), (*c).c_str());
jack_latency_range_t lr;
if (remote_port) {
jack_port_get_latency_range (remote_port, (playback ? JackPlaybackLatency : JackCaptureLatency), &lr);
DEBUG_TRACE (DEBUG::Latency, string_compose ("\t\%1 has latency range %2 .. %3\n", *c, lr.min, lr.max));
DEBUG_TRACE (DEBUG::Latency, string_compose ("\t%1 <-> %2 : latter has latency range %3 .. %4\n", name(), *c, lr.min, lr.max));
range.min = min (range.min, lr.min);
range.max = max (range.max, lr.max);
} else {
cerr << "\t NO PORT BY NAME!\n";
}
}

View File

@ -920,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, false));
processor->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false));
_output->set_user_latency (0);
}
@ -1057,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, false));
(*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false));
}
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
@ -2422,7 +2422,7 @@ 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));
(*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false));
boost::shared_ptr<PluginInsert> pi;
@ -2752,7 +2752,9 @@ Route::output_change_handler (IOChange change, void * /*src*/)
and we are master (as an auto-connect in this situation would cause a
feedback loop)
*/
AutoConnectOption ac = Config->get_output_auto_connect ();
if (ac == AutoConnectPhysical || (ac == AutoConnectMaster && !is_master ())) {
ChanCount start = change.before;
@ -2769,8 +2771,8 @@ Route::output_change_handler (IOChange change, void * /*src*/)
already there
*/
start.set (*i, start.get (*i) + 1);
_session.auto_connect_route (this, dummy, dummy, false, ChanCount(), change.before);
_session.auto_connect_route (this, dummy, dummy, false, false, ChanCount(), change.before);
}
}
}
@ -3076,7 +3078,7 @@ void
Route::set_user_latency (framecnt_t nframes)
{
_output->set_user_latency (nframes);
_session.update_latency_compensation (false, false);
_session.update_latency_compensation ();
}
void

View File

@ -325,31 +325,6 @@ Session::destroy ()
#endif
}
void
Session::set_worst_io_latencies ()
{
if (_state_of_the_state & InitialConnecting) {
return;
}
_worst_output_latency = 0;
_worst_input_latency = 0;
if (!_engine.connected()) {
return;
}
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
_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
Session::when_engine_running ()
{
@ -656,7 +631,7 @@ Session::when_engine_running ()
BootMessage (_("Connect to engine"));
_engine.set_session (this);
update_latency_compensation (false, false, true);
update_latency_compensation (true);
}
void
@ -1431,7 +1406,9 @@ Session::count_existing_route_channels (ChanCount& in, ChanCount& out)
{
in = ChanCount::ZERO;
out = ChanCount::ZERO;
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (!(*i)->is_hidden()) {
in += (*i)->n_inputs();
@ -1448,15 +1425,11 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
{
char track_name[32];
uint32_t track_id = 0;
ChanCount existing_inputs;
ChanCount existing_outputs;
string port;
RouteList new_routes;
list<boost::shared_ptr<MidiTrack> > ret;
uint32_t control_id;
count_existing_route_channels (existing_inputs, existing_outputs);
control_id = ntracks() + nbusses();
bool const use_number = (how_many != 1);
@ -1494,8 +1467,6 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
}
}
auto_connect_route (track.get(), existing_inputs, existing_outputs);
track->non_realtime_input_change();
if (route_group) {
@ -1525,23 +1496,31 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
failed:
if (!new_routes.empty()) {
add_routes (new_routes, false);
add_routes (new_routes, true, false);
save_state (_current_snapshot_name);
}
return ret;
}
/** Caller must hold process lock.
* @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs.
/** @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs.
* @param input_start Where to start from when auto-connecting inputs; e.g. if this is 0, auto-connect starting from input 0.
* @param output_start As \a input_start, but for outputs.
*/
void
Session::auto_connect_route (
Route* route, ChanCount& existing_inputs, ChanCount& existing_outputs, bool connect_inputs, ChanCount input_start, ChanCount output_start
)
Session::auto_connect_route (Route* route, ChanCount& existing_inputs, ChanCount& existing_outputs,
bool with_lock, bool connect_inputs, ChanCount input_start, ChanCount output_start)
{
if (!IO::connecting_legal) {
return;
}
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::NOT_LOCK);
if (with_lock) {
lm.acquire ();
}
/* If both inputs and outputs are auto-connected to physical ports,
use the max of input and output offsets to ensure auto-connected
port numbers always match up (e.g. the first audio input and the
@ -1550,14 +1529,14 @@ Session::auto_connect_route (
offset possible.
*/
cerr << "ACR: existing in = " << existing_inputs << " out = " << existing_outputs << endl;
const bool in_out_physical =
(Config->get_input_auto_connect() & AutoConnectPhysical)
&& (Config->get_output_auto_connect() & AutoConnectPhysical)
&& connect_inputs;
const ChanCount in_offset = in_out_physical
? ChanCount::max(existing_inputs, existing_outputs)
: existing_inputs;
const ChanCount in_offset = existing_inputs;
const ChanCount out_offset = in_out_physical
? ChanCount::max(existing_inputs, existing_outputs)
@ -1572,13 +1551,21 @@ Session::auto_connect_route (
if (!physinputs.empty() && connect_inputs) {
uint32_t nphysical_in = physinputs.size();
cerr << "There are " << nphysical_in << " physical inputs of type " << *t << endl;
for (uint32_t i = input_start.get(*t); i < route->n_inputs().get(*t) && i < nphysical_in; ++i) {
string port;
if (Config->get_input_auto_connect() & AutoConnectPhysical) {
cerr << "Get index " << in_offset.get(*t) << " + " << i << " % " << nphysical_in << " = "
<< (in_offset.get(*t) + i) % nphysical_in
<< endl;
port = physinputs[(in_offset.get(*t) + i) % nphysical_in];
}
cerr << "Connect route " << route->name() << " IN to " << port << endl;
if (!port.empty() && route->input()->connect (
route->input()->ports().port(*t, i), port, this)) {
break;
@ -1600,6 +1587,8 @@ Session::auto_connect_route (
}
}
cerr << "Connect route " << route->name() << " OUT to " << port << endl;
if (!port.empty() && route->output()->connect (
route->output()->ports().port(*t, i), port, this)) {
break;
@ -1607,9 +1596,6 @@ Session::auto_connect_route (
}
}
}
existing_inputs += route->n_inputs();
existing_outputs += route->n_outputs();
}
/** Caller must not hold process lock
@ -1622,15 +1608,11 @@ Session::new_audio_track (
{
char track_name[32];
uint32_t track_id = 0;
ChanCount existing_inputs;
ChanCount existing_outputs;
string port;
RouteList new_routes;
list<boost::shared_ptr<AudioTrack> > ret;
uint32_t control_id;
count_existing_route_channels (existing_inputs, existing_outputs);
control_id = ntracks() + nbusses() + 1;
bool const use_number = (how_many != 1);
@ -1673,8 +1655,6 @@ Session::new_audio_track (
<< endmsg;
goto failed;
}
auto_connect_route (track.get(), existing_inputs, existing_outputs);
}
if (route_group) {
@ -1707,7 +1687,7 @@ Session::new_audio_track (
failed:
if (!new_routes.empty()) {
add_routes (new_routes, true);
add_routes (new_routes, true, true);
}
return ret;
@ -1748,14 +1728,10 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
{
char bus_name[32];
uint32_t bus_id = 0;
ChanCount existing_inputs;
ChanCount existing_outputs;
string port;
RouteList ret;
uint32_t control_id;
count_existing_route_channels (existing_inputs, existing_outputs);
control_id = ntracks() + nbusses() + 1;
bool const use_number = (how_many != 1);
@ -1792,8 +1768,6 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
<< endmsg;
goto failure;
}
auto_connect_route (bus.get(), existing_inputs, existing_outputs, false);
}
if (route_group) {
@ -1824,7 +1798,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
failure:
if (!ret.empty()) {
add_routes (ret, true);
add_routes (ret, true, true);
}
return ret;
@ -1914,14 +1888,14 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
out:
if (!ret.empty()) {
add_routes (ret, true);
add_routes (ret, true, true);
}
return ret;
}
void
Session::add_routes (RouteList& new_routes, bool save)
Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
{
{
RCUWriter<RouteList> writer (routes);
@ -1972,7 +1946,17 @@ Session::add_routes (RouteList& new_routes, bool save)
mt->StepEditStatusChange.connect_same_thread (*this, boost::bind (&Session::step_edit_status_change, this, _1));
}
}
}
if (auto_connect) {
ChanCount existing_inputs;
ChanCount existing_outputs;
count_existing_route_channels (existing_inputs, existing_outputs);
auto_connect_route (r, existing_inputs, existing_outputs, true);
}
}
if (_monitor_out && IO::connecting_legal) {
@ -2141,7 +2125,7 @@ Session::remove_route (boost::shared_ptr<Route> route)
}
}
update_latency_compensation (false, false);
update_latency_compensation ();
set_dirty();
/* Re-sort routes to remove the graph's current references to the one that is
@ -4156,6 +4140,10 @@ Session::update_latency (bool playback)
{
DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
if (_state_of_the_state & (InitialConnecting|Deletion)) {
return;
}
boost::shared_ptr<RouteList> r = routes.reader ();
framecnt_t max_latency = 0;
@ -4164,15 +4152,166 @@ Session::update_latency (bool playback)
reverse (r->begin(), r->end());
}
/* compute actual latency values for the given direction and store them all in per-port
structures. this will also publish the same values (to JACK) so that computation of latency
for routes can consistently use public latency values.
*/
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
max_latency = max (max_latency, (*i)->set_private_port_latencies (playback));
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("Set public port latencies to %1\n", max_latency));
if (playback) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->set_public_port_latencies (max_latency, playback);
post_playback_latency ();
/* because we latency compensate playback, our published playback latencies should
be the same for all output ports - all material played back by ardour has
the same latency, whether its caused by plugins or by latency compensation. since
these may differ from the values computed above, reset all playback port latencies
to the same value.
*/
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);
}
} else {
post_capture_latency ();
}
DEBUG_TRACE (DEBUG::Latency, "JACK latency callback: DONE\n");
}
void
Session::post_playback_latency ()
{
set_worst_playback_latency ();
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (!(*i)->is_hidden() && ((*i)->active())) {
_worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->set_latency_compensation (_worst_track_latency);
}
}
}
void
Session::post_capture_latency ()
{
set_worst_capture_latency ();
/* reflect any changes in capture latencies into capture offsets
*/
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (tr) {
tr->set_capture_offset ();
}
}
}
void
Session::set_worst_io_latencies ()
{
set_worst_playback_latency ();
set_worst_capture_latency ();
}
void
Session::set_worst_playback_latency ()
{
if (_state_of_the_state & (InitialConnecting|Deletion)) {
return;
}
_worst_output_latency = 0;
if (!_engine.connected()) {
return;
}
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
_worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst output latency: %1\n", _worst_output_latency));
}
void
Session::set_worst_capture_latency ()
{
if (_state_of_the_state & (InitialConnecting|Deletion)) {
return;
}
_worst_input_latency = 0;
if (!_engine.connected()) {
return;
}
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
_worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst input latency: %1\n", _worst_input_latency));
}
void
Session::update_latency_compensation (bool force_whole_graph)
{
bool update_jack = false;
if (_state_of_the_state & Deletion) {
return;
}
DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n");
_worst_track_latency = 0;
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (!(*i)->is_hidden() && ((*i)->active())) {
framecnt_t tl;
if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
update_jack = true;
}
_worst_track_latency = max (tl, _worst_track_latency);
}
}
DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
(update_jack ? "yes" : "no")));
if (force_whole_graph || update_jack) {
/* trigger a full recompute of latency numbers for the graph.
everything else that we need to do will be done in the latency
callback.
*/
_engine.update_total_latencies ();
return; // everything else will be done in the latency callback
}
DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")
}

View File

@ -606,7 +606,7 @@ Session::create (const string& mix_template, BusProfile* bus_profile)
}
if (!rl.empty()) {
add_routes (rl, false);
add_routes (rl, false, false);
}
/* this allows the user to override settings with an environment variable.
@ -1439,7 +1439,7 @@ Session::load_routes (const XMLNode& node, int version)
new_routes.push_back (route);
}
add_routes (new_routes, false);
add_routes (new_routes, false, false);
return 0;
}

View File

@ -490,7 +490,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
if (_engine.running()) {
update_latency_compensation (true, abort);
PostTransportWork ptw = post_transport_work ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
}
update_latency_compensation ();
}
bool const auto_return_enabled =
@ -1461,72 +1465,10 @@ Session::route_processors_changed (RouteProcessorChange c)
return;
}
update_latency_compensation (false, false);
update_latency_compensation ();
resort_routes ();
}
void
Session::update_latency_compensation (bool with_stop, bool abort, bool force_whole_graph)
{
bool update_jack = false;
PostTransportWork ptw;
if (_state_of_the_state & Deletion) {
return;
}
_worst_track_latency = 0;
ptw = post_transport_work();
DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n")
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (with_stop) {
(*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
}
framecnt_t old_latency = (*i)->signal_latency ();
framecnt_t new_latency = (*i)->update_signal_latency ();
if (old_latency != new_latency) {
update_jack = true;
}
if (!(*i)->is_hidden() && ((*i)->active())) {
_worst_track_latency = max (_worst_track_latency, new_latency);
}
}
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_compensation (_worst_track_latency);
}
set_worst_io_latencies ();
/* reflect any changes in latencies into capture offsets
*/
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (tr) {
tr->set_capture_offset ();
}
}
DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")
}
void
Session::allow_auto_play (bool yn)
{