expose plugin sidechain (via route):
authorRobin Gareus <robin@gareus.org>
Sun, 3 Apr 2016 01:11:18 +0000 (03:11 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 3 Apr 2016 01:11:18 +0000 (03:11 +0200)
Processor and Process lock are needed, and the plugin chain needs to be
reconfigured, so this cannot be directly performed by the plugin.

libs/ardour/ardour/route.h
libs/ardour/luabindings.cc
libs/ardour/route.cc

index b103abf45bb408634c2bf5e635184252681927e4..8c71e87e94b2dd47ced9c9ff730517842013a4fc 100644 (file)
@@ -278,6 +278,9 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        bool set_strict_io (bool);
        bool reset_plugin_insert (boost::shared_ptr<Processor> proc);
        bool customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t count, ChanCount outs);
+       bool add_remove_sidechain (boost::shared_ptr<Processor> proc, bool);
+       bool add_sidechain (boost::shared_ptr<Processor> proc) { return add_remove_sidechain (proc, true); }
+       bool remove_sidechain (boost::shared_ptr<Processor> proc) { return add_remove_sidechain (proc, false); }
 
        framecnt_t set_private_port_latencies (bool playback) const;
        void       set_public_port_latencies (framecnt_t, bool playback) const;
index fbbb73ba870a9bb2ec7019bba887a146dc2eca7a..33506ee6a9f7ca284a51ebee46cf651a35b2e3c6 100644 (file)
@@ -257,6 +257,8 @@ LuaBindings::common (lua_State* L)
                .addFunction ("set_strict_io", &Route::set_strict_io)
                .addFunction ("reset_plugin_insert", &Route::reset_plugin_insert)
                .addFunction ("customize_plugin_insert", &Route::customize_plugin_insert)
+               .addFunction ("add_sidechain", &Route::add_sidechain)
+               .addFunction ("remove_sidechain", &Route::remove_sidechain)
                .endClass ()
 
                .deriveWSPtrClass <Track, Route> ("Track")
index c0cbcf21dcf472547530ca10792db86aec4810d3..76f88a3ce239b3251dc87b109e6c5b9c53276e96 100644 (file)
@@ -1769,9 +1769,15 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                                   run.
                                */
 
-                               boost::shared_ptr<IOProcessor> iop;
+                               boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (*i);
+                               boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert>(*i);
 
-                               if ((iop = boost::dynamic_pointer_cast<IOProcessor> (*i)) != 0) {
+                               if (pi != 0) {
+                                       assert (iop == 0);
+                                       iop = pi->sidechain();
+                               }
+
+                               if (iop != 0) {
                                        iop->disconnect ();
                                }
 
@@ -1963,9 +1969,14 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
                           run.
                        */
 
-                       boost::shared_ptr<IOProcessor> iop;
+                       boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor>(processor);
+                       boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert>(processor);
+                       if (pi != 0) {
+                               assert (iop == 0);
+                               iop = pi->sidechain();
+                       }
 
-                       if ((iop = boost::dynamic_pointer_cast<IOProcessor> (processor)) != 0) {
+                       if (iop != 0) {
                                iop->disconnect ();
                        }
 
@@ -2169,6 +2180,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
                         * 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());
@@ -2404,6 +2416,63 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
        return 0;
 }
 
+bool
+Route::add_remove_sidechain (boost::shared_ptr<Processor> proc, bool add)
+{
+       boost::shared_ptr<PluginInsert> pi;
+       if ((pi = boost::dynamic_pointer_cast<PluginInsert>(proc)) == 0) {
+               return false;
+       }
+
+       if (pi->has_sidechain () == add) {
+               return true; // ?? call failed, but result is as expected.
+       }
+
+       {
+               Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
+               ProcessorList::iterator i = find (_processors.begin(), _processors.end(), proc);
+               if (i == _processors.end ()) {
+                       return false;
+               }
+       }
+
+       {
+               Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); // take before Writerlock to avoid deadlock
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+
+               lx.release (); // IO::add_port() and ~IO takes process lock  - XXX check if this is safe
+               if (add) {
+                       if (!pi->add_sidechain ()) {
+                               return false;
+                       }
+               } else {
+                       if (!pi->del_sidechain ()) {
+                               return false;
+                       }
+               }
+
+               lx.acquire ();
+               list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
+               lx.release ();
+
+               if (c.empty()) {
+                       if (add) {
+                               pi->del_sidechain ();
+                       } else {
+                               pi->add_sidechain ();
+                               // TODO restore side-chain's state.
+                       }
+                       return false;
+               }
+               lx.acquire ();
+               configure_processors_unlocked (0);
+       }
+
+       processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+       _session.set_dirty ();
+       return true;
+}
+
 bool
 Route::reset_plugin_insert (boost::shared_ptr<Processor> proc)
 {
@@ -2420,15 +2489,9 @@ Route::customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t coun
        }
 
        {
-               bool found = false;
                Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
-               for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
-                       if (*p == proc) {
-                               found = true;
-                               break;
-                       }
-               }
-               if (!found) {
+               ProcessorList::iterator i = find (_processors.begin(), _processors.end(), proc);
+               if (i == _processors.end ()) {
                        return false;
                }
        }
@@ -2436,7 +2499,6 @@ Route::customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t coun
        {
                Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
-               ProcessorState pstate (this);
 
                bool      old_cust = pi->custom_cfg ();
                uint32_t  old_cnt  = pi->get_count ();
@@ -3544,9 +3606,14 @@ Route::direct_feeds_according_to_reality (boost::shared_ptr<Route> other, bool*
 
        for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) {
 
-               boost::shared_ptr<IOProcessor> iop;
+               boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor>(*r);
+               boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert>(*r);
+               if (pi != 0) {
+                       assert (iop == 0);
+                       iop = pi->sidechain();
+               }
 
-               if ((iop = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
+               if (iop != 0) {
                        if (iop->feeds (other)) {
                                DEBUG_TRACE (DEBUG::Graph,  string_compose ("\tIOP %1 does feed %2\n", iop->name(), other->name()));
                                if (via_send_only) {