summaryrefslogtreecommitdiff
path: root/libs/ardour/route.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/route.cc')
-rw-r--r--libs/ardour/route.cc254
1 files changed, 177 insertions, 77 deletions
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index e655efedb2..638c026056 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -813,7 +813,7 @@ Route::set_mute (bool yn, void *src)
int
Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
{
- ChanCount old_rmo = processor_max_outs;
+ ChanCount old_pmo = processor_max_outs;
if (!_session.engine().connected()) {
return 1;
@@ -827,8 +827,15 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
//processor->set_default_type(_default_type);
+ _processors.push_back (processor);
+
+ if (_reset_processor_counts (err)) {
+ _processors.pop_back ();
+ _reset_processor_counts (0); // it worked before we tried to add it ...
+ return -1;
+ }
+
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
- pi->set_count (1);
if (pi->natural_input_streams() == ChanCount::ZERO) {
/* generator plugin */
@@ -841,15 +848,22 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
// Set up processor list channels. This will set processor->[input|output]_streams(),
// configure redirect ports properly, etc.
- if (_reset_plugin_counts (err)) {
+ if (_reset_processor_counts (err)) {
_processors.pop_back ();
- _reset_plugin_counts (0); // it worked before we tried to add it ...
+ _reset_processor_counts (0); // it worked before we tried to add it ...
return -1;
}
// Ensure peak vector sizes before the plugin is activated
- ChanCount potential_max_streams = max(processor->input_streams(), processor->output_streams());
- _meter->configure_io(potential_max_streams, potential_max_streams);
+
+ ChanCount potential_max_streams;
+
+ potential_max_streams.set (DataType::AUDIO, max (processor->input_streams().n_audio(),
+ processor->output_streams().n_audio()));
+ potential_max_streams.set (DataType::MIDI, max (processor->input_streams().n_midi(),
+ processor->output_streams().n_midi()));
+
+ _meter->configure_io (potential_max_streams, potential_max_streams);
processor->activate ();
processor->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
@@ -857,7 +871,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
_user_latency = 0;
}
- if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
+ if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) {
reset_panner ();
}
@@ -869,7 +883,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
int
Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
{
- ChanCount old_rmo = processor_max_outs;
+ ChanCount old_pmo = processor_max_outs;
if (!_session.engine().connected()) {
return 1;
@@ -896,14 +910,14 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
}
// Ensure peak vector sizes before the plugin is activated
- _meter->configure_io(potential_max_streams, potential_max_streams);
+ _meter->configure_io (potential_max_streams, potential_max_streams);
_processors.push_back (*i);
- if (_reset_plugin_counts (err)) {
+ if (_reset_processor_counts (err)) {
++existing_end;
_processors.erase (existing_end, _processors.end());
- _reset_plugin_counts (0); // it worked before we tried to add it ...
+ _reset_processor_counts (0); // it worked before we tried to add it ...
return -1;
}
@@ -914,7 +928,7 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
_user_latency = 0;
}
- if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
+ if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) {
reset_panner ();
}
@@ -1064,7 +1078,7 @@ Route::pre_fader_streams() const
void
Route::clear_processors (Placement p)
{
- const ChanCount old_rmo = processor_max_outs;
+ const ChanCount old_pmo = processor_max_outs;
if (!_session.engine().connected()) {
return;
@@ -1088,7 +1102,7 @@ Route::clear_processors (Placement p)
}
/* FIXME: can't see how this test can ever fire */
- if (processor_max_outs != old_rmo) {
+ if (processor_max_outs != old_pmo) {
reset_panner ();
}
@@ -1100,7 +1114,7 @@ Route::clear_processors (Placement p)
int
Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
{
- ChanCount old_rmo = processor_max_outs;
+ ChanCount old_pmo = processor_max_outs;
if (!_session.engine().connected()) {
return 1;
@@ -1118,7 +1132,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
ProcessorList::iterator tmp;
- /* move along, see failure case for reset_plugin_counts()
+ /* move along, see failure case for reset_processor_counts()
where we may need to reprocessor the processor.
*/
@@ -1152,30 +1166,29 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
return 1;
}
- if (_reset_plugin_counts (err)) {
+ if (_reset_processor_counts (err)) {
/* get back to where we where */
_processors.insert (i, processor);
/* we know this will work, because it worked before :) */
- _reset_plugin_counts (0);
+ _reset_processor_counts (0);
return -1;
}
- bool foo = false;
+ _have_internal_generator = false;
for (i = _processors.begin(); i != _processors.end(); ++i) {
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
if (pi->is_generator()) {
- foo = true;
+ _have_internal_generator = true;
+ break;
}
}
}
-
- _have_internal_generator = foo;
}
- if (old_rmo != processor_max_outs) {
+ if (old_pmo != processor_max_outs) {
reset_panner ();
}
@@ -1186,27 +1199,32 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
}
int
-Route::reset_plugin_counts (ProcessorStreams* err)
+Route::reset_processor_counts (ProcessorStreams* err)
{
Glib::RWLock::WriterLock lm (_processor_lock);
- return _reset_plugin_counts (err);
+ return _reset_processor_counts (err);
}
int
-Route::_reset_plugin_counts (ProcessorStreams* err)
+Route::_reset_processor_counts (ProcessorStreams* err)
{
ProcessorList::iterator r;
- map<Placement,list<ProcessorCount> > processor_map;
- ChanCount initial_streams;
- ChanCount post_fader_input;
+ uint32_t insert_cnt = 0;
+ uint32_t send_cnt = 0;
+ map<Placement,list<ProcessorCount> > proc_map;
+ ProcessorList::iterator prev;
+ ChanCount initial_streams = n_inputs ();
+ ChanCount previous_initial_streams = n_inputs ();
int ret = -1;
+ uint32_t max_audio = 0;
+ uint32_t max_midi = 0;
- /* Process each placement in order, checking to see if we
- can really do what has been requested.
- */
+ processor_max_outs.reset ();
- /* divide processors up by placement so we get the signal flow
+ /* Step 1: build a map that links each insert to an in/out channel count
+
+ Divide inserts up by placement so we get the signal flow
properly modelled. we need to do this because the _processors
list is not sorted by placement, and because other reasons may
exist now or in the future for this separate treatment.
@@ -1216,60 +1234,146 @@ Route::_reset_plugin_counts (ProcessorStreams* err)
for (r = _processors.begin(); r != _processors.end(); ++r) {
- boost::shared_ptr<Processor> processor;
+ boost::shared_ptr<PluginInsert> plugin_insert;
+ boost::shared_ptr<PortInsert> port_insert;
+
+ if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert>(*r)) != 0) {
+
+ ++insert_cnt;
+ proc_map[(*r)->placement()].push_back (ProcessorCount (*r));
+
+ /* reset plugin counts back to one for now so
+ that we have a predictable, controlled
+ state to try to configure.
+ */
- if ((processor = boost::dynamic_pointer_cast<Processor>(*r)) != 0) {
- processor_map[processor->placement()].push_back (ProcessorCount (processor));
+ plugin_insert->set_count (1);
+
+ } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert>(*r)) != 0) {
+
+ ++insert_cnt;
+ proc_map[(*r)->placement()].push_back (ProcessorCount (*r));
+
+ } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
+ ++send_cnt;
}
}
+ if (insert_cnt == 0) {
+ if (send_cnt) {
+ goto recompute;
+ } else {
+ ret = 0;
+ goto streamcount;
+ }
+ }
+
+ /* Now process each placement in order, checking to see if we
+ can really do what has been requested.
+ */
+
/* A: PreFader */
- if ( ! check_some_plugin_counts (processor_map[PreFader], n_inputs (), err)) {
+ if (check_some_processor_counts (proc_map[PreFader], n_inputs (), err)) {
goto streamcount;
}
- post_fader_input = (err ? err->count : n_inputs());
+ if (!proc_map[PreFader].empty()) {
+ previous_initial_streams = n_inputs ();
+ for (list<ProcessorCount>::iterator i = proc_map[PreFader].begin(); i != proc_map[PreFader].end(); i++) {
+ if (i->processor->can_support_io_configuration (previous_initial_streams, initial_streams) < 0) {
+ goto streamcount;
+ }
+ previous_initial_streams = initial_streams;
+ }
+ }
/* B: PostFader */
- if ( ! check_some_plugin_counts (processor_map[PostFader], post_fader_input, err)) {
+ if (check_some_processor_counts (proc_map[PostFader], initial_streams, err)) {
goto streamcount;
}
+ if (!proc_map[PostFader].empty()) {
+ for (list<ProcessorCount>::iterator i = proc_map[PostFader].begin(); i != proc_map[PostFader].end(); i++) {
+ if (i->processor->can_support_io_configuration (previous_initial_streams, initial_streams) < 0) {
+ goto streamcount;
+ }
+ previous_initial_streams = initial_streams;
+ }
+ }
+
/* OK, everything can be set up correctly, so lets do it */
- apply_some_plugin_counts (processor_map[PreFader]);
- apply_some_plugin_counts (processor_map[PostFader]);
+ apply_some_processor_counts (proc_map[PreFader]);
+ apply_some_processor_counts (proc_map[PostFader]);
/* recompute max outs of any processor */
ret = 0;
- streamcount:
- processor_max_outs.reset();
+ recompute:
- for (r = _processors.begin(); r != _processors.end(); ++r) {
- processor_max_outs = max ((*r)->output_streams (), processor_max_outs);
+ processor_max_outs.reset ();
+ prev = _processors.end();
+
+ for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
+ boost::shared_ptr<Send> s;
+
+ if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
+ if (r == _processors.begin()) {
+ s->expect_inputs (n_inputs());
+ } else {
+ s->expect_inputs ((*prev)->output_streams());
+ }
+
+ } else {
+
+ /* don't pay any attention to send output configuration, since it doesn't
+ affect the route.
+ */
+
+ max_audio = max ((*r)->output_streams ().n_audio(), max_audio);
+ max_midi = max ((*r)->output_streams ().n_midi(), max_midi);
+ }
}
+ processor_max_outs.set (DataType::AUDIO, max_audio);
+ processor_max_outs.set (DataType::MIDI, max_midi);
+
+ /* we're done */
return 0;
+
+ streamcount:
+ for (r = _processors.begin(); r != _processors.end(); ++r) {
+ max_audio = max ((*r)->output_streams ().n_audio(), max_audio);
+ max_midi = max ((*r)->output_streams ().n_midi(), max_midi);
+ }
+
+ processor_max_outs.set (DataType::AUDIO, max_audio);
+ processor_max_outs.set (DataType::MIDI, max_midi);
+
+ return ret;
}
int32_t
-Route::apply_some_plugin_counts (list<ProcessorCount>& iclist)
+Route::apply_some_processor_counts (list<ProcessorCount>& iclist)
{
list<ProcessorCount>::iterator i;
-
+
for (i = iclist.begin(); i != iclist.end(); ++i) {
-
- cerr << "now applying for " << (*i).processor->name() << " in = " << (*i).in.n_audio() << " out = " << (*i).out.n_audio() << endl;
- if ((*i).processor->configure_io ((*i).in, (*i).out)) {
+ ProcessorCount& pc (*i);
+
+ cerr << "now applying for " << (*i).processor->name() << " in = " << pc.in.n_audio() << " out = " << pc.out.n_audio() << endl;
+
+ if (pc.processor->configure_io (pc.in, pc.out)) {
return -1;
}
+
/* make sure that however many we have, they are all active */
- (*i).processor->activate ();
+
+ pc.processor->activate ();
}
return 0;
@@ -1281,7 +1385,7 @@ Route::apply_some_plugin_counts (list<ProcessorCount>& iclist)
* Otherwise, \a err is set to the output of the list.
*/
bool
-Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err)
+Route::check_some_processor_counts (list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err)
{
list<ProcessorCount>::iterator i;
size_t index = 0;
@@ -1291,12 +1395,11 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require
err->count = required_inputs;
}
- for (i = iclist.begin(); i != iclist.end(); ++i) {
-
+ for (i = iclist.begin(); i != iclist.end(); ++i, ++index) {
cerr << "Checking whether " << (*i).processor->name() << " can support " << required_inputs.n_audio() << " inputs\n";
- if ((*i).processor->can_support_input_configuration (required_inputs) < 0) {
+ if (!(*i).processor->can_support_io_configuration (required_inputs, (*i).out)) {
if (err) {
err->index = index;
err->count = required_inputs;
@@ -1305,20 +1408,7 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require
}
(*i).in = required_inputs;
- (*i).out = (*i).processor->output_for_input_configuration (required_inputs);
-
- cerr << "config looks like " << (*i).processor->name() << " in = " << (*i).in.n_audio() << " out = " << (*i).out.n_audio() << endl;
-
required_inputs = (*i).out;
-
- ++index;
- }
-
- if (err) {
- if (!iclist.empty()) {
- err->index = index;
- err->count = iclist.back().processor->output_for_input_configuration(required_inputs);
- }
}
return true;
@@ -1327,7 +1417,7 @@ Route::check_some_plugin_counts (list<ProcessorCount>& iclist, ChanCount require
int
Route::copy_processors (const Route& other, Placement placement, ProcessorStreams* err)
{
- ChanCount old_rmo = processor_max_outs;
+ ChanCount old_pmo = processor_max_outs;
ProcessorList to_be_deleted;
@@ -1362,7 +1452,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream
/* reset plugin stream handling */
- if (_reset_plugin_counts (err)) {
+ if (_reset_processor_counts (err)) {
/* FAILED COPY ATTEMPT: we have to restore order */
@@ -1383,7 +1473,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream
/* restore the natural order */
_processors = the_copy;
- processor_max_outs = old_rmo;
+ processor_max_outs = old_pmo;
/* we failed, even though things are OK again */
@@ -1397,7 +1487,7 @@ Route::copy_processors (const Route& other, Placement placement, ProcessorStream
}
}
- if (processor_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
+ if (processor_max_outs != old_pmo || old_pmo == ChanCount::ZERO) {
reset_panner ();
}
@@ -1457,7 +1547,7 @@ Route::sort_processors (ProcessorStreams* err)
{
ProcessorSorter comparator;
Glib::RWLock::WriterLock lm (_processor_lock);
- ChanCount old_rmo = processor_max_outs;
+ ChanCount old_pmo = processor_max_outs;
/* the sweet power of C++ ... */
@@ -1465,9 +1555,9 @@ Route::sort_processors (ProcessorStreams* err)
_processors.sort (comparator);
- if (_reset_plugin_counts (err)) {
+ if (_reset_processor_counts (err)) {
_processors = as_it_was_before;
- processor_max_outs = old_rmo;
+ processor_max_outs = old_pmo;
return -1;
}
}
@@ -2334,7 +2424,7 @@ void
Route::input_change_handler (IOChange change, void *ignored)
{
if (change & ConfigurationChanged) {
- reset_plugin_counts (0);
+ reset_processor_counts (0);
}
}
@@ -2346,7 +2436,7 @@ Route::output_change_handler (IOChange change, void *ignored)
_control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().n_audio()), true, this);
}
- reset_plugin_counts (0);
+ reset_processor_counts (0);
}
}
@@ -2540,6 +2630,11 @@ Route::update_total_latency ()
}
}
+#undef DEBUG_LATENCY
+#ifdef DEBUG_LATENCY
+ cerr << _name << ": internal redirect latency = " << _own_latency << endl;
+#endif
+
set_port_latency (_own_latency);
if (!_user_latency) {
@@ -2558,6 +2653,11 @@ Route::update_total_latency ()
signal_latency_changed (); /* EMIT SIGNAL */
}
+#ifdef DEBUG_LATENCY
+ cerr << _name << ": input latency = " << input_latency() << " total = "
+ << _own_latency << endl;
+#endif
+
return _own_latency;
}