fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / plugin_insert.cc
index a8757fc97e53b80785457a0b21f4fe36e927f181..9a0e6c55c40574e32cd001bf5e3df688593e625c 100644 (file)
@@ -57,7 +57,7 @@
 #include "ardour/session.h"
 #include "ardour/types.h"
 
 #include "ardour/session.h"
 #include "ardour/types.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
 
 using namespace std;
 using namespace ARDOUR;
@@ -69,6 +69,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
        : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
        , _sc_playback_latency (0)
        , _sc_capture_latency (0)
        : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
        , _sc_playback_latency (0)
        , _sc_capture_latency (0)
+       , _plugin_signal_latency (0)
        , _signal_analysis_collected_nframes(0)
        , _signal_analysis_collect_nframes_max(0)
        , _configured (false)
        , _signal_analysis_collected_nframes(0)
        , _signal_analysis_collect_nframes_max(0)
        , _configured (false)
@@ -84,8 +85,8 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
                add_plugin (plug);
                create_automatable_parameters ();
                const ChanCount& sc (sidechain_input_pins ());
                add_plugin (plug);
                create_automatable_parameters ();
                const ChanCount& sc (sidechain_input_pins ());
-               if (sc.n_audio () > 0) {
-                       add_sidechain (sc.n_audio ());
+               if (sc.n_audio () > 0 || sc.n_midi () > 0) {
+                       add_sidechain (sc.n_audio (), sc.n_midi ());
                }
        }
 }
                }
        }
 }
@@ -189,14 +190,14 @@ PluginInsert::set_preset_out (const ChanCount& c)
 }
 
 bool
 }
 
 bool
-PluginInsert::add_sidechain (uint32_t n_audio)
+PluginInsert::add_sidechain (uint32_t n_audio, uint32_t n_midi)
 {
        // caller must hold process lock
        if (_sidechain) {
                return false;
        }
        std::ostringstream n;
 {
        // caller must hold process lock
        if (_sidechain) {
                return false;
        }
        std::ostringstream n;
-       if (n_audio > 0) {
+       if (n_audio > 0 || n_midi > 0) {
                n << "Sidechain " << Session::next_name_id ();
        } else {
                n << "TO BE RESET FROM XML";
                n << "Sidechain " << Session::next_name_id ();
        } else {
                n << "TO BE RESET FROM XML";
@@ -205,7 +206,10 @@ PluginInsert::add_sidechain (uint32_t n_audio)
        _sidechain = boost::shared_ptr<SideChain> (sc);
        _sidechain->activate ();
        for (uint32_t n = 0; n < n_audio; ++n) {
        _sidechain = boost::shared_ptr<SideChain> (sc);
        _sidechain->activate ();
        for (uint32_t n = 0; n < n_audio; ++n) {
-               _sidechain->input()->add_port ("", owner()); // add a port, don't connect.
+               _sidechain->input()->add_port ("", owner(), DataType::AUDIO); // add a port, don't connect.
+       }
+       for (uint32_t n = 0; n < n_midi; ++n) {
+               _sidechain->input()->add_port ("", owner(), DataType::MIDI); // add a port, don't connect.
        }
        PluginConfigChanged (); /* EMIT SIGNAL */
        return true;
        }
        PluginConfigChanged (); /* EMIT SIGNAL */
        return true;
@@ -551,6 +555,17 @@ PluginInsert::activate ()
        }
 
        Processor::activate ();
        }
 
        Processor::activate ();
+       /* when setting state e.g ProcessorBox::paste_processor_state ()
+        * the plugin is not yet owned by a route.
+        * but no matter.  Route::add_processors() will call activate () again
+        */
+       if (!owner ()) {
+               return;
+       }
+       if (_plugin_signal_latency != signal_latency ()) {
+               _plugin_signal_latency = signal_latency ();
+               latency_changed ();
+       }
 }
 
 void
 }
 
 void
@@ -561,6 +576,10 @@ PluginInsert::deactivate ()
        for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->deactivate ();
        }
        for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
                (*i)->deactivate ();
        }
+       if (_plugin_signal_latency != signal_latency ()) {
+               _plugin_signal_latency = signal_latency ();
+               latency_changed ();
+       }
 }
 
 void
 }
 
 void
@@ -914,6 +933,11 @@ PluginInsert::connect_and_run (BufferSet& bufs, framepos_t start, framepos_t end
                                             &_signal_analysis_outputs);
                }
        }
                                             &_signal_analysis_outputs);
                }
        }
+
+       if (_plugin_signal_latency != signal_latency ()) {
+               _plugin_signal_latency = signal_latency ();
+               latency_changed ();
+       }
 }
 
 void
 }
 
 void
@@ -1332,7 +1356,7 @@ PluginInsert::no_sc_input_map () const
                for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
                        uint32_t ins = natural_input_streams().get(tm->first) - _cached_sidechain_pins.get(tm->first);
                        for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
                for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
                        uint32_t ins = natural_input_streams().get(tm->first) - _cached_sidechain_pins.get(tm->first);
                        for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
-                               if (i->second < ins) {
+                               if (i->first < ins) {
                                        rv.set (tm->first, i->first + pc * ins, i->second);
                                }
                        }
                                        rv.set (tm->first, i->first + pc * ins, i->second);
                                }
                        }
@@ -2144,7 +2168,7 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha
 
        uint32_t f             = 0;
        bool     can_replicate = true;
 
        uint32_t f             = 0;
        bool     can_replicate = true;
-       for (DataType::iterator t = DataType::begin(); t != DataType::end() && can_replicate; ++t) {
+       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
 
                // ignore side-chains
                uint32_t nin = ns_inputs.get (*t);
 
                // ignore side-chains
                uint32_t nin = ns_inputs.get (*t);
@@ -2699,6 +2723,9 @@ PluginInsert::describe_parameter (Evoral::Parameter param)
 ARDOUR::framecnt_t
 PluginInsert::signal_latency() const
 {
 ARDOUR::framecnt_t
 PluginInsert::signal_latency() const
 {
+       if (!_pending_active) {
+               return 0;
+       }
        if (_user_latency) {
                return _user_latency;
        }
        if (_user_latency) {
                return _user_latency;
        }
@@ -2845,7 +2872,14 @@ PluginInsert::get_impulse_analysis_plugin()
                // during init() -- most notably block_size..
                // not great.
                ret = plugin_factory(_plugins[0]);
                // during init() -- most notably block_size..
                // not great.
                ret = plugin_factory(_plugins[0]);
-               ret->configure_io (internal_input_streams (), internal_output_streams ());
+               ChanCount out (internal_output_streams ());
+               if (ret->get_info ()->reconfigurable_io ()) {
+                       // populate get_info ()->n_inputs and ->n_outputs
+                       ChanCount useins;
+                       ret->can_support_io_configuration (internal_input_streams (), out, &useins);
+                       assert (out == internal_output_streams ());
+               }
+               ret->configure_io (internal_input_streams (), out);
                _impulseAnalysisPlugin = ret;
        } else {
                ret = _impulseAnalysisPlugin.lock();
                _impulseAnalysisPlugin = ret;
        } else {
                ret = _impulseAnalysisPlugin.lock();
@@ -2878,7 +2912,6 @@ PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
                plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed_externally, this, _1, _2));
                plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
                plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
                plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed_externally, this, _1, _2));
                plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
                plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
-               plugin->LatencyChanged.connect_same_thread (*this, boost::bind (&PluginInsert::latency_changed, this, _1, _2));
                _custom_sinks = plugin->get_info()->n_inputs;
                // cache sidechain port count
                _cached_sidechain_pins.reset ();
                _custom_sinks = plugin->get_info()->n_inputs;
                // cache sidechain port count
                _cached_sidechain_pins.reset ();
@@ -2939,10 +2972,13 @@ PluginInsert::monitoring_changed ()
 }
 
 void
 }
 
 void
-PluginInsert::latency_changed (framecnt_t, framecnt_t)
+PluginInsert::latency_changed ()
 {
        // this is called in RT context, LatencyChanged is emitted after run()
        _latency_changed = true;
 {
        // this is called in RT context, LatencyChanged is emitted after run()
        _latency_changed = true;
+       // XXX This also needs a proper API not an owner() hack.
+       assert (owner ());
+       static_cast<Route*>(owner ())->processor_latency_changed (); /* EMIT SIGNAL */
 }
 
 void
 }
 
 void