From 91b875148ab8b86effc9a462d5ff06381975bbf9 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 3 Apr 2016 03:11:18 +0200 Subject: [PATCH] expose plugin sidechain (via route): 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 | 3 ++ libs/ardour/luabindings.cc | 2 + libs/ardour/route.cc | 97 ++++++++++++++++++++++++++++++++------ 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index b103abf45b..8c71e87e94 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -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 proc); bool customize_plugin_insert (boost::shared_ptr proc, uint32_t count, ChanCount outs); + bool add_remove_sidechain (boost::shared_ptr proc, bool); + bool add_sidechain (boost::shared_ptr proc) { return add_remove_sidechain (proc, true); } + bool remove_sidechain (boost::shared_ptr 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; diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index fbbb73ba87..33506ee6a9 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -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") diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index c0cbcf21dc..76f88a3ce2 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1769,9 +1769,15 @@ Route::remove_processor (boost::shared_ptr processor, ProcessorStream run. */ - boost::shared_ptr iop; + boost::shared_ptr iop = boost::dynamic_pointer_cast (*i); + boost::shared_ptr pi = boost::dynamic_pointer_cast(*i); - if ((iop = boost::dynamic_pointer_cast (*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 iop; + boost::shared_ptr iop = boost::dynamic_pointer_cast(processor); + boost::shared_ptr pi = boost::dynamic_pointer_cast(processor); + if (pi != 0) { + assert (iop == 0); + iop = pi->sidechain(); + } - if ((iop = boost::dynamic_pointer_cast (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 proc, bool add) +{ + boost::shared_ptr pi; + if ((pi = boost::dynamic_pointer_cast(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 > 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 proc) { @@ -2420,15 +2489,9 @@ Route::customize_plugin_insert (boost::shared_ptr 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 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 other, bool* for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); ++r) { - boost::shared_ptr iop; + boost::shared_ptr iop = boost::dynamic_pointer_cast(*r); + boost::shared_ptr pi = boost::dynamic_pointer_cast(*r); + if (pi != 0) { + assert (iop == 0); + iop = pi->sidechain(); + } - if ((iop = boost::dynamic_pointer_cast(*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) {