2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
26 #include "pbd/failed_constructor.h"
27 #include "pbd/xml++.h"
28 #include "pbd/types_convert.h"
30 #include "ardour/audio_buffer.h"
31 #include "ardour/automation_list.h"
32 #include "ardour/buffer_set.h"
33 #include "ardour/debug.h"
34 #include "ardour/event_type_map.h"
35 #include "ardour/ladspa_plugin.h"
36 #include "ardour/luaproc.h"
37 #include "ardour/plugin.h"
38 #include "ardour/plugin_insert.h"
39 #include "ardour/port.h"
42 #include "ardour/lv2_plugin.h"
45 #ifdef WINDOWS_VST_SUPPORT
46 #include "ardour/windows_vst_plugin.h"
50 #include "ardour/lxvst_plugin.h"
54 #include "ardour/mac_vst_plugin.h"
57 #ifdef AUDIOUNIT_SUPPORT
58 #include "ardour/audio_unit.h"
61 #include "ardour/session.h"
62 #include "ardour/types.h"
67 using namespace ARDOUR;
70 const string PluginInsert::port_automation_node_name = "PortAutomation";
72 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
73 : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
74 , _sc_playback_latency (0)
75 , _sc_capture_latency (0)
76 , _plugin_signal_latency (0)
77 , _signal_analysis_collect_nsamples (0)
78 , _signal_analysis_collect_nsamples_max (0)
83 , _maps_from_state (false)
84 , _latency_changed (false)
85 , _bypass_port (UINT32_MAX)
88 /* the first is the master */
92 create_automatable_parameters ();
93 const ChanCount& sc (sidechain_input_pins ());
94 if (sc.n_audio () > 0 || sc.n_midi () > 0) {
95 add_sidechain (sc.n_audio (), sc.n_midi ());
100 PluginInsert::~PluginInsert ()
102 for (CtrlOutMap::const_iterator i = _control_outputs.begin(); i != _control_outputs.end(); ++i) {
103 boost::dynamic_pointer_cast<ReadOnlyControl>(i->second)->drop_references ();
108 PluginInsert::set_strict_io (bool b)
110 bool changed = _strict_io != b;
113 PluginConfigChanged (); /* EMIT SIGNAL */
118 PluginInsert::set_count (uint32_t num)
120 bool require_state = !_plugins.empty();
122 if (require_state && num > 1 && plugin (0)->get_info ()->type == ARDOUR::AudioUnit) {
123 // we don't allow to replicate AUs
127 /* this is a bad idea.... we shouldn't do this while active.
128 * only a route holding their redirect_lock should be calling this
133 } else if (num > _plugins.size()) {
134 uint32_t diff = num - _plugins.size();
136 for (uint32_t n = 0; n < diff; ++n) {
137 boost::shared_ptr<Plugin> p = plugin_factory (_plugins[0]);
141 XMLNode& state = _plugins[0]->get_state ();
142 p->set_state (state, Stateful::loading_state_version);
149 PluginConfigChanged (); /* EMIT SIGNAL */
151 } else if (num < _plugins.size()) {
152 uint32_t diff = _plugins.size() - num;
153 for (uint32_t n= 0; n < diff; ++n) {
156 PluginConfigChanged (); /* EMIT SIGNAL */
164 PluginInsert::set_sinks (const ChanCount& c)
167 /* no signal, change will only be visible after re-config */
171 PluginInsert::set_outputs (const ChanCount& c)
173 bool changed = (_custom_out != c) && _custom_cfg;
176 PluginConfigChanged (); /* EMIT SIGNAL */
181 PluginInsert::set_custom_cfg (bool b)
183 bool changed = _custom_cfg != b;
186 PluginConfigChanged (); /* EMIT SIGNAL */
191 PluginInsert::set_preset_out (const ChanCount& c)
193 bool changed = _preset_out != c;
195 if (changed && !_custom_cfg) {
196 PluginConfigChanged (); /* EMIT SIGNAL */
202 PluginInsert::add_sidechain (uint32_t n_audio, uint32_t n_midi)
204 // caller must hold process lock
208 std::ostringstream n;
209 if (n_audio == 0 && n_midi == 0) {
210 n << "TO BE RESET FROM XML";
211 } else if (owner()) {
212 n << "SC " << owner()->name() << "/" << name() << " " << Session::next_name_id ();
216 SideChain *sc = new SideChain (_session, n.str ());
217 _sidechain = boost::shared_ptr<SideChain> (sc);
218 _sidechain->activate ();
219 for (uint32_t n = 0; n < n_audio; ++n) {
220 _sidechain->input()->add_port ("", owner(), DataType::AUDIO); // add a port, don't connect.
222 for (uint32_t n = 0; n < n_midi; ++n) {
223 _sidechain->input()->add_port ("", owner(), DataType::MIDI); // add a port, don't connect.
225 PluginConfigChanged (); /* EMIT SIGNAL */
230 PluginInsert::del_sidechain ()
236 _sc_playback_latency = 0;
237 _sc_capture_latency = 0;
238 PluginConfigChanged (); /* EMIT SIGNAL */
243 PluginInsert::update_sidechain_name ()
249 std::ostringstream n;
253 n << owner()->name() << "/";
256 n << name() << " " << Session::next_name_id ();
258 _sidechain->set_name (n.str());
262 PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, AutoState s)
264 if (which.type() != PluginAutomation)
267 boost::shared_ptr<AutomationControl> c
268 = boost::dynamic_pointer_cast<AutomationControl>(control (which));
271 _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_sample()));
276 PluginInsert::output_streams() const
278 assert (_configured);
279 return _configured_out;
283 PluginInsert::input_streams() const
285 assert (_configured);
286 return _configured_in;
290 PluginInsert::internal_streams() const
292 assert (_configured);
293 return _configured_internal;
297 PluginInsert::internal_output_streams() const
299 assert (!_plugins.empty());
301 PluginInfoPtr info = _plugins.front()->get_info();
303 if (info->reconfigurable_io()) {
304 ChanCount out = _plugins.front()->output_streams ();
305 // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out));
308 ChanCount out = info->n_outputs;
309 // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size()));
310 out.set_audio (out.n_audio() * _plugins.size());
311 out.set_midi (out.n_midi() * _plugins.size());
317 PluginInsert::internal_input_streams() const
319 assert (!_plugins.empty());
323 PluginInfoPtr info = _plugins.front()->get_info();
325 if (info->reconfigurable_io()) {
326 in = _plugins.front()->input_streams();
331 DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, input streams = %1, match using %2\n", in, _match.method));
333 if (_match.method == Split) {
335 /* we are splitting 1 processor input to multiple plugin inputs,
336 so we have a maximum of 1 stream of each type.
338 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
339 if (in.get (*t) > 1) {
345 } else if (_match.method == Hide) {
347 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
348 in.set (*t, in.get (*t) - _match.hide.get (*t));
354 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
355 in.set (*t, in.get (*t) * _plugins.size ());
363 PluginInsert::natural_output_streams() const
366 if (is_channelstrip ()) {
367 return ChanCount::min (_configured_out, ChanCount (DataType::AUDIO, 2));
370 return _plugins[0]->get_info()->n_outputs;
374 PluginInsert::natural_input_streams() const
377 if (is_channelstrip ()) {
378 return ChanCount::min (_configured_in, ChanCount (DataType::AUDIO, 2));
381 return _plugins[0]->get_info()->n_inputs;
385 PluginInsert::sidechain_input_pins() const
387 return _cached_sidechain_pins;
391 PluginInsert::has_no_inputs() const
393 return _plugins[0]->get_info()->n_inputs == ChanCount::ZERO;
397 PluginInsert::has_no_audio_inputs() const
399 return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
403 PluginInsert::plugin_latency () const {
404 return _plugins.front()->signal_latency ();
408 PluginInsert::is_instrument() const
410 PluginInfoPtr pip = _plugins[0]->get_info();
411 return (pip->is_instrument ());
415 PluginInsert::has_output_presets (ChanCount in, ChanCount out)
417 if (!_configured && _plugins[0]->get_info ()->reconfigurable_io ()) {
418 // collect possible configurations, prefer given in/out
419 _plugins[0]->can_support_io_configuration (in, out);
422 PluginOutputConfiguration ppc (_plugins[0]->possible_output ());
424 if (ppc.size () == 0) {
427 if (!strict_io () && ppc.size () == 1) {
431 if (strict_io () && ppc.size () == 1) {
432 // "stereo" is currently preferred default for instruments
433 if (ppc.find (2) != ppc.end ()) {
438 if (ppc.size () == 1 && ppc.find (0) != ppc.end () && !_plugins[0]->get_info ()->reconfigurable_io ()) {
439 // some midi-sequencer (e.g. QMidiArp) or other midi-out plugin
440 // pretending to be an "Instrument"
444 if (!is_instrument ()) {
451 PluginInsert::create_automatable_parameters ()
453 assert (!_plugins.empty());
455 boost::shared_ptr<Plugin> plugin = _plugins.front();
456 set<Evoral::Parameter> a = _plugins.front()->automatable ();
458 const uint32_t limit_automatables = Config->get_limit_n_automatables ();
460 for (uint32_t i = 0; i < plugin->parameter_count(); ++i) {
461 if (!plugin->parameter_is_control (i)) {
465 ParameterDescriptor desc;
466 plugin->get_parameter_descriptor(i, desc);
468 if (!plugin->parameter_is_input (i)) {
469 _control_outputs[i] = boost::shared_ptr<ReadOnlyControl> (new ReadOnlyControl (plugin, desc, i));
472 Evoral::Parameter param (PluginAutomation, 0, i);
474 const bool automatable = a.find(param) != a.end();
476 boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
477 boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
478 if (!automatable || (limit_automatables > 0 && i > limit_automatables)) {
479 c->set_flags (Controllable::Flag ((int)c->flags() | Controllable::NotAutomatable));
482 plugin->set_automation_control (i, c);
486 const Plugin::PropertyDescriptors& pdl (plugin->get_supported_properties ());
487 for (Plugin::PropertyDescriptors::const_iterator p = pdl.begin(); p != pdl.end(); ++p) {
488 Evoral::Parameter param (PluginPropertyAutomation, 0, p->first);
489 const ParameterDescriptor& desc = plugin->get_property_descriptor(param.id());
490 if (desc.datatype != Variant::NOTHING) {
491 boost::shared_ptr<AutomationList> list;
492 if (Variant::type_is_numeric(desc.datatype)) {
493 list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
495 boost::shared_ptr<AutomationControl> c (new PluginPropertyControl(this, param, desc, list));
496 if (!Variant::type_is_numeric(desc.datatype)) {
497 c->set_flags (Controllable::Flag ((int)c->flags() | Controllable::NotAutomatable));
503 _bypass_port = plugin->designated_bypass_port ();
505 /* special case VST effSetBypass */
506 if (_bypass_port == UINT32_MAX -1) {
507 // emulate VST Bypass
508 Evoral::Parameter param (PluginAutomation, 0, _bypass_port);
509 ParameterDescriptor desc;
510 desc.label = _("Plugin Enable");
515 boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
516 boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
520 if (_bypass_port != UINT32_MAX) {
521 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port));
522 if (0 == (ac->flags () & Controllable::NotAutomatable)) {
523 ac->alist()->automation_state_changed.connect_same_thread (*this, boost::bind (&PluginInsert::bypassable_changed, this));
524 ac->Changed.connect_same_thread (*this, boost::bind (&PluginInsert::enable_changed, this));
527 plugin->PresetPortSetValue.connect_same_thread (*this, boost::bind (&PluginInsert::preset_load_set_value, this, _1, _2));
530 /** Called when something outside of this host has modified a plugin
531 * parameter. Responsible for propagating the change to two places:
533 * 1) anything listening to the Control itself
534 * 2) any replicated plugins that make up this PluginInsert.
536 * The PluginInsert is connected to the ParameterChangedExternally signal for
537 * the first (primary) plugin, and here broadcasts that change to any others.
539 * XXX We should probably drop this whole replication idea (Paul, October 2015)
540 * since it isn't used by sensible plugin APIs (AU, LV2).
543 PluginInsert::parameter_changed_externally (uint32_t which, float val)
545 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, which));
547 /* First propagation: alter the underlying value of the control,
548 * without telling the plugin(s) that own/use it to set it.
555 boost::shared_ptr<PluginControl> pc = boost::dynamic_pointer_cast<PluginControl> (ac);
558 pc->catch_up_with_external_value (val);
561 /* Second propagation: tell all plugins except the first to
562 update the value of this parameter. For sane plugin APIs,
563 there are no other plugins, so this is a no-op in those
567 Plugins::iterator i = _plugins.begin();
569 /* don't set the first plugin, just all the slaves */
571 if (i != _plugins.end()) {
573 for (; i != _plugins.end(); ++i) {
574 (*i)->set_parameter (which, val);
577 boost::shared_ptr<Plugin> iasp = _impulseAnalysisPlugin.lock();
579 iasp->set_parameter (which, val);
584 PluginInsert::set_block_size (pframes_t nframes)
587 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
588 if ((*i)->set_block_size (nframes) != 0) {
596 PluginInsert::automation_run (samplepos_t start, pframes_t nframes, bool only_active)
598 // XXX does not work when rolling backwards
599 if (_loop_location && nframes > 0) {
600 const samplepos_t loop_start = _loop_location->start ();
601 const samplepos_t loop_end = _loop_location->end ();
602 const samplecnt_t looplen = loop_end - loop_start;
604 samplecnt_t remain = nframes;
605 samplepos_t start_pos = start;
608 if (start_pos >= loop_end) {
609 sampleoffset_t start_off = (start_pos - loop_start) % looplen;
610 start_pos = loop_start + start_off;
612 samplecnt_t move = std::min ((samplecnt_t)nframes, loop_end - start_pos);
614 Automatable::automation_run (start_pos, move, only_active);
620 Automatable::automation_run (start, nframes, only_active);
624 PluginInsert::find_next_event (double now, double end, Evoral::ControlEvent& next_event, bool only_active) const
626 bool rv = Automatable::find_next_event (now, end, next_event, only_active);
628 if (_loop_location && now < end) {
630 end = ceil (next_event.when);
632 const samplepos_t loop_end = _loop_location->end ();
633 assert (now < loop_end); // due to map_loop_range ()
634 if (end > loop_end) {
635 next_event.when = loop_end;
643 PluginInsert::activate ()
645 _timing_stats.reset ();
646 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
650 Processor::activate ();
651 /* when setting state e.g ProcessorBox::paste_processor_state ()
652 * the plugin is not yet owned by a route.
653 * but no matter. Route::add_processors() will call activate () again
659 const samplecnt_t l = effective_latency ();
660 if (_plugin_signal_latency != l) {
661 _plugin_signal_latency = l;
667 PluginInsert::deactivate ()
670 if (is_nonbypassable ()) {
674 _timing_stats.reset ();
675 Processor::deactivate ();
677 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
681 const samplecnt_t l = effective_latency ();
682 if (_plugin_signal_latency != l) {
683 _plugin_signal_latency = l;
689 PluginInsert::flush ()
691 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
697 PluginInsert::enable (bool yn)
699 if (_bypass_port == UINT32_MAX) {
706 if (!_pending_active) {
709 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port));
710 const double val = yn ? 1.0 : 0.0;
711 ac->set_value (val, Controllable::NoGroup);
713 #ifdef ALLOW_VST_BYPASS_TO_FAIL // yet unused, see also vst_plugin.cc
714 /* special case VST.. bypass may fail */
715 if (_bypass_port == UINT32_MAX - 1) {
716 /* check if bypass worked */
717 if (ac->get_value () != val) {
718 warning << _("PluginInsert: VST Bypass failed, falling back to host bypass.") << endmsg;
719 // set plugin to enabled (not-byassed)
720 ac->set_value (1.0, Controllable::NoGroup);
721 // ..and use host-provided hard-bypass
736 PluginInsert::enabled () const
738 if (_bypass_port == UINT32_MAX) {
739 return Processor::enabled ();
741 boost::shared_ptr<const AutomationControl> ac = boost::const_pointer_cast<AutomationControl> (automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port)));
742 return (ac->get_value () > 0 && _pending_active);
747 PluginInsert::bypassable () const
749 if (_bypass_port == UINT32_MAX) {
752 boost::shared_ptr<const AutomationControl> ac = boost::const_pointer_cast<AutomationControl> (automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port)));
754 return !ac->automation_playback ();
759 PluginInsert::enable_changed ()
765 PluginInsert::bypassable_changed ()
767 BypassableChanged ();
771 PluginInsert::write_immediate_event (size_t size, const uint8_t* buf)
774 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
775 if (!(*i)->write_immediate_event (size, buf)) {
783 PluginInsert::preset_load_set_value (uint32_t p, float v)
785 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, p));
790 if (ac->automation_state() & Play) {
795 ac->set_value (v, Controllable::NoGroup);
800 PluginInsert::inplace_silence_unconnected (BufferSet& bufs, const PinMappings& out_map, samplecnt_t nframes, samplecnt_t offset) const
802 // TODO optimize: store "unconnected" in a fixed set.
803 // it only changes on reconfiguration.
804 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
805 for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
807 if (*t == DataType::MIDI && out == 0 && has_midi_bypass ()) {
808 mapped = true; // in-place Midi bypass
810 for (uint32_t pc = 0; pc < get_count() && !mapped; ++pc) {
811 PinMappings::const_iterator i = out_map.find (pc);
812 if (i == out_map.end ()) {
815 const ChanMapping& outmap (i->second);
816 for (uint32_t o = 0; o < natural_output_streams().get (*t); ++o) {
818 uint32_t idx = outmap.get (*t, o, &valid);
819 if (valid && idx == out) {
826 bufs.get (*t, out).silence (nframes, offset);
833 PluginInsert::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes, samplecnt_t offset, bool with_auto)
835 if (_mapping_changed) { // ToDo use a counter, increment until match
836 _no_inplace = check_inplace ();
837 _mapping_changed = false;
839 // TODO: atomically copy maps & _no_inplace
840 PinMappings in_map (_in_map); // TODO Split case below overrides, use const& in_map
841 PinMappings const& out_map (_out_map);
842 ChanMapping const& thru_map (_thru_map);
844 if (_latency_changed) {
845 /* delaylines are configured with the max possible latency (as reported by the plugin)
846 * so this won't allocate memory (unless the plugin lied about its max latency)
847 * It may still 'click' though, since the fixed delaylines are not de-clicked.
848 * Then again plugin-latency changes are not click-free to begin with.
850 * This is also worst case, there is currently no concept of per-stream latency.
852 * e.g. Two identical latent plugins:
853 * 1st plugin: process left (latent), bypass right.
854 * 2nd plugin: bypass left, process right (latent).
855 * -> currently this yields 2 times latency of the plugin,
857 _latency_changed = false;
858 _delaybuffers.set (ChanCount::max(bufs.count(), _configured_out), plugin_latency ());
861 if (_match.method == Split && !_no_inplace) {
862 // TODO: also use this optimization if one source-buffer
863 // feeds _all_ *connected* inputs.
864 // currently this is *first* buffer to all only --
865 // see PluginInsert::check_inplace
866 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
867 if (_configured_internal.get (*t) == 0) {
871 uint32_t first_idx = in_map.p(0).get (*t, 0, &valid);
872 assert (valid && first_idx == 0); // check_inplace ensures this
873 /* copy the first stream's buffer contents to the others */
874 for (uint32_t i = 1; i < natural_input_streams ().get (*t); ++i) {
875 uint32_t idx = in_map.p(0).get (*t, i, &valid);
878 bufs.get (*t, i).read_from (bufs.get (*t, first_idx), nframes, offset, offset);
882 /* the copy operation produces a linear monotonic input map */
883 in_map[0] = ChanMapping (natural_input_streams ());
886 bufs.set_count(ChanCount::max(bufs.count(), _configured_internal));
887 bufs.set_count(ChanCount::max(bufs.count(), _configured_out));
890 boost::shared_ptr<ControlList> cl = _automated_controls.reader ();
891 for (ControlList::const_iterator ci = cl->begin(); ci != cl->end(); ++ci) {
892 AutomationControl& c = *(ci->get());
893 boost::shared_ptr<const Evoral::ControlList> clist (c.list());
894 /* we still need to check for Touch and Latch */
895 if (clist && (static_cast<AutomationList const&> (*clist)).automation_playback ()) {
897 const float val = c.list()->rt_safe_eval (start, valid);
899 c.set_value_unchecked(val);
905 if (_signal_analysis_collect_nsamples_max > 0) {
906 if (_signal_analysis_collect_nsamples < _signal_analysis_collect_nsamples_max) {
907 samplecnt_t ns = std::min ((samplecnt_t) nframes, _signal_analysis_collect_nsamples_max - _signal_analysis_collect_nsamples);
908 _signal_analysis_inputs.set_count (ChanCount (DataType::AUDIO, input_streams().n_audio()));
910 for (uint32_t i = 0; i < input_streams().n_audio(); ++i) {
911 _signal_analysis_inputs.get_audio(i).read_from (
914 _signal_analysis_collect_nsamples);
917 _signal_analysis_collect_nsamples += nframes;
921 if (is_channelstrip ()) {
922 if (_configured_in.n_audio() > 0) {
923 ChanMapping mb_in_map (ChanCount::min (_configured_in, ChanCount (DataType::AUDIO, 2)));
924 ChanMapping mb_out_map (ChanCount::min (_configured_out, ChanCount (DataType::AUDIO, 2)));
926 _plugins.front()->connect_and_run (bufs, start, end, speed, mb_in_map, mb_out_map, nframes, offset);
928 for (uint32_t out = _configured_in.n_audio (); out < bufs.count().get (DataType::AUDIO); ++out) {
929 bufs.get (DataType::AUDIO, out).silence (nframes, offset);
935 // TODO optimize -- build maps once.
937 BufferSet& inplace_bufs = _session.get_noinplace_buffers();
938 ARDOUR::ChanMapping used_outputs;
940 assert (inplace_bufs.count () >= natural_input_streams () + _configured_out);
942 /* build used-output map */
943 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
944 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
945 for (uint32_t out = 0; out < natural_output_streams().get (*t); ++out) {
947 uint32_t out_idx = out_map.p(pc).get (*t, out, &valid);
949 used_outputs.set (*t, out_idx, 1); // mark as used
954 /* copy thru data to outputs before processing in-place */
955 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
956 for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
958 uint32_t in_idx = thru_map.get (*t, out, &valid);
959 uint32_t m = out + natural_input_streams ().get (*t);
961 _delaybuffers.delay (*t, out, inplace_bufs.get (*t, m), bufs.get (*t, in_idx), nframes, offset, offset);
962 used_outputs.set (*t, out, 1); // mark as used
964 used_outputs.get (*t, out, &valid);
966 /* the plugin is expected to write here, but may not :(
967 * (e.g. drumgizmo w/o kit loaded)
969 inplace_bufs.get (*t, m).silence (nframes);
976 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
978 ARDOUR::ChanMapping i_in_map (natural_input_streams());
979 ARDOUR::ChanMapping i_out_map (out_map.p(pc));
980 ARDOUR::ChanCount mapped;
982 /* map inputs sequentially */
983 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
984 for (uint32_t in = 0; in < natural_input_streams().get (*t); ++in) {
986 uint32_t in_idx = in_map.p(pc).get (*t, in, &valid);
987 uint32_t m = mapped.get (*t);
989 inplace_bufs.get (*t, m).read_from (bufs.get (*t, in_idx), nframes, offset, offset);
991 inplace_bufs.get (*t, m).silence (nframes, offset);
993 mapped.set (*t, m + 1);
997 /* outputs are mapped to inplace_bufs after the inputs */
998 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
999 i_out_map.offset_to (*t, natural_input_streams ().get (*t));
1002 if ((*i)->connect_and_run (inplace_bufs, start, end, speed, i_in_map, i_out_map, nframes, offset)) {
1007 /* all instances have completed, now copy data that was written
1008 * and zero unconnected buffers */
1009 ARDOUR::ChanMapping nonzero_out (used_outputs);
1010 if (has_midi_bypass ()) {
1011 nonzero_out.set (DataType::MIDI, 0, 1); // Midi bypass.
1013 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1014 for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
1016 used_outputs.get (*t, out, &valid);
1018 nonzero_out.get (*t, out, &valid);
1020 bufs.get (*t, out).silence (nframes, offset);
1023 uint32_t m = out + natural_input_streams ().get (*t);
1024 bufs.get (*t, out).read_from (inplace_bufs.get (*t, m), nframes, offset, offset);
1029 /* in-place processing */
1031 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
1032 if ((*i)->connect_and_run(bufs, start, end, speed, in_map.p(pc), out_map.p(pc), nframes, offset)) {
1036 // now silence unconnected outputs
1037 inplace_silence_unconnected (bufs, _out_map, nframes, offset);
1040 const samplecnt_t l = effective_latency ();
1041 if (_plugin_signal_latency != l) {
1042 _plugin_signal_latency = l;
1043 _signal_analysis_collect_nsamples = 0;
1047 if (_signal_analysis_collect_nsamples > l) {
1048 assert (_signal_analysis_collect_nsamples_max > 0);
1049 assert (_signal_analysis_collect_nsamples >= nframes);
1050 samplecnt_t sample_pos = _signal_analysis_collect_nsamples - nframes;
1052 samplecnt_t dst_off = sample_pos >= l ? sample_pos - l : 0;
1053 samplecnt_t src_off = sample_pos >= l ? 0 : l - sample_pos;
1054 samplecnt_t n_copy = std::min ((samplecnt_t)nframes, _signal_analysis_collect_nsamples - l);
1055 n_copy = std::min (n_copy, _signal_analysis_collect_nsamples_max - dst_off);
1057 _signal_analysis_outputs.set_count (ChanCount (DataType::AUDIO, output_streams().n_audio()));
1059 for (uint32_t i = 0; i < output_streams().n_audio(); ++i) {
1060 _signal_analysis_outputs.get_audio(i).read_from(
1061 bufs.get_audio(i), n_copy, dst_off, src_off);
1064 if (dst_off + n_copy == _signal_analysis_collect_nsamples_max) {
1065 _signal_analysis_collect_nsamples_max = 0;
1066 _signal_analysis_collect_nsamples = 0;
1068 AnalysisDataGathered (&_signal_analysis_inputs, &_signal_analysis_outputs);
1074 PluginInsert::bypass (BufferSet& bufs, pframes_t nframes)
1076 /* bypass the plugin(s) not the whole processor.
1077 * -> use mappings just like connect_and_run
1079 if (_mapping_changed) {
1080 _no_inplace = check_inplace ();
1081 _mapping_changed = false;
1083 // TODO: atomically copy maps & _no_inplace
1084 ChanMapping const& in_map (no_sc_input_map ());
1085 ChanMapping const& out_map (output_map ());
1087 bufs.set_count(ChanCount::max(bufs.count(), _configured_internal));
1088 bufs.set_count(ChanCount::max(bufs.count(), _configured_out));
1091 ChanMapping thru_map (_thru_map);
1093 BufferSet& inplace_bufs = _session.get_noinplace_buffers();
1095 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1096 for (uint32_t in = 0; in < _configured_internal.get (*t); ++in) {
1097 inplace_bufs.get (*t, in).read_from (bufs.get (*t, in), nframes, 0, 0);
1100 ARDOUR::ChanMapping used_outputs;
1102 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1103 for (uint32_t out = 0; out < _configured_out.get (*t); ++out) {
1105 uint32_t in_idx = thru_map.get (*t, out, &valid);
1107 bufs.get (*t, out).read_from (inplace_bufs.get (*t, in_idx), nframes, 0, 0);
1108 used_outputs.set (*t, out, 1); // mark as used
1112 // plugin no-op: assume every plugin has an internal identity map
1113 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1114 for (uint32_t out = 0; out < _configured_out.get (*t); ++out) {
1116 uint32_t src_idx = out_map.get_src (*t, out, &valid);
1120 uint32_t in_idx = in_map.get (*t, src_idx, &valid);
1124 bufs.get (*t, out).read_from (inplace_bufs.get (*t, in_idx), nframes, 0, 0);
1125 used_outputs.set (*t, out, 1); // mark as used
1128 // now silence all unused outputs
1129 if (has_midi_bypass ()) {
1130 used_outputs.set (DataType::MIDI, 0, 1); // Midi bypass.
1132 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1133 for (uint32_t out = 0; out < _configured_out.get (*t); ++out) {
1135 used_outputs.get (*t, out, &valid);
1137 bufs.get (*t, out).silence (nframes, 0);
1142 if (_match.method == Split) {
1143 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1144 if (_configured_internal.get (*t) == 0) {
1147 // copy/feeds _all_ *connected* inputs, copy the first buffer
1149 uint32_t first_idx = in_map.get (*t, 0, &valid);
1150 assert (valid && first_idx == 0); // check_inplace ensures this
1151 for (uint32_t i = 1; i < natural_input_streams ().get (*t); ++i) {
1152 uint32_t idx = in_map.get (*t, i, &valid);
1155 bufs.get (*t, i).read_from (bufs.get (*t, first_idx), nframes, 0, 0);
1161 // apply output map and/or monotonic but not identity i/o mappings
1162 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1163 for (uint32_t out = 0; out < _configured_out.get (*t); ++out) {
1165 uint32_t src_idx = out_map.get_src (*t, out, &valid);
1167 bufs.get (*t, out).silence (nframes, 0);
1170 uint32_t in_idx = in_map.get (*t, src_idx, &valid);
1172 bufs.get (*t, out).silence (nframes, 0);
1175 if (in_idx != src_idx) {
1176 bufs.get (*t, out).read_from (bufs.get (*t, in_idx), nframes, 0, 0);
1184 PluginInsert::silence (samplecnt_t nframes, samplepos_t start_sample)
1186 automation_run (start_sample, nframes, true); // evaluate automation only
1189 // XXX delaybuffers need to be offset by nframes
1193 _delaybuffers.flush ();
1195 const ChanMapping in_map (natural_input_streams ());
1196 const ChanMapping out_map (natural_output_streams ());
1197 ChanCount maxbuf = ChanCount::max (natural_input_streams (), natural_output_streams());
1199 if (is_channelstrip ()) {
1200 if (_configured_in.n_audio() > 0) {
1201 _plugins.front()->connect_and_run (_session.get_scratch_buffers (maxbuf, true), start_sample, start_sample + nframes, 1.0, in_map, out_map, nframes, 0);
1205 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1206 (*i)->connect_and_run (_session.get_scratch_buffers (maxbuf, true), start_sample, start_sample + nframes, 1.0, in_map, out_map, nframes, 0);
1211 PluginInsert::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool)
1214 // collect sidechain input for complete cycle (!)
1215 // TODO we need delaylines here for latency compensation
1216 _sidechain->run (bufs, start_sample, end_sample, speed, nframes, true);
1219 if (g_atomic_int_compare_and_exchange (&_stat_reset, 1, 0)) {
1220 _timing_stats.reset ();
1223 if (_pending_active) {
1224 #if defined MIXBUS && defined NDEBUG
1225 if (!is_channelstrip ()) {
1226 _timing_stats.start ();
1229 _timing_stats.start ();
1231 /* run as normal if we are active or moving from inactive to active */
1233 if (_session.transport_rolling() || _session.bounce_processing()) {
1234 automate_and_run (bufs, start_sample, end_sample, speed, nframes);
1236 Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
1237 connect_and_run (bufs, start_sample, end_sample, speed, nframes, 0, lm.locked());
1239 #if defined MIXBUS && defined NDEBUG
1240 if (!is_channelstrip ()) {
1241 _timing_stats.update ();
1244 _timing_stats.update ();
1248 _timing_stats.reset ();
1249 // XXX should call ::silence() to run plugin(s) for consistent load.
1250 // We'll need to change this anyway when bypass can be automated
1251 bypass (bufs, nframes);
1252 automation_run (start_sample, nframes, true); // evaluate automation only
1253 _delaybuffers.flush ();
1256 _active = _pending_active;
1258 /* we have no idea whether the plugin generated silence or not, so mark
1259 * all buffers appropriately.
1264 PluginInsert::automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes)
1266 Evoral::ControlEvent next_event (0, 0.0f);
1267 samplecnt_t offset = 0;
1269 Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
1272 connect_and_run (bufs, start, end, speed, nframes, offset, false);
1276 /* map start back into loop-range, adjust end */
1277 map_loop_range (start, end);
1279 if (!find_next_event (start, end, next_event) || _plugins.front()->requires_fixed_sized_buffers()) {
1281 /* no events have a time within the relevant range */
1283 connect_and_run (bufs, start, end, speed, nframes, offset, true);
1289 samplecnt_t cnt = min (((samplecnt_t) ceil (next_event.when) - start), (samplecnt_t) nframes);
1291 connect_and_run (bufs, start, start + cnt, speed, cnt, offset, true); // XXX (start + cnt) * speed
1297 map_loop_range (start, end);
1299 if (!find_next_event (start, end, next_event)) {
1304 /* cleanup anything that is left to do */
1307 connect_and_run (bufs, start, start + nframes, speed, nframes, offset, true);
1312 PluginInsert::default_parameter_value (const Evoral::Parameter& param)
1314 if (param.type() != PluginAutomation)
1317 if (_plugins.empty()) {
1318 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
1320 abort(); /*NOTREACHED*/
1323 return _plugins[0]->default_value (param.id());
1328 PluginInsert::can_reset_all_parameters ()
1331 uint32_t params = 0;
1332 for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) {
1334 const uint32_t cid = _plugins[0]->nth_parameter (par, ok);
1336 if (!ok || !_plugins[0]->parameter_is_input(cid)) {
1340 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid));
1346 if (ac->automation_state() & Play) {
1351 return all && (params > 0);
1355 PluginInsert::reset_parameters_to_default ()
1359 for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) {
1361 const uint32_t cid = _plugins[0]->nth_parameter (par, ok);
1363 if (!ok || !_plugins[0]->parameter_is_input(cid)) {
1367 const float dflt = _plugins[0]->default_value (cid);
1368 const float curr = _plugins[0]->get_parameter (cid);
1374 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid));
1379 if (ac->automation_state() & Play) {
1384 ac->set_value (dflt, Controllable::NoGroup);
1389 boost::shared_ptr<Plugin>
1390 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
1392 boost::shared_ptr<LadspaPlugin> lp;
1393 boost::shared_ptr<LuaProc> lua;
1395 boost::shared_ptr<LV2Plugin> lv2p;
1397 #ifdef WINDOWS_VST_SUPPORT
1398 boost::shared_ptr<WindowsVSTPlugin> vp;
1400 #ifdef LXVST_SUPPORT
1401 boost::shared_ptr<LXVSTPlugin> lxvp;
1403 #ifdef MACVST_SUPPORT
1404 boost::shared_ptr<MacVSTPlugin> mvp;
1406 #ifdef AUDIOUNIT_SUPPORT
1407 boost::shared_ptr<AUPlugin> ap;
1410 if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
1411 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
1412 } else if ((lua = boost::dynamic_pointer_cast<LuaProc> (other)) != 0) {
1413 return boost::shared_ptr<Plugin> (new LuaProc (*lua));
1415 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
1416 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
1418 #ifdef WINDOWS_VST_SUPPORT
1419 } else if ((vp = boost::dynamic_pointer_cast<WindowsVSTPlugin> (other)) != 0) {
1420 return boost::shared_ptr<Plugin> (new WindowsVSTPlugin (*vp));
1422 #ifdef LXVST_SUPPORT
1423 } else if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (other)) != 0) {
1424 return boost::shared_ptr<Plugin> (new LXVSTPlugin (*lxvp));
1426 #ifdef MACVST_SUPPORT
1427 } else if ((mvp = boost::dynamic_pointer_cast<MacVSTPlugin> (other)) != 0) {
1428 return boost::shared_ptr<Plugin> (new MacVSTPlugin (*mvp));
1430 #ifdef AUDIOUNIT_SUPPORT
1431 } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
1432 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
1436 fatal << string_compose (_("programming error: %1"),
1437 X_("unknown plugin type in PluginInsert::plugin_factory"))
1439 abort(); /*NOTREACHED*/
1440 return boost::shared_ptr<Plugin> ((Plugin*) 0);
1444 PluginInsert::set_input_map (uint32_t num, ChanMapping m) {
1445 if (num < _in_map.size()) {
1446 bool changed = _in_map[num] != m;
1448 changed |= sanitize_maps ();
1450 PluginMapChanged (); /* EMIT SIGNAL */
1451 _mapping_changed = true;
1452 _session.set_dirty();
1458 PluginInsert::set_output_map (uint32_t num, ChanMapping m) {
1459 if (num < _out_map.size()) {
1460 bool changed = _out_map[num] != m;
1462 changed |= sanitize_maps ();
1464 PluginMapChanged (); /* EMIT SIGNAL */
1465 _mapping_changed = true;
1466 _session.set_dirty();
1472 PluginInsert::set_thru_map (ChanMapping m) {
1473 bool changed = _thru_map != m;
1475 changed |= sanitize_maps ();
1477 PluginMapChanged (); /* EMIT SIGNAL */
1478 _mapping_changed = true;
1479 _session.set_dirty();
1484 PluginInsert::pre_seed (const ChanCount& in, const ChanCount& out,
1485 const ChanMapping& im, const ChanMapping& om, const ChanMapping& tm)
1487 if (_configured) { return false; }
1488 _configured_in = in;
1489 _configured_out = out;
1493 _maps_from_state = in.n_total () > 0 && out.n_total () > 0;
1498 PluginInsert::input_map () const
1502 for (PinMappings::const_iterator i = _in_map.begin (); i != _in_map.end (); ++i, ++pc) {
1503 ChanMapping m (i->second);
1504 const ChanMapping::Mappings& mp ((*i).second.mappings());
1505 for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
1506 for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
1507 rv.set (tm->first, i->first + pc * natural_input_streams().get(tm->first), i->second);
1516 PluginInsert::no_sc_input_map () const
1520 for (PinMappings::const_iterator i = _in_map.begin (); i != _in_map.end (); ++i, ++pc) {
1521 ChanMapping m (i->second);
1522 const ChanMapping::Mappings& mp ((*i).second.mappings());
1523 for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
1524 uint32_t ins = natural_input_streams().get(tm->first) - _cached_sidechain_pins.get(tm->first);
1525 for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
1526 if (i->first < ins) {
1527 rv.set (tm->first, i->first + pc * ins, i->second);
1532 if (has_midi_thru ()) {
1533 rv.set (DataType::MIDI, 0, 0);
1539 PluginInsert::output_map () const
1543 for (PinMappings::const_iterator i = _out_map.begin (); i != _out_map.end (); ++i, ++pc) {
1544 ChanMapping m (i->second);
1545 const ChanMapping::Mappings& mp ((*i).second.mappings());
1546 for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
1547 for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
1548 rv.set (tm->first, i->first + pc * natural_output_streams().get(tm->first), i->second);
1552 if (has_midi_bypass ()) {
1553 rv.set (DataType::MIDI, 0, 0);
1560 PluginInsert::has_midi_bypass () const
1562 if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1
1563 && natural_output_streams ().n_midi () == 0) {
1570 PluginInsert::has_midi_thru () const
1572 if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1
1573 && natural_input_streams ().n_midi () == 0 && natural_output_streams ().n_midi () == 0) {
1580 PluginInsert::is_channelstrip () const
1583 return _plugins.front()->is_channelstrip();
1590 PluginInsert::is_nonbypassable () const
1593 return _plugins.front()->is_nonbypassable ();
1600 PluginInsert::show_on_ctrl_surface () const
1602 if (is_channelstrip () || !is_nonbypassable ()) {
1609 PluginInsert::check_inplace ()
1611 bool inplace_ok = !_plugins.front()->inplace_broken ();
1613 if (_thru_map.n_total () > 0) {
1614 // TODO once midi-bypass is part of the mapping, ignore it
1618 if (_match.method == Split && inplace_ok) {
1619 assert (get_count() == 1);
1620 assert (_in_map.size () == 1);
1621 if (!_out_map[0].is_monotonic ()) {
1624 if (_configured_internal != _configured_in) {
1625 /* no sidechain -- TODO we could allow this with
1626 * some more logic in PluginInsert::connect_and_run().
1628 * PluginInsert::reset_map() already maps it.
1633 for (DataType::iterator t = DataType::begin(); t != DataType::end() && inplace_ok; ++t) {
1634 if (_configured_internal.get (*t) == 0) {
1638 uint32_t first_idx = _in_map[0].get (*t, 0, &valid);
1639 if (!valid || first_idx != 0) {
1640 // so far only allow to copy the *first* stream's buffer to others
1643 for (uint32_t i = 1; i < natural_input_streams ().get (*t); ++i) {
1644 uint32_t idx = _in_map[0].get (*t, i, &valid);
1645 if (valid && idx != first_idx) {
1654 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: In Place Split Map\n", name()));
1659 for (uint32_t pc = 0; pc < get_count() && inplace_ok ; ++pc) {
1660 if (!_in_map[pc].is_monotonic ()) {
1663 if (!_out_map[pc].is_monotonic ()) {
1669 /* check if every output is fed by the corresponding input
1671 * this prevents in-port 1 -> sink-pin 2 || source-pin 1 -> out port 1, source-pin 2 -> out port 2
1672 * (with in-place, source-pin 1 -> out port 1 overwrites in-port 1)
1674 * but allows in-port 1 -> sink-pin 2 || source-pin 2 -> out port 1
1676 ChanMapping const& in_map (input_map ());
1677 const ChanMapping::Mappings out_m (output_map ().mappings ());
1678 for (ChanMapping::Mappings::const_iterator t = out_m.begin (); t != out_m.end () && inplace_ok; ++t) {
1679 for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
1680 /* src-pin: c->first, out-port: c->second */
1682 uint32_t in_port = in_map.get (t->first, c->first, &valid);
1683 if (valid && in_port != c->second) {
1691 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: %2\n", name(), inplace_ok ? "In-Place" : "No Inplace Processing"));
1692 return !inplace_ok; // no-inplace
1696 PluginInsert::sanitize_maps ()
1698 bool changed = false;
1699 /* strip dead wood */
1700 PinMappings new_ins;
1701 PinMappings new_outs;
1702 ChanMapping new_thru;
1704 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1706 ChanMapping new_out;
1707 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1708 for (uint32_t i = 0; i < natural_input_streams().get (*t); ++i) {
1710 uint32_t idx = _in_map[pc].get (*t, i, &valid);
1711 if (valid && idx < _configured_internal.get (*t)) {
1712 new_in.set (*t, i, idx);
1715 for (uint32_t o = 0; o < natural_output_streams().get (*t); ++o) {
1717 uint32_t idx = _out_map[pc].get (*t, o, &valid);
1718 if (valid && idx < _configured_out.get (*t)) {
1719 new_out.set (*t, o, idx);
1723 if (_in_map[pc] != new_in || _out_map[pc] != new_out) {
1726 new_ins[pc] = new_in;
1727 new_outs[pc] = new_out;
1730 /* prevent dup output assignments */
1731 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1732 for (uint32_t o = 0; o < _configured_out.get (*t); ++o) {
1733 bool mapped = false;
1734 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1736 uint32_t idx = new_outs[pc].get_src (*t, o, &valid);
1737 if (valid && mapped) {
1738 new_outs[pc].unset (*t, idx);
1746 /* remove excess thru */
1747 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1748 for (uint32_t o = 0; o < _configured_out.get (*t); ++o) {
1750 uint32_t idx = _thru_map.get (*t, o, &valid);
1751 if (valid && idx < _configured_internal.get (*t)) {
1752 new_thru.set (*t, o, idx);
1757 /* prevent out + thru, existing plugin outputs override thru */
1758 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1759 for (uint32_t o = 0; o < _configured_out.get (*t); ++o) {
1760 bool mapped = false;
1762 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1763 new_outs[pc].get_src (*t, o, &mapped);
1764 if (mapped) { break; }
1766 if (!mapped) { continue; }
1767 uint32_t idx = new_thru.get (*t, o, &valid);
1769 new_thru.unset (*t, idx);
1774 if (has_midi_bypass ()) {
1775 // TODO: include midi-bypass in the thru set,
1776 // remove dedicated handling.
1777 new_thru.unset (DataType::MIDI, 0);
1780 if (_in_map != new_ins || _out_map != new_outs || _thru_map != new_thru) {
1784 _out_map = new_outs;
1785 _thru_map = new_thru;
1791 PluginInsert::reset_map (bool emit)
1793 const PinMappings old_in (_in_map);
1794 const PinMappings old_out (_out_map);
1798 _thru_map = ChanMapping ();
1800 /* build input map */
1801 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1802 uint32_t sc = 0; // side-chain round-robin (all instances)
1804 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
1805 const uint32_t nis = natural_input_streams ().get(*t);
1806 const uint32_t stride = nis - sidechain_input_pins().get (*t);
1808 /* SC inputs are last in the plugin-insert.. */
1809 const uint32_t sc_start = _configured_in.get (*t);
1810 const uint32_t sc_len = _configured_internal.get (*t) - sc_start;
1811 /* ...but may not be at the end of the plugin ports.
1812 * in case the side-chain is not the last port, shift connections back.
1813 * and connect to side-chain
1816 uint32_t ic = 0; // split inputs
1817 const uint32_t cend = _configured_in.get (*t);
1819 for (uint32_t in = 0; in < nis; ++in) {
1820 const Plugin::IOPortDescription& iod (_plugins[pc]->describe_io_port (*t, true, in));
1821 if (iod.is_sidechain) {
1822 /* connect sidechain sinks to sidechain inputs in round-robin fashion */
1823 if (sc_len > 0) {// side-chain may be hidden
1824 _in_map[pc].set (*t, in, sc_start + sc);
1825 sc = (sc + 1) % sc_len;
1829 if (_match.method == Split) {
1830 if (cend == 0) { continue; }
1831 if (_strict_io && ic + stride * pc >= cend) {
1834 /* connect *no* sidechain sinks in round-robin fashion */
1835 _in_map[pc].set (*t, in, ic + stride * pc);
1836 if (_strict_io && (ic + 1) == cend) {
1839 ic = (ic + 1) % cend;
1841 uint32_t s = in - shift;
1842 if (stride * pc + s < cend) {
1843 _in_map[pc].set (*t, in, s + stride * pc);
1851 /* build output map */
1853 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
1854 _out_map[pc] = ChanMapping (ChanCount::min (natural_output_streams(), _configured_out));
1855 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1856 _out_map[pc].offset_to(*t, pc * natural_output_streams().get(*t));
1861 if (old_in == _in_map && old_out == _out_map) {
1865 PluginMapChanged (); /* EMIT SIGNAL */
1866 _mapping_changed = true;
1867 _session.set_dirty();
1873 PluginInsert::configure_io (ChanCount in, ChanCount out)
1875 Match old_match = _match;
1877 ChanCount old_internal;
1881 old_pins = natural_input_streams();
1882 old_in = _configured_in;
1883 old_out = _configured_out;
1884 old_internal = _configured_internal;
1886 _configured_in = in;
1887 _configured_internal = in;
1888 _configured_out = out;
1891 /* TODO hide midi-bypass, and custom outs. Best /fake/ "out" here.
1892 * (currently _sidechain->configure_io always succeeds
1893 * since Processor::configure_io() succeeds)
1895 if (!_sidechain->configure_io (in, out)) {
1896 DEBUG_TRACE (DEBUG::ChanMapping, "Sidechain configuration failed\n");
1899 _configured_internal += _sidechain->input()->n_ports();
1901 // include (static_cast<Route*>owner())->name() ??
1902 _sidechain->input ()-> set_pretty_name (string_compose (_("SC %1"), name ()));
1905 /* get plugin configuration */
1906 _match = private_can_support_io_configuration (in, out);
1908 if (DEBUG_ENABLED(DEBUG::ChanMapping)) {
1910 DEBUG_STR_APPEND(a, string_compose ("%1: ", name()));
1911 DEBUG_STR_APPEND(a, _match);
1912 DEBUG_TRACE (DEBUG::ChanMapping, DEBUG_STR(a).str());
1916 /* set the matching method and number of plugins that we will use to meet this configuration */
1917 if (set_count (_match.plugins) == false) {
1918 PluginIoReConfigure (); /* EMIT SIGNAL */
1919 _configured = false;
1923 /* configure plugins */
1924 switch (_match.method) {
1927 if (_plugins.front()->configure_io (natural_input_streams(), out) == false) {
1928 PluginIoReConfigure (); /* EMIT SIGNAL */
1929 _configured = false;
1935 ChanCount din (_configured_internal);
1936 ChanCount dout (din); // hint
1938 if (_custom_sinks.n_total () > 0) {
1939 din = _custom_sinks;
1942 } else if (_preset_out.n_audio () > 0) {
1943 dout.set (DataType::AUDIO, _preset_out.n_audio ());
1944 } else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
1945 dout.set (DataType::AUDIO, 2);
1947 if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
1949 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: Delegate lookup : %2 %3\n", name(), din, dout));
1950 bool const r = _plugins.front()->can_support_io_configuration (din, dout, &useins);
1952 if (useins.n_audio() == 0) {
1955 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: Delegate configuration: %2 %3\n", name(), useins, dout));
1957 if (_plugins.front()->configure_io (useins, dout) == false) {
1958 PluginIoReConfigure (); /* EMIT SIGNAL */
1959 _configured = false;
1963 _custom_sinks = din;
1968 if (_plugins.front()->configure_io (in, out) == false) {
1969 PluginIoReConfigure (); /* EMIT SIGNAL */
1970 _configured = false;
1976 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: cfg:%2 state:%3 chn-in:%4 chn-out:%5 inpin:%6 match:%7 cust:%8 size-in:%9 size-out:%10\n",
1978 _configured ? "Y" : "N",
1979 _maps_from_state ? "Y" : "N",
1980 old_in == in ? "==" : "!=",
1981 old_out == out ? "==" : "!=",
1982 old_pins == natural_input_streams () ? "==" : "!=",
1983 old_match.method == _match.method ? "==" : "!=",
1984 old_match.custom_cfg == _match.custom_cfg ? "==" : "!=",
1985 _in_map.size() == get_count () ? "==" : "!=",
1986 _out_map.size() == get_count () ? "==" : "!="
1989 bool mapping_changed = false;
1990 if (old_in == in && old_out == out
1992 && old_pins == natural_input_streams ()
1993 && old_match.method == _match.method
1994 && old_match.custom_cfg == _match.custom_cfg
1995 && _in_map.size() == _out_map.size()
1996 && _in_map.size() == get_count ()
1998 /* If the configuration has not changed, keep the mapping */
1999 mapping_changed = sanitize_maps ();
2000 } else if (_match.custom_cfg && _configured) {
2001 /* don't touch the map in manual mode */
2002 mapping_changed = sanitize_maps ();
2005 if (is_channelstrip ()) {
2006 /* fake channel map - for wire display */
2009 _thru_map = ChanMapping ();
2010 _in_map[0] = ChanMapping (ChanCount::min (_configured_in, ChanCount (DataType::AUDIO, 2)));
2011 _out_map[0] = ChanMapping (ChanCount::min (_configured_out, ChanCount (DataType::AUDIO, 2)));
2012 /* set "thru" map for in-place forward of audio */
2013 for (uint32_t i = 2; i < _configured_in.n_audio(); ++i) {
2014 _thru_map.set (DataType::AUDIO, i, i);
2016 /* and midi (after implicit 1st channel bypass) */
2017 for (uint32_t i = 1; i < _configured_in.n_midi(); ++i) {
2018 _thru_map.set (DataType::MIDI, i, i);
2022 if (_maps_from_state && old_in == in && old_out == out) {
2023 mapping_changed = true;
2026 /* generate a new mapping */
2027 mapping_changed = reset_map (false);
2029 _maps_from_state = false;
2032 if (mapping_changed) {
2033 PluginMapChanged (); /* EMIT SIGNAL */
2036 if (DEBUG_ENABLED(DEBUG::ChanMapping)) {
2039 DEBUG_STR_APPEND(a, "\n--------<<--------\n");
2040 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
2042 DEBUG_STR_APPEND(a, "----><----\n");
2044 DEBUG_STR_APPEND(a, string_compose ("Channel Map for %1 plugin %2\n", name(), pc));
2045 DEBUG_STR_APPEND(a, " * Inputs:\n");
2046 DEBUG_STR_APPEND(a, _in_map[pc]);
2047 DEBUG_STR_APPEND(a, " * Outputs:\n");
2048 DEBUG_STR_APPEND(a, _out_map[pc]);
2050 DEBUG_STR_APPEND(a, " * Thru:\n");
2051 DEBUG_STR_APPEND(a, _thru_map);
2052 DEBUG_STR_APPEND(a, "-------->>--------\n");
2053 DEBUG_TRACE (DEBUG::ChanMapping, DEBUG_STR(a).str());
2058 _no_inplace = check_inplace ();
2059 _mapping_changed = false;
2061 /* only the "noinplace_buffers" thread buffers need to be this large,
2062 * this can be optimized. other buffers are fine with
2063 * ChanCount::max (natural_input_streams (), natural_output_streams())
2064 * and route.cc's max (configured_in, configured_out)
2066 * no-inplace copies "thru" outputs (to emulate in-place) for
2067 * all outputs (to prevent overwrite) into a temporary space
2068 * which also holds input buffers (in case the plugin does process
2069 * in-place and overwrites those).
2071 * this buffers need to be at least as
2072 * natural_input_streams () + possible outputs.
2074 * sidechain inputs add a constraint on the input:
2075 * configured input + sidechain (=_configured_internal)
2077 * NB. this also satisfies
2078 * max (natural_input_streams(), natural_output_streams())
2079 * which is needed for silence runs
2081 _required_buffers = ChanCount::max (_configured_internal,
2082 natural_input_streams () + ChanCount::max (_configured_out, natural_output_streams () * get_count ()));
2084 if (old_in != in || old_out != out || old_internal != _configured_internal
2085 || old_pins != natural_input_streams ()
2086 || (old_match.method != _match.method && (old_match.method == Split || _match.method == Split))
2088 PluginIoReConfigure (); /* EMIT SIGNAL */
2091 _delaybuffers.configure (_configured_out, _plugins.front ()->max_latency ());
2092 _latency_changed = true;
2094 /* we don't know the analysis window size, so we must work with the
2095 * current buffer size here. each request for data fills in these
2096 * buffers and the analyser makes sure it gets enough data for the
2097 * analysis window. We also only analyze audio, so we can ignore
2100 ChanCount cc_analysis_in (DataType::AUDIO, in.n_audio());
2101 ChanCount cc_analysis_out (DataType::AUDIO, out.n_audio());
2103 session().ensure_buffer_set (_signal_analysis_inputs, cc_analysis_in);
2104 _signal_analysis_inputs.set_count (cc_analysis_in);
2106 session().ensure_buffer_set (_signal_analysis_outputs, cc_analysis_out);
2107 _signal_analysis_outputs.set_count (cc_analysis_out);
2109 // std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
2112 return Processor::configure_io (in, out);
2115 /** Decide whether this PluginInsert can support a given IO configuration.
2116 * To do this, we run through a set of possible solutions in rough order of
2119 * @param in Required input channel count.
2120 * @param out Filled in with the output channel count if we return true.
2121 * @return true if the given IO configuration can be supported.
2124 PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
2127 _sidechain->can_support_io_configuration (in, out); // never fails, sets "out"
2129 return private_can_support_io_configuration (in, out).method != Impossible;
2133 PluginInsert::private_can_support_io_configuration (ChanCount const& in, ChanCount& out) const
2135 if (!_custom_cfg && _preset_out.n_audio () > 0) {
2136 // preseed hint (for variable i/o)
2137 out.set (DataType::AUDIO, _preset_out.n_audio ());
2140 Match rv = internal_can_support_io_configuration (in, out);
2142 if (!_custom_cfg && _preset_out.n_audio () > 0) {
2143 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: using output preset: %2\n", name(), _preset_out));
2144 out.set (DataType::AUDIO, _preset_out.n_audio ());
2149 /** A private version of can_support_io_configuration which returns the method
2150 * by which the configuration can be matched, rather than just whether or not
2154 PluginInsert::internal_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
2156 if (_plugins.empty()) {
2161 if (is_channelstrip ()) {
2163 return Match (ExactMatch, 1);
2167 /* if a user specified a custom cfg, so be it. */
2169 PluginInfoPtr info = _plugins.front()->get_info();
2171 if (info->reconfigurable_io()) {
2172 return Match (Delegate, 1, _strict_io, true);
2174 return Match (ExactMatch, get_count(), _strict_io, true);
2178 /* try automatic configuration */
2179 Match m = PluginInsert::automatic_can_support_io_configuration (inx, out);
2181 PluginInfoPtr info = _plugins.front()->get_info();
2182 ChanCount inputs = info->n_inputs;
2183 ChanCount outputs = info->n_outputs;
2185 /* handle case strict-i/o */
2186 if (_strict_io && m.method != Impossible) {
2189 /* special case MIDI instruments */
2190 if (is_instrument ()) {
2191 // output = midi-bypass + at most master-out channels.
2192 ChanCount max_out (DataType::AUDIO, 2); // TODO use master-out
2193 max_out.set (DataType::MIDI, out.get(DataType::MIDI));
2194 out = ChanCount::min (out, max_out);
2195 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: special case strict-i/o instrument\n", name()));
2201 if (inx.n_audio () != out.n_audio ()) { // ignore midi bypass
2202 /* replicate processor to match output count (generators and such)
2203 * at least enough to feed every output port. */
2204 uint32_t f = 1; // at least one. e.g. control data filters, no in, no out.
2205 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2206 uint32_t nout = outputs.get (*t);
2207 if (nout == 0 || inx.get(*t) == 0) { continue; }
2208 f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nout));
2211 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: special case strict-i/o for generator\n", name()));
2212 return Match (Replicate, f, _strict_io);
2223 if (m.method != Impossible) {
2227 ChanCount ns_inputs = inputs - sidechain_input_pins ();
2229 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: resolving 'Impossible' match...\n", name()));
2231 if (info->reconfigurable_io()) {
2234 if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
2235 if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
2236 bool const r = _plugins.front()->can_support_io_configuration (inx + sidechain_input_pins (), out, &useins);
2238 // houston, we have a problem.
2239 return Match (Impossible, 0);
2242 if (inx.n_midi () > 0 && out.n_midi () == 0) { out.set (DataType::MIDI, 1); }
2243 return Match (Delegate, 1, _strict_io);
2246 ChanCount midi_bypass;
2247 if (inx.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
2248 midi_bypass.set (DataType::MIDI, 1);
2251 // add at least as many plugins so that output count matches input count (w/o sidechain pins)
2253 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2254 uint32_t nin = ns_inputs.get (*t);
2255 uint32_t nout = outputs.get (*t);
2256 if (nin == 0 || inx.get(*t) == 0) { continue; }
2257 // prefer floor() so the count won't overly increase IFF (nin < nout)
2258 f = max (f, (uint32_t) floor (inx.get(*t) / (float)nout));
2260 if (f > 0 && outputs * f >= _configured_out) {
2261 out = outputs * f + midi_bypass;
2262 return Match (Replicate, f, _strict_io);
2265 // add at least as many plugins needed to connect all inputs (w/o sidechain pins)
2267 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2268 uint32_t nin = ns_inputs.get (*t);
2269 if (nin == 0 || inx.get(*t) == 0) { continue; }
2270 f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin));
2273 out = outputs * f + midi_bypass;
2274 return Match (Replicate, f, _strict_io);
2277 // add at least as many plugins needed to connect all inputs
2279 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2280 uint32_t nin = inputs.get (*t);
2281 if (nin == 0 || inx.get(*t) == 0) { continue; }
2282 f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin));
2284 out = outputs * f + midi_bypass;
2285 return Match (Replicate, f, _strict_io);
2288 /* this is the original Ardour 3/4 behavior, mainly for backwards compatibility */
2290 PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
2292 if (_plugins.empty()) {
2296 PluginInfoPtr info = _plugins.front()->get_info();
2297 ChanCount in; in += inx;
2298 ChanCount midi_bypass;
2300 if (info->reconfigurable_io()) {
2301 /* Plugin has flexible I/O, so delegate to it
2302 * pre-seed outputs, plugin tries closest match
2305 if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
2306 if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
2307 bool const r = _plugins.front()->can_support_io_configuration (in + sidechain_input_pins (), out);
2309 return Match (Impossible, 0);
2312 if (in.n_midi () > 0 && out.n_midi () == 0) { out.set (DataType::MIDI, 1); }
2313 return Match (Delegate, 1);
2316 ChanCount inputs = info->n_inputs;
2317 ChanCount outputs = info->n_outputs;
2318 ChanCount ns_inputs = inputs - sidechain_input_pins ();
2320 if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
2321 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: bypassing midi-data\n", name()));
2322 midi_bypass.set (DataType::MIDI, 1);
2324 if (in.get(DataType::MIDI) == 1 && inputs.get(DataType::MIDI) == 0) {
2325 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: hiding midi-port from plugin\n", name()));
2326 in.set(DataType::MIDI, 0);
2329 // add internally provided sidechain ports
2330 ChanCount insc = in + sidechain_input_ports ();
2332 bool no_inputs = true;
2333 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2334 if (inputs.get (*t) != 0) {
2341 /* no inputs so we can take any input configuration since we throw it away */
2342 out = outputs + midi_bypass;
2343 return Match (NoInputs, 1);
2346 /* Plugin inputs match requested inputs + side-chain-ports exactly */
2347 if (inputs == insc) {
2348 out = outputs + midi_bypass;
2349 return Match (ExactMatch, 1);
2352 /* Plugin inputs matches without side-chain-pins */
2353 if (ns_inputs == in) {
2354 out = outputs + midi_bypass;
2355 return Match (ExactMatch, 1);
2358 /* We may be able to run more than one copy of the plugin within this insert
2359 to cope with the insert having more inputs than the plugin.
2360 We allow replication only for plugins with either zero or 1 inputs and outputs
2361 for every valid data type.
2365 bool can_replicate = true;
2366 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2368 // ignore side-chains
2369 uint32_t nin = ns_inputs.get (*t);
2371 // No inputs of this type
2372 if (nin == 0 && in.get(*t) == 0) {
2376 if (nin != 1 || outputs.get (*t) != 1) {
2377 can_replicate = false;
2381 // Potential factor not set yet
2383 f = in.get(*t) / nin;
2386 // Factor for this type does not match another type, can not replicate
2387 if (f != (in.get(*t) / nin)) {
2388 can_replicate = false;
2393 if (can_replicate && f > 0) {
2394 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2395 out.set (*t, outputs.get(*t) * f);
2398 return Match (Replicate, f);
2401 /* If the processor has exactly one input of a given type, and
2402 the plugin has more, we can feed the single processor input
2403 to some or all of the plugin inputs. This is rather
2404 special-case-y, but the 1-to-many case is by far the
2405 simplest. How do I split thy 2 processor inputs to 3
2406 plugin inputs? Let me count the ways ...
2409 bool can_split = true;
2410 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2412 bool const can_split_type = (in.get (*t) == 1 && ns_inputs.get (*t) > 1);
2413 bool const nothing_to_do_for_type = (in.get (*t) == 0 && inputs.get (*t) == 0);
2415 if (!can_split_type && !nothing_to_do_for_type) {
2421 out = outputs + midi_bypass;
2422 return Match (Split, 1);
2425 /* If the plugin has more inputs than we want, we can `hide' some of them
2426 by feeding them silence.
2429 bool could_hide = false;
2430 bool cannot_hide = false;
2431 ChanCount hide_channels;
2433 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2434 if (inputs.get(*t) > in.get(*t)) {
2435 /* there is potential to hide, since the plugin has more inputs of type t than the insert */
2436 hide_channels.set (*t, inputs.get(*t) - in.get(*t));
2438 } else if (inputs.get(*t) < in.get(*t)) {
2439 /* we definitely cannot hide, since the plugin has fewer inputs of type t than the insert */
2444 if (could_hide && !cannot_hide) {
2445 out = outputs + midi_bypass;
2446 return Match (Hide, 1, false, false, hide_channels);
2449 return Match (Impossible, 0);
2454 PluginInsert::state ()
2456 XMLNode& node = Processor::state ();
2458 node.set_property("type", _plugins[0]->state_node_name());
2459 node.set_property("unique-id", _plugins[0]->unique_id());
2460 node.set_property("count", (uint32_t)_plugins.size());
2462 /* remember actual i/o configuration (for later placeholder
2463 * in case the plugin goes missing) */
2464 node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
2465 node.add_child_nocopy (* _custom_sinks.state (X_("CustomSinks")));
2466 node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
2467 node.add_child_nocopy (* _preset_out.state (X_("PresetOutput")));
2469 /* save custom i/o config */
2470 node.set_property("custom", _custom_cfg);
2471 for (uint32_t pc = 0; pc < get_count(); ++pc) {
2473 snprintf (tmp, sizeof(tmp), "InputMap-%d", pc);
2474 node.add_child_nocopy (* _in_map[pc].state (tmp));
2475 snprintf (tmp, sizeof(tmp), "OutputMap-%d", pc);
2476 node.add_child_nocopy (* _out_map[pc].state (tmp));
2478 node.add_child_nocopy (* _thru_map.state ("ThruMap"));
2481 node.add_child_nocopy (_sidechain->get_state ());
2484 _plugins[0]->set_insert_id(this->id());
2485 node.add_child_nocopy (_plugins[0]->get_state());
2487 for (Controls::iterator c = controls().begin(); c != controls().end(); ++c) {
2488 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> ((*c).second);
2490 node.add_child_nocopy (ac->get_state());
2498 PluginInsert::set_control_ids (const XMLNode& node, int version)
2500 const XMLNodeList& nlist = node.children();
2501 for (XMLNodeConstIterator iter = nlist.begin(); iter != nlist.end(); ++iter) {
2502 if ((*iter)->name() != Controllable::xml_node_name) {
2506 uint32_t p = (uint32_t)-1;
2509 if ((*iter)->get_property (X_("symbol"), str)) {
2510 boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugins[0]);
2512 p = lv2plugin->port_index(str.c_str());
2516 if (p == (uint32_t)-1) {
2517 (*iter)->get_property (X_("parameter"), p);
2520 if (p == (uint32_t)-1) {
2524 /* this may create the new controllable */
2525 boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p));
2527 #ifndef NO_PLUGIN_STATE
2531 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
2533 ac->set_state (**iter, version);
2540 PluginInsert::update_control_values (const XMLNode& node, int version)
2542 const XMLNodeList& nlist = node.children();
2543 for (XMLNodeConstIterator iter = nlist.begin(); iter != nlist.end(); ++iter) {
2544 if ((*iter)->name() != Controllable::xml_node_name) {
2549 if (!(*iter)->get_property (X_("value"), val)) {
2553 uint32_t p = (uint32_t)-1;
2556 if ((*iter)->get_property (X_("symbol"), str)) {
2557 boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugins[0]);
2559 p = lv2plugin->port_index(str.c_str());
2563 if (p == (uint32_t)-1) {
2564 (*iter)->get_property (X_("parameter"), p);
2567 if (p == (uint32_t)-1) {
2571 /* lookup controllable */
2572 boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p), false);
2576 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
2578 ac->set_value (val, Controllable::NoGroup);
2584 PluginInsert::set_state(const XMLNode& node, int version)
2586 XMLNodeList nlist = node.children();
2587 XMLNodeIterator niter;
2588 XMLPropertyList plist;
2589 ARDOUR::PluginType type;
2592 if (!node.get_property ("type", str)) {
2593 error << _("XML node describing plugin is missing the `type' field") << endmsg;
2597 if (str == X_("ladspa") || str == X_("Ladspa")) { /* handle old school sessions */
2598 type = ARDOUR::LADSPA;
2599 } else if (str == X_("lv2")) {
2601 } else if (str == X_("windows-vst")) {
2602 type = ARDOUR::Windows_VST;
2603 } else if (str == X_("lxvst")) {
2604 type = ARDOUR::LXVST;
2605 } else if (str == X_("mac-vst")) {
2606 type = ARDOUR::MacVST;
2607 } else if (str == X_("audiounit")) {
2608 type = ARDOUR::AudioUnit;
2609 } else if (str == X_("luaproc")) {
2612 error << string_compose (_("unknown plugin type %1 in plugin insert state"), str) << endmsg;
2616 XMLProperty const * prop = node.property ("unique-id");
2619 #ifdef WINDOWS_VST_SUPPORT
2620 /* older sessions contain VST plugins with only an "id" field. */
2621 if (type == ARDOUR::Windows_VST) {
2622 prop = node.property ("id");
2626 #ifdef LXVST_SUPPORT
2627 /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/
2628 if (type == ARDOUR::LXVST) {
2629 prop = node.property ("id");
2636 error << _("Plugin has no unique ID field") << endmsg;
2641 boost::shared_ptr<Plugin> plugin = find_plugin (_session, prop->value(), type);
2642 bool any_vst = false;
2644 /* treat VST plugins equivalent if they have the same uniqueID
2645 * allow to move sessions windows <> linux */
2646 #ifdef LXVST_SUPPORT
2647 if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::MacVST)) {
2648 type = ARDOUR::LXVST;
2649 plugin = find_plugin (_session, prop->value(), type);
2650 if (plugin) { any_vst = true; }
2654 #ifdef WINDOWS_VST_SUPPORT
2655 if (plugin == 0 && (type == ARDOUR::LXVST || type == ARDOUR::MacVST)) {
2656 type = ARDOUR::Windows_VST;
2657 plugin = find_plugin (_session, prop->value(), type);
2658 if (plugin) { any_vst = true; }
2662 #ifdef MACVST_SUPPORT
2663 if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::LXVST)) {
2664 type = ARDOUR::MacVST;
2665 plugin = find_plugin (_session, prop->value(), type);
2666 if (plugin) { any_vst = true; }
2670 if (plugin == 0 && type == ARDOUR::Lua) {
2671 /* unique ID (sha1 of script) was not found,
2672 * load the plugin from the serialized version in the
2673 * session-file instead.
2675 boost::shared_ptr<LuaProc> lp (new LuaProc (_session.engine(), _session, ""));
2676 XMLNode *ls = node.child (lp->state_node_name().c_str());
2678 lp->set_script_from_state (*ls);
2684 error << string_compose(
2685 _("Found a reference to a plugin (\"%1\") that is unknown.\n"
2686 "Perhaps it was removed or moved since it was last used."),
2692 // The name of the PluginInsert comes from the plugin, nothing else
2693 _name = plugin->get_info()->name;
2697 // Processor::set_state() will set this, but too late
2698 // for it to be available when setting up plugin
2699 // state. We can't call Processor::set_state() until
2700 // the plugins themselves are created and added.
2704 if (_plugins.empty()) {
2705 /* if we are adding the first plugin, we will need to set
2706 * up automatable controls.
2708 add_plugin (plugin);
2709 create_automatable_parameters ();
2710 set_control_ids (node, version);
2712 /* update controllable value only (copy plugin state) */
2713 update_control_values (node, version);
2716 node.get_property ("count", count);
2718 if (_plugins.size() != count) {
2719 for (uint32_t n = 1; n < count; ++n) {
2720 add_plugin (plugin_factory (plugin));
2724 Processor::set_state (node, version);
2726 PBD::ID new_id = this->id();
2727 PBD::ID old_id = this->id();
2729 node.get_property ("id", old_id);
2731 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2733 /* find the node with the type-specific node name ("lv2", "ladspa", etc)
2734 and set all plugins to the same state.
2737 if ( ((*niter)->name() == plugin->state_node_name())
2738 || (any_vst && ((*niter)->name() == "lxvst" || (*niter)->name() == "windows-vst" || (*niter)->name() == "mac-vst"))
2741 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2742 /* Plugin state can include external files which are named after the ID.
2744 * If regenerate_xml_or_string_ids() is set, the ID will already have
2745 * been changed, so we need to use the old ID from the XML to load the
2746 * state and then update the ID.
2748 * When copying a plugin-state, route_ui takes care of of updating the ID,
2749 * but we need to call set_insert_id() to clear the cached plugin-state
2750 * and force a change.
2752 if (!regenerate_xml_or_string_ids ()) {
2753 (*i)->set_insert_id (new_id);
2755 (*i)->set_insert_id (old_id);
2758 (*i)->set_state (**niter, version);
2760 if (regenerate_xml_or_string_ids ()) {
2761 (*i)->set_insert_id (new_id);
2765 /* when copying plugin state, notify UI */
2766 for (Controls::const_iterator li = controls().begin(); li != controls().end(); ++li) {
2767 boost::shared_ptr<PBD::Controllable> c = boost::dynamic_pointer_cast<PBD::Controllable> (li->second);
2769 c->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
2777 if (version < 3000) {
2779 /* Only 2.X sessions need a call to set_parameter_state() - in 3.X and above
2780 this is all handled by Automatable
2783 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2784 if ((*niter)->name() == "Redirect") {
2785 /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
2786 Processor::set_state (**niter, version);
2791 set_parameter_state_2X (node, version);
2794 node.get_property (X_("custom"), _custom_cfg);
2796 uint32_t in_maps = 0;
2797 uint32_t out_maps = 0;
2798 XMLNodeList kids = node.children ();
2799 for (XMLNodeIterator i = kids.begin(); i != kids.end(); ++i) {
2800 if ((*i)->name() == X_("ConfiguredInput")) {
2801 _configured_in = ChanCount(**i);
2803 if ((*i)->name() == X_("CustomSinks")) {
2804 _custom_sinks = ChanCount(**i);
2806 if ((*i)->name() == X_("ConfiguredOutput")) {
2807 _custom_out = ChanCount(**i);
2808 _configured_out = ChanCount(**i);
2810 if ((*i)->name() == X_("PresetOutput")) {
2811 _preset_out = ChanCount(**i);
2813 if (strncmp ((*i)->name ().c_str(), X_("InputMap-"), 9) == 0) {
2814 long pc = atol (&((*i)->name().c_str()[9]));
2815 if (pc >= 0 && pc <= (long) get_count()) {
2816 _in_map[pc] = ChanMapping (**i);
2820 if (strncmp ((*i)->name ().c_str(), X_("OutputMap-"), 10) == 0) {
2821 long pc = atol (&((*i)->name().c_str()[10]));
2822 if (pc >= 0 && pc <= (long) get_count()) {
2823 _out_map[pc] = ChanMapping (**i);
2827 if ((*i)->name () == "ThruMap") {
2828 _thru_map = ChanMapping (**i);
2831 // sidechain is a Processor (IO)
2832 if ((*i)->name () == Processor::state_node_name) {
2834 if (regenerate_xml_or_string_ids ()) {
2835 add_sidechain_from_xml (**i, version);
2840 if (!regenerate_xml_or_string_ids ()) {
2841 _sidechain->set_state (**i, version);
2843 update_sidechain_name ();
2848 if (in_maps == out_maps && out_maps >0 && out_maps == get_count()) {
2849 _maps_from_state = true;
2852 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2856 (*i)->deactivate ();
2860 PluginConfigChanged (); /* EMIT SIGNAL */
2865 PluginInsert::update_id (PBD::ID id)
2868 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2869 (*i)->set_insert_id (id);
2874 PluginInsert::set_owner (SessionObject* o)
2876 Processor::set_owner (o);
2877 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2878 (*i)->set_owner (o);
2883 PluginInsert::set_state_dir (const std::string& d)
2885 // state() only saves the state of the first plugin
2886 _plugins[0]->set_state_dir (d);
2890 PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
2892 XMLNodeList nlist = node.children();
2893 XMLNodeIterator niter;
2895 /* look for port automation node */
2897 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2899 if ((*niter)->name() != port_automation_node_name) {
2904 XMLNodeConstIterator iter;
2908 cnodes = (*niter)->children ("port");
2910 for (iter = cnodes.begin(); iter != cnodes.end(); ++iter){
2914 if (!child->get_property("number", port_id)) {
2915 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
2919 if (port_id >= _plugins[0]->parameter_count()) {
2920 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
2924 boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
2925 control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
2927 if (c && c->alist()) {
2928 if (!child->children().empty()) {
2929 c->alist()->set_state (*child->children().front(), version);
2932 error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
2942 boost::shared_ptr<ReadOnlyControl>
2943 PluginInsert::control_output (uint32_t num) const
2945 CtrlOutMap::const_iterator i = _control_outputs.find (num);
2946 if (i == _control_outputs.end ()) {
2947 return boost::shared_ptr<ReadOnlyControl> ();
2954 PluginInsert::describe_parameter (Evoral::Parameter param)
2956 if (param.type() == PluginAutomation) {
2957 return _plugins[0]->describe_parameter (param);
2958 } else if (param.type() == PluginPropertyAutomation) {
2959 boost::shared_ptr<AutomationControl> c(automation_control(param));
2960 if (c && !c->desc().label.empty()) {
2961 return c->desc().label;
2964 return Automatable::describe_parameter(param);
2968 PluginInsert::signal_latency() const
2970 if (!_pending_active) {
2973 return plugin_latency ();
2977 PluginInsert::type ()
2979 return plugin()->get_info()->type;
2982 PluginInsert::PluginControl::PluginControl (PluginInsert* p,
2983 const Evoral::Parameter& param,
2984 const ParameterDescriptor& desc,
2985 boost::shared_ptr<AutomationList> list)
2986 : AutomationControl (p->session(), param, desc, list, p->describe_parameter(param))
2991 list->set_interpolation(Evoral::ControlList::Discrete);
2996 /** @param val `user' value */
2999 PluginInsert::PluginControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
3001 /* FIXME: probably should be taking out some lock here.. */
3003 for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
3004 (*i)->set_parameter (_list->parameter().id(), user_val);
3007 boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
3009 iasp->set_parameter (_list->parameter().id(), user_val);
3012 AutomationControl::actually_set_value (user_val, group_override);
3016 PluginInsert::PluginControl::catch_up_with_external_value (double user_val)
3018 AutomationControl::actually_set_value (user_val, Controllable::NoGroup);
3022 PluginInsert::PluginControl::get_state ()
3024 XMLNode& node (AutomationControl::get_state());
3025 node.set_property (X_("parameter"), parameter().id());
3027 boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugin->_plugins[0]);
3029 node.set_property (X_("symbol"), lv2plugin->port_symbol (parameter().id()));
3036 /** @return `user' val */
3038 PluginInsert::PluginControl::get_value () const
3040 boost::shared_ptr<Plugin> plugin = _plugin->plugin (0);
3046 return plugin->get_parameter (_list->parameter().id());
3050 PluginInsert::PluginControl::get_user_string () const
3052 boost::shared_ptr<Plugin> plugin = _plugin->plugin (0);
3055 if (plugin->print_parameter (parameter().id(), buf, sizeof(buf))) {
3056 assert (strlen (buf) > 0);
3057 return std::string (buf) + " (" + AutomationControl::get_user_string () + ")";
3060 return AutomationControl::get_user_string ();
3063 PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert* p,
3064 const Evoral::Parameter& param,
3065 const ParameterDescriptor& desc,
3066 boost::shared_ptr<AutomationList> list)
3067 : AutomationControl (p->session(), param, desc, list)
3073 PluginInsert::PluginPropertyControl::actually_set_value (double user_val, Controllable::GroupControlDisposition gcd)
3075 /* Old numeric set_value(), coerce to appropriate datatype if possible.
3076 This is lossy, but better than nothing until Ardour's automation system
3077 can handle various datatypes all the way down. */
3078 const Variant value(_desc.datatype, user_val);
3079 if (value.type() == Variant::NOTHING) {
3080 error << "set_value(double) called for non-numeric property" << endmsg;
3084 for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
3085 (*i)->set_property(_list->parameter().id(), value);
3090 AutomationControl::actually_set_value (user_val, gcd);
3094 PluginInsert::PluginPropertyControl::get_state ()
3096 XMLNode& node (AutomationControl::get_state());
3097 node.set_property (X_("property"), parameter().id());
3098 node.remove_property (X_("value"));
3104 PluginInsert::PluginPropertyControl::get_value () const
3106 return _value.to_double();
3109 boost::shared_ptr<Plugin>
3110 PluginInsert::get_impulse_analysis_plugin()
3112 boost::shared_ptr<Plugin> ret;
3113 if (_impulseAnalysisPlugin.expired()) {
3114 // LV2 in particular uses various _session params
3115 // during init() -- most notably block_size..
3117 ret = plugin_factory(_plugins[0]);
3118 ret->use_for_impulse_analysis ();
3119 ChanCount out (internal_output_streams ());
3120 if (ret->get_info ()->reconfigurable_io ()) {
3121 // populate get_info ()->n_inputs and ->n_outputs
3123 ret->can_support_io_configuration (internal_input_streams (), out, &useins);
3124 assert (out == internal_output_streams ());
3126 ret->configure_io (internal_input_streams (), out);
3127 ret->set_owner (_owner);
3128 _impulseAnalysisPlugin = ret;
3130 ret = _impulseAnalysisPlugin.lock();
3137 PluginInsert::collect_signal_for_analysis (samplecnt_t nframes)
3139 if (_signal_analysis_collect_nsamples_max != 0
3140 || _signal_analysis_collect_nsamples != 0) {
3144 // called from outside the audio thread, so this should be safe
3145 // only do audio as analysis is (currently) only for audio plugins
3146 _signal_analysis_inputs.ensure_buffers (DataType::AUDIO, input_streams().n_audio(), nframes);
3147 _signal_analysis_outputs.ensure_buffers (DataType::AUDIO, output_streams().n_audio(), nframes);
3149 /* these however should not be set while processing,
3150 * however in the given order, this should be fine.
3152 _signal_analysis_collect_nsamples = 0;
3153 _signal_analysis_collect_nsamples_max = nframes;
3156 /** Add a plugin to our list */
3158 PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
3160 plugin->set_insert_id (this->id());
3161 plugin->set_owner (_owner);
3163 if (_plugins.empty()) {
3164 /* first (and probably only) plugin instance - connect to relevant signals */
3166 plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed_externally, this, _1, _2));
3167 plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
3168 plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
3169 _custom_sinks = plugin->get_info()->n_inputs;
3170 // cache sidechain port count
3171 _cached_sidechain_pins.reset ();
3172 const ChanCount& nis (plugin->get_info()->n_inputs);
3173 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
3174 for (uint32_t in = 0; in < nis.get (*t); ++in) {
3175 const Plugin::IOPortDescription& iod (plugin->describe_io_port (*t, true, in));
3176 if (iod.is_sidechain) {
3177 _cached_sidechain_pins.set (*t, 1 + _cached_sidechain_pins.n(*t));
3182 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
3183 boost::shared_ptr<VSTPlugin> vst = boost::dynamic_pointer_cast<VSTPlugin> (plugin);
3185 vst->set_insert (this, _plugins.size ());
3189 _plugins.push_back (plugin);
3193 PluginInsert::add_sidechain_from_xml (const XMLNode& node, int version)
3195 if (version < 3000) {
3199 XMLNodeList nlist = node.children();
3201 if (nlist.size() == 0) {
3208 XMLNodeConstIterator it = nlist.front()->children().begin();
3209 for ( ; it != nlist.front()->children().end(); ++ it) {
3210 if ((*it)->name() == "Port") {
3211 DataType type(DataType::NIL);
3212 (*it)->get_property ("type", type);
3213 if (type == DataType::AUDIO) {
3215 } else if (type == DataType::MIDI) {
3221 ChanCount in_cc = ChanCount();
3222 in_cc.set (DataType::AUDIO, audio);
3223 in_cc.set (DataType::MIDI, midi);
3225 add_sidechain (audio, midi);
3229 PluginInsert::load_preset (ARDOUR::Plugin::PresetRecord pr)
3232 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
3233 if (! (*i)->load_preset (pr)) {
3238 boost::shared_ptr<Plugin> iasp = _impulseAnalysisPlugin.lock();
3240 iasp->load_preset (pr);
3247 PluginInsert::realtime_handle_transport_stopped ()
3249 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
3250 (*i)->realtime_handle_transport_stopped ();
3255 PluginInsert::realtime_locate ()
3257 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
3258 (*i)->realtime_locate ();
3263 PluginInsert::monitoring_changed ()
3265 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
3266 (*i)->monitoring_changed ();
3271 PluginInsert::latency_changed ()
3273 // this is called in RT context, LatencyChanged is emitted after run()
3274 _latency_changed = true;
3275 LatencyChanged (); /* EMIT SIGNAL */
3276 // XXX This needs a proper API not an owner() hack:
3277 // TODO Route should subscribe to LatencyChanged() and forward it
3278 // to the session as processor_latency_changed.
3280 static_cast<Route*>(owner ())->processor_latency_changed (); /* EMIT SIGNAL */
3284 PluginInsert::start_touch (uint32_t param_id)
3286 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
3288 // ToDo subtract _plugin_signal_latency from audible_sample() when rolling, assert > 0
3289 ac->start_touch (session().audible_sample());
3294 PluginInsert::end_touch (uint32_t param_id)
3296 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
3298 // ToDo subtract _plugin_signal_latency from audible_sample() when rolling, assert > 0
3299 ac->stop_touch (session().audible_sample());
3304 PluginInsert::provides_stats () const
3306 #if defined MIXBUS && defined NDEBUG
3307 if (is_channelstrip () || !display_to_user ()) {
3315 PluginInsert::get_stats (uint64_t& min, uint64_t& max, double& avg, double& dev) const
3317 /* TODO: consider taking a try/lock: Don't run concurrently with
3318 * TimingStats::update, TimingStats::reset.
3320 return _timing_stats.get_stats (min, max, avg, dev);
3324 PluginInsert::clear_stats ()
3326 g_atomic_int_set (&_stat_reset, 1);
3329 std::ostream& operator<<(std::ostream& o, const ARDOUR::PluginInsert::Match& m)
3332 case PluginInsert::Impossible: o << "Impossible"; break;
3333 case PluginInsert::Delegate: o << "Delegate"; break;
3334 case PluginInsert::NoInputs: o << "NoInputs"; break;
3335 case PluginInsert::ExactMatch: o << "ExactMatch"; break;
3336 case PluginInsert::Replicate: o << "Replicate"; break;
3337 case PluginInsert::Split: o << "Split"; break;
3338 case PluginInsert::Hide: o << "Hide"; break;
3340 o << " cnt: " << m.plugins
3341 << (m.strict_io ? " strict-io" : "")
3342 << (m.custom_cfg ? " custom-cfg" : "");
3343 if (m.method == PluginInsert::Hide) {
3344 o << " hide: " << m.hide;