special case mixbus routing
[ardour.git] / libs / ardour / route.cc
index 730176405ee5e6a6cce8d4ae306e4c1d61423c32..51fc33a39509cb97bb83c0295d8163876bc637fc 100644 (file)
@@ -79,6 +79,7 @@ using namespace PBD;
 PBD::Signal0<void> Route::SyncOrderKeys;
 PBD::Signal0<void> Route::RemoteControlIDChange;
 
+/** Base class for all routable/mixable objects (tracks and busses) */
 Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        : SessionObject (sess, name)
        , Automatable (sess)
@@ -1465,7 +1466,6 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                        boost::shared_ptr<PluginInsert> pi;
 
                        if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
-                               pi->set_count (1); // why? configure_processors_unlocked() will re-do this
                                pi->set_strict_io (_strict_io);
                        }
 
@@ -2080,6 +2080,31 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
        for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
 
                if ((*p)->can_support_io_configuration(in, out)) {
+
+                       if (boost::dynamic_pointer_cast<Delivery> (*p)
+                                       && boost::dynamic_pointer_cast<Delivery> (*p)->role() == Delivery::Main
+                                       && ( _strict_io || Profile->get_mixbus ())) {
+                               /* with strict I/O the panner + output are forced to
+                                * follow the last processor's output.
+                                *
+                                * Delivery::can_support_io_configuration() will only add ports,
+                                * but not remove excess ports.
+                                *
+                                * This works because the delivery only requires
+                                * as many outputs as there are inputs.
+                                * Delivery::configure_io() will do the actual removal
+                                * by calling _output->ensure_io()
+                                */
+                               if (!is_master() && _session.master_out ()) {
+                                       /* ..but at least as many as there are master-inputs */
+                                       // XXX this may need special-casing for mixbus (master-outputs)
+                                       // and should maybe be a preference anyway ?!
+                                       out = ChanCount::max (in, _session.master_out ()->n_inputs ());
+                               } else {
+                                       out = in;
+                               }
+                       }
+
                        DEBUG_TRACE (DEBUG::Processors, string_compose ("\t%1 ID=%2 in=%3 out=%4\n",(*p)->name(), (*p)->id(), in, out));
                        configuration.push_back(make_pair(in, out));
 
@@ -2174,17 +2199,18 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
                processor_max_streams = ChanCount::max(processor_max_streams, c->first);
                processor_max_streams = ChanCount::max(processor_max_streams, c->second);
 
+               boost::shared_ptr<IOProcessor> iop;
                boost::shared_ptr<PluginInsert> pi;
                if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
                        /* plugins connected via Split or Hide Match may have more channels.
                         * route/scratch buffers are needed for all of them
                         * The configuration may only be a subset (both input and output)
                         */
-                       processor_max_streams = ChanCount::max(processor_max_streams, pi->input_streams());
-                       processor_max_streams = ChanCount::max(processor_max_streams, pi->internal_streams());
-                       processor_max_streams = ChanCount::max(processor_max_streams, pi->output_streams());
-                       processor_max_streams = ChanCount::max(processor_max_streams, pi->natural_input_streams() * pi->get_count());
-                       processor_max_streams = ChanCount::max(processor_max_streams, pi->natural_output_streams() * pi->get_count());
+                       processor_max_streams = ChanCount::max(processor_max_streams, pi->required_buffers());
+               }
+               else if ((iop = boost::dynamic_pointer_cast<IOProcessor>(*p)) != 0) {
+                       processor_max_streams = ChanCount::max(processor_max_streams, iop->natural_input_streams());
+                       processor_max_streams = ChanCount::max(processor_max_streams, iop->natural_output_streams());
                }
                out = c->second;
 
@@ -2539,6 +2565,8 @@ Route::customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t coun
 bool
 Route::set_strict_io (const bool enable)
 {
+       Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
+
        if (_strict_io != enable) {
                _strict_io = enable;
                Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
@@ -2564,10 +2592,9 @@ Route::set_strict_io (const bool enable)
                }
                lm.release ();
 
-               {
-                       Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
-                       configure_processors (0);
-               }
+               configure_processors (0);
+               lx.release ();
+
                processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
                _session.set_dirty ();
        }
@@ -4732,6 +4759,9 @@ Route::input_port_count_changing (ChanCount to)
 bool
 Route::output_port_count_changing (ChanCount to)
 {
+       if (_strict_io && !_in_configure_processors) {
+               return true;
+       }
        for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
                if (processor_out_streams.get(*t) > to.get(*t)) {
                        return true;