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:
parent
06b4092ad0
commit
1e4c1388c3
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user