prepare strict-i/o configuration.
authorRobin Gareus <robin@gareus.org>
Fri, 25 Mar 2016 19:00:48 +0000 (20:00 +0100)
committerRobin Gareus <robin@gareus.org>
Fri, 25 Mar 2016 19:00:48 +0000 (20:00 +0100)
libs/ardour/ardour/plugin_insert.h
libs/ardour/ardour/route.h
libs/ardour/plugin_insert.cc
libs/ardour/route.cc

index ed97126e348cd703140e79843f657954354dc731..fa1fc1be95af9bb10b2f5491019aff132261c3fb 100644 (file)
@@ -143,6 +143,14 @@ class LIBARDOUR_API PluginInsert : public Processor
 
        void collect_signal_for_analysis (framecnt_t nframes);
 
+       void set_strict_io (bool b) {
+               _strict_io = b;
+       }
+
+       bool strict_io_configured () const {
+               return _strict_io_configured;
+       }
+
        bool splitting () const {
                return _match.method == Split;
        }
@@ -191,6 +199,9 @@ class LIBARDOUR_API PluginInsert : public Processor
        ChanCount _configured_in;
        ChanCount _configured_out;
 
+       bool _strict_io;
+       bool _strict_io_configured;
+
        /** Description of how we can match our plugin's IO to our own insert IO */
        struct Match {
                Match () : method (Impossible), plugins (0) {}
index bb6bc4816a2461a260994053cdcdb787d214e84a..990f1670549be95c137070922d74426f7c49b4d4 100644 (file)
@@ -274,6 +274,9 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        void clear_processors (Placement);
        void all_visible_processors_active (bool);
 
+       bool strict_io () const { return _strict_io; }
+       bool set_strict_io (bool);
+
        framecnt_t set_private_port_latencies (bool playback) const;
        void       set_public_port_latencies (framecnt_t, bool playback) const;
 
@@ -833,6 +836,8 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 
        friend class ProcessorState;
 
+       bool _strict_io;
+
        /* no copy construction */
        Route (Route const &);
 
index 19571c6b5faff5d53b8352547def2b52dd013491..ac3ef46155f16565b4f2306b0dbef422c6a002c3 100644 (file)
@@ -68,6 +68,8 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
        : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
        , _signal_analysis_collected_nframes(0)
        , _signal_analysis_collect_nframes_max(0)
+       , _strict_io (false)
+       , _strict_io_configured (false)
 {
        /* the first is the master */
 
@@ -138,7 +140,10 @@ PluginInsert::output_streams() const
 
        PluginInfoPtr info = _plugins.front()->get_info();
 
-       if (info->reconfigurable_io()) {
+       if (_strict_io_configured) {
+               return _configured_in; // XXX, check initial configuration
+       }
+       else if (info->reconfigurable_io()) {
                ChanCount out = _plugins.front()->output_streams ();
                // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out));
                return out;
@@ -807,6 +812,7 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
 PluginInsert::Match
 PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out)
 {
+       _strict_io_configured = false;
        if (_plugins.empty()) {
                return Match();
        }
@@ -822,6 +828,11 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
                        return Match (Impossible, 0);
                }
 
+               if (_strict_io && in.n_audio() < out.n_audio()) {
+                       DEBUG_TRACE (DEBUG::Processors, string_compose ("hiding output ports of reconfigurable %1\n", name()));
+                       out.set (DataType::AUDIO, in.get (DataType::AUDIO));
+               }
+
                return Match (Delegate, 1);
        }
 
@@ -852,7 +863,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
        }
 
        /* Plugin inputs match requested inputs exactly */
-       if (inputs == in) {
+       if (inputs == in  && (!_strict_io || outputs.n_audio() == inputs.n_audio())) {
                out = outputs + midi_bypass;
                return Match (ExactMatch, 1);
        }
@@ -907,7 +918,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
           plugin inputs?  Let me count the ways ...
        */
 
-       bool can_split = true;
+       bool can_split = !_strict_io;
        for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
 
                bool const can_split_type = (in.get (*t) == 1 && inputs.get (*t) > 1);
@@ -943,7 +954,12 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC
        }
 
        if (could_hide && !cannot_hide) {
-               out = outputs + midi_bypass;
+               if (_strict_io && inputs.get (DataType::AUDIO) == outputs.get (DataType::AUDIO)) {
+                       _strict_io_configured = true;
+                       outputs = inputs;
+               } else {
+                       out = outputs + midi_bypass;
+               }
                return Match (Hide, 1, hide_channels);
        }
 
index 30e901cfba5900b54e8b3689f49576bbb89cf4d1..573660d038c41d504163b430117003b4ea628dd1 100644 (file)
@@ -115,6 +115,7 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _track_number (0)
        , _in_configure_processors (false)
        , _initial_io_setup (false)
+       , _strict_io (false)
        , _custom_meter_position_noted (false)
 {
        processor_max_streams.reset();
@@ -1257,6 +1258,13 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
                return 1;
        }
 
+       if (_strict_io) {
+               boost::shared_ptr<PluginInsert> pi;
+               if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
+                       pi->set_strict_io (true);
+               }
+       }
+
        {
                Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
@@ -1456,6 +1464,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
 
                        if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
                                pi->set_count (1);
+                               pi->set_strict_io (_strict_io);
                        }
 
                        _processors.insert (loc, *i);
@@ -1839,6 +1848,11 @@ Route::replace_processor (boost::shared_ptr<Processor> old, boost::shared_ptr<Pr
                return 1;
        }
 
+       /* ensure that sub is not owned by another route */
+       if (sub->owner ()) {
+               return 1;
+       }
+
        {
                Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
@@ -1866,6 +1880,13 @@ Route::replace_processor (boost::shared_ptr<Processor> old, boost::shared_ptr<Pr
                        return 1;
                }
 
+               if (_strict_io) {
+                       boost::shared_ptr<PluginInsert> pi;
+                       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(sub)) != 0) {
+                               pi->set_strict_io (true);
+                       }
+               }
+
                if (configure_processors_unlocked (err)) {
                        pstate.restore ();
                        configure_processors_unlocked (0);
@@ -2376,6 +2397,44 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
        return 0;
 }
 
+bool
+Route::set_strict_io (const bool enable)
+{
+       if (_strict_io != enable) {
+               _strict_io = enable;
+               Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
+               for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
+                       boost::shared_ptr<PluginInsert> pi;
+                       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
+                               pi->set_strict_io (_strict_io);
+                       }
+               }
+
+               list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
+
+               if (c.empty()) {
+                       // not possible
+                       _strict_io = !enable; // restore old value
+                       for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
+                               boost::shared_ptr<PluginInsert> pi;
+                               if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
+                                       pi->set_strict_io (_strict_io);
+                               }
+                       }
+                       return false;
+               }
+               lm.release ();
+
+               {
+                       Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
+                       configure_processors (0);
+               }
+               processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+               _session.set_dirty ();
+       }
+       return true;
+}
+
 XMLNode&
 Route::get_state()
 {
@@ -2404,6 +2463,7 @@ Route::state(bool full_state)
        node->add_property("id", buf);
        node->add_property ("name", _name);
        node->add_property("default-type", _default_type.to_string());
+       node->add_property ("strict-io", _strict_io);
 
        if (_flags) {
                node->add_property("flags", enum_2_string (_flags));
@@ -2527,6 +2587,10 @@ Route::set_state (const XMLNode& node, int version)
                _flags = Flag (0);
        }
 
+       if ((prop = node.property (X_("strict-io"))) != 0) {
+               _strict_io = string_is_affirmative (prop->value());
+       }
+
        if (is_master() || is_monitor() || is_auditioner()) {
                _mute_master->set_solo_ignore (true);
        }
@@ -3078,6 +3142,11 @@ Route::set_processor_state (const XMLNode& node)
                                                processor.reset (new UnknownProcessor (_session, **niter));
                                        } else {
                                                processor.reset (new PluginInsert (_session));
+                                               if (_strict_io) {
+                                                       boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert>(processor);
+                                                       pi->set_strict_io (true);
+                                               }
+
                                        }
                                } else if (prop->value() == "port") {