enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / ardour / plugin_insert.cc
index 0de2d7fe5a8dc0b1af4b0048615623883f8b62d9..7fb799d4923e22cbf24c0f606b744702d0ddf588 100644 (file)
@@ -57,7 +57,7 @@
 #include "ardour/session.h"
 #include "ardour/types.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 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)
+       , _plugin_signal_latency (0)
        , _signal_analysis_collected_nframes(0)
        , _signal_analysis_collect_nframes_max(0)
        , _configured (false)
@@ -76,6 +77,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
        , _strict_io (false)
        , _custom_cfg (false)
        , _maps_from_state (false)
+       , _bypass_port (UINT32_MAX)
 {
        /* the first is the master */
 
@@ -457,6 +459,7 @@ PluginInsert::create_automatable_parameters ()
                plugin->set_automation_control (i, c);
        }
 
+
        const Plugin::PropertyDescriptors& pdl (plugin->get_supported_properties ());
        for (Plugin::PropertyDescriptors::const_iterator p = pdl.begin(); p != pdl.end(); ++p) {
                Evoral::Parameter param (PluginPropertyAutomation, 0, p->first);
@@ -469,6 +472,16 @@ PluginInsert::create_automatable_parameters ()
                        add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
                }
        }
+
+       _bypass_port = plugin->designated_bypass_port ();
+
+       if (_bypass_port != UINT32_MAX) {
+               boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port));
+               if (0 == (ac->flags () & Controllable::NotAutomatable)) {
+                       ac->alist()->automation_state_changed.connect_same_thread (*this, boost::bind (&PluginInsert::bypassable_changed, this));
+                       ac->Changed.connect_same_thread (*this, boost::bind (&PluginInsert::enable_changed, this));
+               }
+       }
 }
 /** Called when something outside of this host has modified a plugin
  * parameter. Responsible for propagating the change to two places:
@@ -539,6 +552,10 @@ PluginInsert::activate ()
        }
 
        Processor::activate ();
+       if (_plugin_signal_latency != signal_latency ()) {
+               _plugin_signal_latency = signal_latency ();
+               latency_changed ();
+       }
 }
 
 void
@@ -549,6 +566,10 @@ PluginInsert::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
@@ -559,6 +580,60 @@ PluginInsert::flush ()
        }
 }
 
+void
+PluginInsert::enable (bool yn)
+{
+       if (_bypass_port == UINT32_MAX) {
+               if (yn) {
+                       activate ();
+               } else {
+                       deactivate ();
+               }
+       } else {
+               if (!_pending_active) {
+                       activate ();
+               }
+               boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port));
+               ac->set_value (yn ? 1.0 : 0.0, Controllable::NoGroup);
+               ActiveChanged ();
+       }
+}
+
+bool
+PluginInsert::enabled () const
+{
+       if (_bypass_port == UINT32_MAX) {
+               return Processor::enabled ();
+       } else {
+               boost::shared_ptr<const AutomationControl> ac = boost::const_pointer_cast<AutomationControl> (automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port)));
+               return (ac->get_value () > 0 && _pending_active);
+       }
+}
+
+bool
+PluginInsert::bypassable () const
+{
+       if (_bypass_port == UINT32_MAX) {
+               return true;
+       } else {
+               boost::shared_ptr<const AutomationControl> ac = boost::const_pointer_cast<AutomationControl> (automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port)));
+
+               return !ac->automation_playback ();
+       }
+}
+
+void
+PluginInsert::enable_changed ()
+{
+       ActiveChanged ();
+}
+
+void
+PluginInsert::bypassable_changed ()
+{
+       BypassableChanged ();
+}
+
 void
 PluginInsert::inplace_silence_unconnected (BufferSet& bufs, const PinMappings& out_map, framecnt_t nframes, framecnt_t offset) const
 {
@@ -848,6 +923,11 @@ PluginInsert::connect_and_run (BufferSet& bufs, framepos_t start, framepos_t end
                                             &_signal_analysis_outputs);
                }
        }
+
+       if (_plugin_signal_latency != signal_latency ()) {
+               _plugin_signal_latency = signal_latency ();
+               latency_changed ();
+       }
 }
 
 void
@@ -1266,7 +1346,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) {
-                               if (i->second < ins) {
+                               if (i->first < ins) {
                                        rv.set (tm->first, i->first + pc * ins, i->second);
                                }
                        }
@@ -2633,6 +2713,9 @@ PluginInsert::describe_parameter (Evoral::Parameter param)
 ARDOUR::framecnt_t
 PluginInsert::signal_latency() const
 {
+       if (!_pending_active) {
+               return 0;
+       }
        if (_user_latency) {
                return _user_latency;
        }
@@ -2779,7 +2862,14 @@ PluginInsert::get_impulse_analysis_plugin()
                // 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();
@@ -2812,7 +2902,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->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 ();
@@ -2832,6 +2921,7 @@ PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
                vst->set_insert (this, _plugins.size ());
        }
 #endif
+
        _plugins.push_back (plugin);
 }
 
@@ -2872,10 +2962,13 @@ PluginInsert::monitoring_changed ()
 }
 
 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;
+       // XXX This also needs a proper API not an owner() hack.
+       assert (owner ());
+       static_cast<Route*>(owner ())->processor_latency_changed (); /* EMIT SIGNAL */
 }
 
 void