handle sidechain input changes
authorRobin Gareus <robin@gareus.org>
Sun, 3 Apr 2016 03:14:05 +0000 (05:14 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 3 Apr 2016 03:16:54 +0000 (05:16 +0200)
libs/ardour/ardour/plugin_insert.h
libs/ardour/ardour/route.h
libs/ardour/plugin_insert.cc
libs/ardour/route.cc

index d9e4b28d72beccc6dde950c7687f375e9c7b79de..db7f0bc3be73fcbb707a296fa1c687aa75aa0285 100644 (file)
@@ -119,6 +119,7 @@ class LIBARDOUR_API PluginInsert : public Processor
        void set_custom_cfg (bool b);
        bool add_sidechain  (uint32_t n_audio = 1);
        bool del_sidechain ();
+       boost::shared_ptr<SideChain> sidechain () const { return _sidechain; }
        // end C++ class slavery!
 
        uint32_t get_count  () const { return _plugins.size(); }
@@ -185,14 +186,6 @@ class LIBARDOUR_API PluginInsert : public Processor
                return _sidechain ? true : false;
        }
 
-       // XXX dangerous
-       boost::shared_ptr<SideChain> sidechain () const {
-               return _sidechain;
-       }
-
-       // XXX even more dangerous (adding/removing ports
-       // must be done by the owning route and the plugin
-       // needs to be reconfigured afterwards)
        boost::shared_ptr<IO> sidechain_input () const {
                if (_sidechain) {
                        return _sidechain->input ();
index 8c71e87e94b2dd47ced9c9ff730517842013a4fc..d673bc75bf0dc8cf86eadf6ab36d3c60eda473b6 100644 (file)
@@ -783,12 +783,14 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
 
        void input_change_handler (IOChange, void *src);
        void output_change_handler (IOChange, void *src);
+       void sidechain_change_handler (IOChange, void *src);
 
        bool input_port_count_changing (ChanCount);
        bool output_port_count_changing (ChanCount);
 
        bool _in_configure_processors;
        bool _initial_io_setup;
+       bool _in_sidechain_setup;
 
        int configure_processors_unlocked (ProcessorStreams*);
        bool set_meter_point_unlocked ();
index 250eaae11e856de0bcd0650a02affccd9dc0b963..3f1146c861c79ff7d5014b9379502b01bb0cefac 100644 (file)
@@ -687,7 +687,7 @@ PluginInsert::silence (framecnt_t nframes)
        ChanMapping in_map (natural_input_streams ());
        ChanMapping out_map (natural_output_streams ());
 
-       // TODO fake run sidechain, too? (maybe once it has meters)
+       // TODO run sidechain (delaylines)
        for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0);
        }
@@ -700,7 +700,8 @@ PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame
                /* run as normal if we are active or moving from inactive to active */
 
                if (_sidechain) {
-                       // collect sidechain input for complete cycle.
+                       // collect sidechain input for complete cycle (!)
+                       // TODO we need delaylines here for latency compensation
                        _sidechain->run (bufs, start_frame, end_frame, nframes, true);
                }
 
index 76f88a3ce239b3251dc87b109e6c5b9c53276e96..44c0028926bc05e42afaeb9a95e5ef1bcddcdc5e 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)
+       , _in_sidechain_setup (false)
        , _strict_io (false)
        , _custom_meter_position_noted (false)
 {
@@ -2439,6 +2440,7 @@ Route::add_remove_sidechain (boost::shared_ptr<Processor> proc, bool add)
        {
                Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); // take before Writerlock to avoid deadlock
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+               PBD::Unwinder<bool> uw (_in_sidechain_setup, true);
 
                lx.release (); // IO::add_port() and ~IO takes process lock  - XXX check if this is safe
                if (add) {
@@ -2468,6 +2470,10 @@ Route::add_remove_sidechain (boost::shared_ptr<Processor> proc, bool add)
                configure_processors_unlocked (0);
        }
 
+       if (pi->has_sidechain ()) {
+               pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2));
+       }
+
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
        _session.set_dirty ();
        return true;
@@ -3300,6 +3306,12 @@ Route::set_processor_state (const XMLNode& node)
                                        processor.reset (new UnknownProcessor (_session, **niter));
                                }
 
+                               /* subscribe to Sidechain IO changes */
+                               boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (processor);
+                               if (pi && pi->has_sidechain ()) {
+                                       pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2));
+                               }
+
                                /* we have to note the monitor send here, otherwise a new one will be created
                                   and the state of this one will be lost.
                                */
@@ -3808,6 +3820,21 @@ Route::output_change_handler (IOChange change, void * /*src*/)
        }
 }
 
+void
+Route::sidechain_change_handler (IOChange change, void * /*src*/)
+{
+       if (_initial_io_setup || _in_sidechain_setup) {
+               return;
+       }
+
+       if ((change.type & IOChange::ConfigurationChanged)) {
+               /* This is called with the process lock held if change
+                  contains ConfigurationChanged
+               */
+               configure_processors (0);
+       }
+}
+
 uint32_t
 Route::pans_required () const
 {