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/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"
41 #include "ardour/lv2_plugin.h"
44 #ifdef WINDOWS_VST_SUPPORT
45 #include "ardour/windows_vst_plugin.h"
49 #include "ardour/lxvst_plugin.h"
52 #ifdef AUDIOUNIT_SUPPORT
53 #include "ardour/audio_unit.h"
56 #include "ardour/session.h"
57 #include "ardour/types.h"
62 using namespace ARDOUR;
65 const string PluginInsert::port_automation_node_name = "PortAutomation";
67 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
68 : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
69 , _signal_analysis_collected_nframes(0)
70 , _signal_analysis_collect_nframes_max(0)
75 , _maps_from_state (false)
77 /* the first is the master */
81 create_automatable_parameters ();
82 const ChanCount& sc (sidechain_input_pins ());
83 if (sc.n_audio () > 0) {
84 add_sidechain (sc.n_audio ());
89 PluginInsert::~PluginInsert ()
94 PluginInsert::set_strict_io (bool b)
96 bool changed = _strict_io != b;
99 PluginConfigChanged (); /* EMIT SIGNAL */
104 PluginInsert::set_count (uint32_t num)
106 bool require_state = !_plugins.empty();
108 /* this is a bad idea.... we shouldn't do this while active.
109 only a route holding their redirect_lock should be calling this
114 } else if (num > _plugins.size()) {
115 uint32_t diff = num - _plugins.size();
117 for (uint32_t n = 0; n < diff; ++n) {
118 boost::shared_ptr<Plugin> p = plugin_factory (_plugins[0]);
125 /* XXX do something */
128 PluginConfigChanged (); /* EMIT SIGNAL */
130 } else if (num < _plugins.size()) {
131 uint32_t diff = _plugins.size() - num;
132 for (uint32_t n= 0; n < diff; ++n) {
135 PluginConfigChanged (); /* EMIT SIGNAL */
143 PluginInsert::set_outputs (const ChanCount& c)
145 bool changed = (_custom_out != c) && _custom_cfg;
148 PluginConfigChanged (); /* EMIT SIGNAL */
153 PluginInsert::set_custom_cfg (bool b)
155 bool changed = _custom_cfg != b;
158 PluginConfigChanged (); /* EMIT SIGNAL */
163 PluginInsert::add_sidechain (uint32_t n_audio)
165 // caller must hold process lock
169 std::ostringstream n;
171 n << "Sidechain " << Session::next_name_id ();
173 n << "TO BE RESET FROM XML";
175 SideChain *sc = new SideChain (_session, n.str ());
176 _sidechain = boost::shared_ptr<SideChain> (sc);
177 _sidechain->activate ();
178 for (uint32_t n = 0; n < n_audio; ++n) {
179 _sidechain->input()->add_port ("", owner()); // add a port, don't connect.
181 PluginConfigChanged (); /* EMIT SIGNAL */
186 PluginInsert::del_sidechain ()
192 PluginConfigChanged (); /* EMIT SIGNAL */
197 PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, AutoState s)
199 if (which.type() != PluginAutomation)
202 boost::shared_ptr<AutomationControl> c
203 = boost::dynamic_pointer_cast<AutomationControl>(control (which));
206 _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
211 PluginInsert::output_streams() const
213 assert (_configured);
214 return _configured_out;
218 PluginInsert::input_streams() const
220 assert (_configured);
221 return _configured_in;
225 PluginInsert::internal_streams() const
227 assert (_configured);
228 return _configured_internal;
232 PluginInsert::internal_output_streams() const
234 assert (!_plugins.empty());
236 PluginInfoPtr info = _plugins.front()->get_info();
238 if (info->reconfigurable_io()) {
239 ChanCount out = _plugins.front()->output_streams ();
240 // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out));
243 ChanCount out = info->n_outputs;
244 // DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size()));
245 out.set_audio (out.n_audio() * _plugins.size());
246 out.set_midi (out.n_midi() * _plugins.size());
252 PluginInsert::internal_input_streams() const
254 assert (!_plugins.empty());
258 PluginInfoPtr info = _plugins.front()->get_info();
260 if (info->reconfigurable_io()) {
261 in = _plugins.front()->input_streams();
266 DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, input streams = %1, match using %2\n", in, _match.method));
268 if (_match.method == Split) {
270 /* we are splitting 1 processor input to multiple plugin inputs,
271 so we have a maximum of 1 stream of each type.
273 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
274 if (in.get (*t) > 1) {
280 } else if (_match.method == Hide) {
282 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
283 in.set (*t, in.get (*t) - _match.hide.get (*t));
289 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
290 in.set (*t, in.get (*t) * _plugins.size ());
298 PluginInsert::natural_output_streams() const
301 if (is_channelstrip ()) {
302 return _configured_out;
305 return _plugins[0]->get_info()->n_outputs;
309 PluginInsert::natural_input_streams() const
312 if (is_channelstrip ()) {
313 return _configured_in;
316 return _plugins[0]->get_info()->n_inputs;
320 PluginInsert::sidechain_input_pins() const
322 return _cached_sidechain_pins;
326 PluginInsert::has_no_inputs() const
328 return _plugins[0]->get_info()->n_inputs == ChanCount::ZERO;
332 PluginInsert::has_no_audio_inputs() const
334 return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
338 PluginInsert::plugin_latency () const {
339 return _plugins.front()->signal_latency ();
343 PluginInsert::needs_midi_input() const
345 PluginInfoPtr pip = _plugins[0]->get_info();
346 if (pip->needs_midi_input ()) {
349 return pip->n_inputs.n_midi() != 0 && pip->n_outputs.n_audio() != 0;
353 PluginInsert::create_automatable_parameters ()
355 assert (!_plugins.empty());
357 set<Evoral::Parameter> a = _plugins.front()->automatable ();
359 for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
360 if (i->type() == PluginAutomation) {
362 Evoral::Parameter param(*i);
364 ParameterDescriptor desc;
365 _plugins.front()->get_parameter_descriptor(i->id(), desc);
367 can_automate (param);
368 boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
369 boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
371 _plugins.front()->set_automation_control (i->id(), c);
372 } else if (i->type() == PluginPropertyAutomation) {
373 Evoral::Parameter param(*i);
374 const ParameterDescriptor& desc = _plugins.front()->get_property_descriptor(param.id());
375 if (desc.datatype != Variant::NOTHING) {
376 boost::shared_ptr<AutomationList> list;
377 if (Variant::type_is_numeric(desc.datatype)) {
378 list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
380 add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
385 /** Called when something outside of this host has modified a plugin
386 * parameter. Responsible for propagating the change to two places:
388 * 1) anything listening to the Control itself
389 * 2) any replicated plugins that make up this PluginInsert.
391 * The PluginInsert is connected to the ParameterChangedExternally signal for
392 * the first (primary) plugin, and here broadcasts that change to any others.
394 * XXX We should probably drop this whole replication idea (Paul, October 2015)
395 * since it isn't used by sensible plugin APIs (AU, LV2).
398 PluginInsert::parameter_changed_externally (uint32_t which, float val)
400 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, which));
402 /* First propagation: alter the underlying value of the control,
403 * without telling the plugin(s) that own/use it to set it.
410 boost::shared_ptr<PluginControl> pc = boost::dynamic_pointer_cast<PluginControl> (ac);
413 pc->catch_up_with_external_value (val);
416 /* Second propagation: tell all plugins except the first to
417 update the value of this parameter. For sane plugin APIs,
418 there are no other plugins, so this is a no-op in those
422 Plugins::iterator i = _plugins.begin();
424 /* don't set the first plugin, just all the slaves */
426 if (i != _plugins.end()) {
428 for (; i != _plugins.end(); ++i) {
429 (*i)->set_parameter (which, val);
435 PluginInsert::set_block_size (pframes_t nframes)
438 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
439 if ((*i)->set_block_size (nframes) != 0) {
447 PluginInsert::activate ()
449 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
453 Processor::activate ();
457 PluginInsert::deactivate ()
459 Processor::deactivate ();
461 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
467 PluginInsert::flush ()
469 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
475 PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t offset, bool with_auto, framepos_t now)
477 // TODO: atomically copy maps & _no_inplace
478 PinMappings in_map (_in_map);
479 PinMappings out_map (_out_map);
480 ChanMapping thru_map (_thru_map);
481 if (_mapping_changed) { // ToDo use a counters, increment until match.
482 _no_inplace = check_inplace ();
483 _mapping_changed = false;
486 if (_latency_changed) {
487 /* delaylines are configured with the max possible latency (as reported by the plugin)
488 * so this won't allocate memory (unless the plugin lied about its max latency)
489 * It may still 'click' though, since the fixed delaylines are not de-clicked.
490 * Then again plugin-latency changes are not click-free to begin with.
492 * This is also worst case, there is currently no concept of per-stream latency.
494 * e.g. Two identical latent plugins:
495 * 1st plugin: process left (latent), bypass right.
496 * 2nd plugin: bypass left, process right (latent).
497 * -> currently this yields 2 times latency of the plugin,
499 _latency_changed = false;
500 _delaybuffers.set (ChanCount::max(bufs.count(), _configured_out), plugin_latency ());
503 if (_match.method == Split && !_no_inplace) {
504 // TODO: also use this optimization if one source-buffer
505 // feeds _all_ *connected* inputs.
506 // currently this is *first* buffer to all only --
507 // see PluginInsert::check_inplace
508 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
509 if (_configured_internal.get (*t) == 0) {
513 uint32_t first_idx = in_map[0].get (*t, 0, &valid);
514 assert (valid && first_idx == 0); // check_inplace ensures this
515 /* copy the first stream's buffer contents to the others */
516 for (uint32_t i = 1; i < natural_input_streams ().get (*t); ++i) {
517 uint32_t idx = in_map[0].get (*t, i, &valid);
520 bufs.get (*t, i).read_from (bufs.get (*t, first_idx), nframes, offset, offset);
524 /* the copy operation produces a linear monotonic input map */
525 in_map[0] = ChanMapping (natural_input_streams ());
528 bufs.set_count(ChanCount::max(bufs.count(), _configured_internal));
529 bufs.set_count(ChanCount::max(bufs.count(), _configured_out));
535 for (Controls::iterator li = controls().begin(); li != controls().end(); ++li, ++n) {
537 boost::shared_ptr<AutomationControl> c
538 = boost::dynamic_pointer_cast<AutomationControl>(li->second);
540 if (c->list() && c->automation_playback()) {
543 const float val = c->list()->rt_safe_eval (now, valid);
546 /* This is the ONLY place where we are
548 * AutomationControl::set_value_unchecked(). We
549 * know that the control is in
550 * automation playback mode, so no
551 * check on writable() is required
552 * (which must be done in AutomationControl::set_value()
555 c->set_value_unchecked(val);
562 /* Calculate if, and how many frames we need to collect for analysis */
563 framecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
564 _signal_analysis_collected_nframes);
565 if (nframes < collect_signal_nframes) { // we might not get all frames now
566 collect_signal_nframes = nframes;
569 if (collect_signal_nframes > 0) {
571 //std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
572 //std::cerr << " streams " << internal_input_streams().n_audio() << std::endl;
573 //std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
575 _signal_analysis_inputs.set_count(internal_input_streams());
577 for (uint32_t i = 0; i < internal_input_streams().n_audio(); ++i) {
578 _signal_analysis_inputs.get_audio(i).read_from(
580 collect_signal_nframes,
581 _signal_analysis_collected_nframes); // offset is for target buffer
586 if (is_channelstrip ()) {
587 if (_configured_in.n_audio() > 0) {
588 ChanMapping mb_in_map (ChanCount::min (_configured_in, ChanCount (DataType::AUDIO, 2)));
589 ChanMapping mb_out_map (ChanCount::min (_configured_out, ChanCount (DataType::AUDIO, 2)));
591 _plugins.front()->connect_and_run (bufs, mb_in_map, mb_out_map, nframes, offset);
593 for (uint32_t out = _configured_in.n_audio (); out < bufs.count().get (DataType::AUDIO); ++out) {
594 bufs.get (DataType::AUDIO, out).silence (nframes, offset);
600 // TODO optimize -- build maps once.
602 BufferSet& inplace_bufs = _session.get_noinplace_buffers();
603 ARDOUR::ChanMapping used_outputs;
605 assert (inplace_bufs.count () >= natural_input_streams () + _configured_out);
607 /* build used-output map */
608 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
609 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
610 for (uint32_t out = 0; out < natural_output_streams().get (*t); ++out) {
612 uint32_t out_idx = out_map[pc].get (*t, out, &valid);
614 used_outputs.set (*t, out_idx, 1); // mark as used
619 /* copy thru data to outputs before processing in-place */
620 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
621 for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
623 uint32_t in_idx = thru_map.get (*t, out, &valid);
625 uint32_t m = out + natural_input_streams ().get (*t);
626 _delaybuffers.delay (*t, out, inplace_bufs.get (*t, m), bufs.get (*t, in_idx), nframes, offset, offset);
627 used_outputs.set (*t, out, 1); // mark as used
633 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
635 ARDOUR::ChanMapping i_in_map (natural_input_streams());
636 ARDOUR::ChanMapping i_out_map (out_map[pc]);
637 ARDOUR::ChanCount mapped;
639 /* map inputs sequentially */
640 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
641 for (uint32_t in = 0; in < natural_input_streams().get (*t); ++in) {
643 uint32_t in_idx = in_map[pc].get (*t, in, &valid);
644 uint32_t m = mapped.get (*t);
646 inplace_bufs.get (*t, m).read_from (bufs.get (*t, in_idx), nframes, offset, offset);
648 inplace_bufs.get (*t, m).silence (nframes, offset);
650 mapped.set (*t, m + 1);
654 /* outputs are mapped to inplace_bufs after the inputs */
655 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
656 i_out_map.offset_to (*t, natural_input_streams ().get (*t));
659 if ((*i)->connect_and_run (inplace_bufs, i_in_map, i_out_map, nframes, offset)) {
664 /* all instances have completed, now copy data that was written
665 * and zero unconnected buffers */
666 ARDOUR::ChanMapping nonzero_out (used_outputs);
667 if (has_midi_bypass ()) {
668 nonzero_out.set (DataType::MIDI, 0, 1); // Midi bypass.
670 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
671 for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
673 used_outputs.get (*t, out, &valid);
675 nonzero_out.get (*t, out, &valid);
677 bufs.get (*t, out).silence (nframes, offset);
680 uint32_t m = out + natural_input_streams ().get (*t);
681 bufs.get (*t, out).read_from (inplace_bufs.get (*t, m), nframes, offset, offset);
686 /* in-place processing */
688 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
689 if ((*i)->connect_and_run(bufs, in_map[pc], out_map[pc], nframes, offset)) {
694 // TODO optimize: store "unconnected" in a fixed set.
695 // it only changes on reconfiguration.
696 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
697 for (uint32_t out = 0; out < bufs.count().get (*t); ++out) {
699 if (*t == DataType::MIDI && out == 0 && has_midi_bypass ()) {
700 mapped = true; // in-place Midi bypass
702 for (uint32_t pc = 0; pc < get_count() && !mapped; ++pc) {
703 for (uint32_t o = 0; o < natural_output_streams().get (*t); ++o) {
705 uint32_t idx = out_map[pc].get (*t, o, &valid);
706 if (valid && idx == out) {
713 bufs.get (*t, out).silence (nframes, offset);
719 if (collect_signal_nframes > 0) {
721 //std::cerr << " output, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
722 //std::cerr << " streams " << internal_output_streams().n_audio() << std::endl;
724 _signal_analysis_outputs.set_count(internal_output_streams());
726 for (uint32_t i = 0; i < internal_output_streams().n_audio(); ++i) {
727 _signal_analysis_outputs.get_audio(i).read_from(
729 collect_signal_nframes,
730 _signal_analysis_collected_nframes); // offset is for target buffer
733 _signal_analysis_collected_nframes += collect_signal_nframes;
734 assert(_signal_analysis_collected_nframes <= _signal_analysis_collect_nframes_max);
736 if (_signal_analysis_collected_nframes == _signal_analysis_collect_nframes_max) {
737 _signal_analysis_collect_nframes_max = 0;
738 _signal_analysis_collected_nframes = 0;
740 AnalysisDataGathered(&_signal_analysis_inputs,
741 &_signal_analysis_outputs);
747 PluginInsert::silence (framecnt_t nframes)
753 ChanMapping in_map (natural_input_streams ());
754 ChanMapping out_map (natural_output_streams ());
756 // TODO run sidechain (delaylines)
757 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
758 (*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0);
763 PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool)
765 if (_pending_active) {
766 /* run as normal if we are active or moving from inactive to active */
769 // collect sidechain input for complete cycle (!)
770 // TODO we need delaylines here for latency compensation
771 _sidechain->run (bufs, start_frame, end_frame, nframes, true);
774 if (_session.transport_rolling() || _session.bounce_processing()) {
775 automation_run (bufs, start_frame, nframes);
777 connect_and_run (bufs, nframes, 0, false);
781 // TODO use mapping in bypassed mode ?!
782 // -> do we bypass the processor or the plugin
784 // TODO include sidechain??
786 uint32_t in = input_streams ().n_audio ();
787 uint32_t out = output_streams().n_audio ();
789 if (has_no_audio_inputs() || in == 0) {
791 /* silence all (audio) outputs. Should really declick
792 * at the transitions of "active"
795 for (uint32_t n = 0; n < out; ++n) {
796 bufs.get_audio (n).silence (nframes);
799 } else if (out > in) {
801 /* not active, but something has make up for any channel count increase
802 * for now , simply replicate last buffer
804 for (uint32_t n = in; n < out; ++n) {
805 bufs.get_audio(n).read_from(bufs.get_audio(in - 1), nframes);
809 bufs.count().set_audio (out);
812 _active = _pending_active;
814 /* we have no idea whether the plugin generated silence or not, so mark
815 * all buffers appropriately.
820 PluginInsert::automation_run (BufferSet& bufs, framepos_t start, pframes_t nframes)
822 Evoral::ControlEvent next_event (0, 0.0f);
823 framepos_t now = start;
824 framepos_t end = now + nframes;
825 framecnt_t offset = 0;
827 Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
830 connect_and_run (bufs, nframes, offset, false);
834 if (!find_next_event (now, end, next_event) || _plugins.front()->requires_fixed_sized_buffers()) {
836 /* no events have a time within the relevant range */
838 connect_and_run (bufs, nframes, offset, true, now);
844 framecnt_t cnt = min (((framecnt_t) ceil (next_event.when) - now), (framecnt_t) nframes);
846 connect_and_run (bufs, cnt, offset, true, now);
852 if (!find_next_event (now, end, next_event)) {
857 /* cleanup anything that is left to do */
860 connect_and_run (bufs, nframes, offset, true, now);
865 PluginInsert::default_parameter_value (const Evoral::Parameter& param)
867 if (param.type() != PluginAutomation)
870 if (_plugins.empty()) {
871 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
873 abort(); /*NOTREACHED*/
876 return _plugins[0]->default_value (param.id());
881 PluginInsert::can_reset_all_parameters ()
885 for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) {
887 const uint32_t cid = _plugins[0]->nth_parameter (par, ok);
889 if (!ok || !_plugins[0]->parameter_is_input(cid)) {
893 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid));
899 if (ac->automation_state() & Play) {
904 return all && (params > 0);
908 PluginInsert::reset_parameters_to_default ()
912 for (uint32_t par = 0; par < _plugins[0]->parameter_count(); ++par) {
914 const uint32_t cid = _plugins[0]->nth_parameter (par, ok);
916 if (!ok || !_plugins[0]->parameter_is_input(cid)) {
920 const float dflt = _plugins[0]->default_value (cid);
921 const float curr = _plugins[0]->get_parameter (cid);
927 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter(PluginAutomation, 0, cid));
932 if (ac->automation_state() & Play) {
937 ac->set_value (dflt, Controllable::NoGroup);
942 boost::shared_ptr<Plugin>
943 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
945 boost::shared_ptr<LadspaPlugin> lp;
946 boost::shared_ptr<LuaProc> lua;
948 boost::shared_ptr<LV2Plugin> lv2p;
950 #ifdef WINDOWS_VST_SUPPORT
951 boost::shared_ptr<WindowsVSTPlugin> vp;
954 boost::shared_ptr<LXVSTPlugin> lxvp;
956 #ifdef AUDIOUNIT_SUPPORT
957 boost::shared_ptr<AUPlugin> ap;
960 if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
961 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
962 } else if ((lua = boost::dynamic_pointer_cast<LuaProc> (other)) != 0) {
963 return boost::shared_ptr<Plugin> (new LuaProc (*lua));
965 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
966 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
968 #ifdef WINDOWS_VST_SUPPORT
969 } else if ((vp = boost::dynamic_pointer_cast<WindowsVSTPlugin> (other)) != 0) {
970 return boost::shared_ptr<Plugin> (new WindowsVSTPlugin (*vp));
973 } else if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (other)) != 0) {
974 return boost::shared_ptr<Plugin> (new LXVSTPlugin (*lxvp));
976 #ifdef AUDIOUNIT_SUPPORT
977 } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
978 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
982 fatal << string_compose (_("programming error: %1"),
983 X_("unknown plugin type in PluginInsert::plugin_factory"))
985 abort(); /*NOTREACHED*/
986 return boost::shared_ptr<Plugin> ((Plugin*) 0);
990 PluginInsert::set_input_map (uint32_t num, ChanMapping m) {
991 if (num < _in_map.size()) {
992 bool changed = _in_map[num] != m;
994 changed |= sanitize_maps ();
996 PluginMapChanged (); /* EMIT SIGNAL */
997 _mapping_changed = true;
998 _session.set_dirty();
1004 PluginInsert::set_output_map (uint32_t num, ChanMapping m) {
1005 if (num < _out_map.size()) {
1006 bool changed = _out_map[num] != m;
1008 changed |= sanitize_maps ();
1010 PluginMapChanged (); /* EMIT SIGNAL */
1011 _mapping_changed = true;
1012 _session.set_dirty();
1018 PluginInsert::set_thru_map (ChanMapping m) {
1019 bool changed = _thru_map != m;
1021 changed |= sanitize_maps ();
1023 PluginMapChanged (); /* EMIT SIGNAL */
1024 _mapping_changed = true;
1025 _session.set_dirty();
1030 PluginInsert::input_map () const
1034 for (PinMappings::const_iterator i = _in_map.begin (); i != _in_map.end (); ++i, ++pc) {
1035 ChanMapping m (i->second);
1036 const ChanMapping::Mappings& mp ((*i).second.mappings());
1037 for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
1038 for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
1039 rv.set (tm->first, i->first + pc * natural_input_streams().get(tm->first), i->second);
1047 PluginInsert::output_map () const
1051 for (PinMappings::const_iterator i = _out_map.begin (); i != _out_map.end (); ++i, ++pc) {
1052 ChanMapping m (i->second);
1053 const ChanMapping::Mappings& mp ((*i).second.mappings());
1054 for (ChanMapping::Mappings::const_iterator tm = mp.begin(); tm != mp.end(); ++tm) {
1055 for (ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) {
1056 rv.set (tm->first, i->first + pc * natural_output_streams().get(tm->first), i->second);
1060 if (has_midi_bypass ()) {
1061 rv.set (DataType::MIDI, 0, 0);
1068 PluginInsert::has_midi_bypass () const
1070 if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1
1071 && natural_output_streams ().n_midi () == 0) {
1078 PluginInsert::has_midi_thru () const
1080 if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1
1081 && natural_input_streams ().n_midi () == 0 && natural_output_streams ().n_midi () == 0) {
1089 PluginInsert::is_channelstrip () const {
1090 return _plugins.front()->is_channelstrip();
1095 PluginInsert::check_inplace ()
1097 bool inplace_ok = !_plugins.front()->inplace_broken ();
1099 if (_thru_map.n_total () > 0) {
1100 // TODO once midi-bypass is part of the mapping, ignore it
1104 if (_match.method == Split && inplace_ok) {
1105 assert (get_count() == 1);
1106 assert (_in_map.size () == 1);
1107 if (!_out_map[0].is_monotonic ()) {
1110 if (_configured_internal != _configured_in) {
1111 /* no sidechain -- TODO we could allow this with
1112 * some more logic in PluginInsert::connect_and_run().
1114 * PluginInsert::reset_map() already maps it.
1119 for (DataType::iterator t = DataType::begin(); t != DataType::end() && inplace_ok; ++t) {
1120 if (_configured_internal.get (*t) == 0) {
1124 uint32_t first_idx = _in_map[0].get (*t, 0, &valid);
1125 if (!valid || first_idx != 0) {
1126 // so far only allow to copy the *first* stream's buffer to others
1129 for (uint32_t i = 1; i < natural_input_streams ().get (*t); ++i) {
1130 uint32_t idx = _in_map[0].get (*t, i, &valid);
1131 if (valid && idx != first_idx) {
1140 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: In Place Split Map\n", name()));
1145 for (uint32_t pc = 0; pc < get_count() && inplace_ok ; ++pc) {
1146 if (!_in_map[pc].is_monotonic ()) {
1149 if (!_out_map[pc].is_monotonic ()) {
1153 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: %2\n", name(), inplace_ok ? "In-Place" : "No Inplace Processing"));
1154 return !inplace_ok; // no-inplace
1158 PluginInsert::sanitize_maps ()
1160 bool changed = false;
1161 /* strip dead wood */
1162 PinMappings new_ins;
1163 PinMappings new_outs;
1164 ChanMapping new_thru (_thru_map);
1166 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1168 ChanMapping new_out;
1169 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1170 for (uint32_t i = 0; i < natural_input_streams().get (*t); ++i) {
1172 uint32_t idx = _in_map[pc].get (*t, i, &valid);
1173 if (valid && idx < _configured_internal.get (*t)) {
1174 new_in.set (*t, i, idx);
1177 for (uint32_t o = 0; o < natural_output_streams().get (*t); ++o) {
1179 uint32_t idx = _out_map[pc].get (*t, o, &valid);
1180 if (valid && idx < _configured_out.get (*t)) {
1181 new_out.set (*t, o, idx);
1185 if (_in_map[pc] != new_in || _out_map[pc] != new_out) {
1188 new_ins[pc] = new_in;
1189 new_outs[pc] = new_out;
1192 /* prevent dup output assignments */
1193 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1194 for (uint32_t o = 0; o < _configured_out.get (*t); ++o) {
1195 bool mapped = false;
1196 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1198 uint32_t idx = new_outs[pc].get_src (*t, o, &valid);
1199 if (valid && mapped) {
1200 new_outs[pc].unset (*t, idx);
1208 /* prevent out + thru, existing plugin outputs override thru */
1209 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1210 for (uint32_t o = 0; o < _configured_out.get (*t); ++o) {
1211 bool mapped = false;
1213 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1214 new_outs[pc].get_src (*t, o, &mapped);
1215 if (mapped) { break; }
1217 if (!mapped) { continue; }
1218 uint32_t idx = new_thru.get (*t, o, &valid);
1220 new_thru.unset (*t, idx);
1225 if (has_midi_bypass ()) {
1226 // TODO: include midi-bypass in the thru set,
1227 // remove dedicated handling.
1228 new_thru.unset (DataType::MIDI, 0);
1231 if (_in_map != new_ins || _out_map != new_outs || _thru_map != new_thru) {
1235 _out_map = new_outs;
1236 _thru_map = new_thru;
1242 PluginInsert::reset_map (bool emit)
1244 const PinMappings old_in (_in_map);
1245 const PinMappings old_out (_out_map);
1249 _thru_map = ChanMapping ();
1251 /* build input map */
1252 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1253 uint32_t sc = 0; // side-chain round-robin (all instances)
1255 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
1256 const uint32_t nis = natural_input_streams ().get(*t);
1257 const uint32_t stride = nis - sidechain_input_pins().get (*t);
1259 /* SC inputs are last in the plugin-insert.. */
1260 const uint32_t sc_start = _configured_in.get (*t);
1261 const uint32_t sc_len = _configured_internal.get (*t) - sc_start;
1262 /* ...but may not be at the end of the plugin ports.
1263 * in case the side-chain is not the last port, shift connections back.
1264 * and connect to side-chain
1267 uint32_t ic = 0; // split inputs
1268 const uint32_t cend = _configured_in.get (*t);
1270 for (uint32_t in = 0; in < nis; ++in) {
1271 const Plugin::IOPortDescription& iod (_plugins[pc]->describe_io_port (*t, true, in));
1272 if (iod.is_sidechain) {
1273 /* connect sidechain sinks to sidechain inputs in round-robin fashion */
1274 if (sc_len > 0) {// side-chain may be hidden
1275 _in_map[pc].set (*t, in, sc_start + sc);
1276 sc = (sc + 1) % sc_len;
1280 if (_match.method == Split) {
1281 if (cend == 0) { continue; }
1282 if (_strict_io && ic + stride * pc >= cend) {
1285 /* connect *no* sidechain sinks in round-robin fashion */
1286 _in_map[pc].set (*t, in, ic + stride * pc);
1287 if (_strict_io && (ic + 1) == cend) {
1290 ic = (ic + 1) % cend;
1292 uint32_t s = in - shift;
1293 if (stride * pc + s < cend) {
1294 _in_map[pc].set (*t, in, s + stride * pc);
1302 /* build output map */
1304 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
1305 _out_map[pc] = ChanMapping (ChanCount::min (natural_output_streams(), _configured_out));
1306 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1307 _out_map[pc].offset_to(*t, pc * natural_output_streams().get(*t));
1312 if (old_in == _in_map && old_out == _out_map) {
1316 PluginMapChanged (); /* EMIT SIGNAL */
1317 _mapping_changed = true;
1318 _session.set_dirty();
1324 PluginInsert::configure_io (ChanCount in, ChanCount out)
1326 Match old_match = _match;
1328 ChanCount old_internal;
1332 old_in = _configured_in;
1333 old_internal = _configured_internal;
1334 old_out = _configured_out;
1337 _configured_in = in;
1338 _configured_internal = in;
1339 _configured_out = out;
1342 /* TODO hide midi-bypass, and custom outs. Best /fake/ "out" here.
1343 * (currently _sidechain->configure_io always succeeds
1344 * since Processor::configure_io() succeeds)
1346 if (!_sidechain->configure_io (in, out)) {
1347 DEBUG_TRACE (DEBUG::ChanMapping, "Sidechain configuration failed\n");
1350 _configured_internal += _sidechain->input()->n_ports();
1353 /* get plugin configuration */
1354 _match = private_can_support_io_configuration (in, out);
1356 if (DEBUG_ENABLED(DEBUG::ChanMapping)) {
1358 DEBUG_STR_APPEND(a, string_compose ("Match '%1': ", name()));
1359 DEBUG_STR_APPEND(a, _match);
1360 DEBUG_TRACE (DEBUG::ChanMapping, DEBUG_STR(a).str());
1364 /* set the matching method and number of plugins that we will use to meet this configuration */
1365 if (set_count (_match.plugins) == false) {
1366 PluginIoReConfigure (); /* EMIT SIGNAL */
1367 _configured = false;
1371 /* configure plugins */
1372 switch (_match.method) {
1375 if (_plugins.front()->configure_io (natural_input_streams(), out) == false) {
1376 PluginIoReConfigure (); /* EMIT SIGNAL */
1377 _configured = false;
1383 ChanCount dout (in); // hint
1386 } else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
1387 dout.set (DataType::AUDIO, 2);
1389 if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
1391 bool const r = _plugins.front()->can_support_io_configuration (in, dout, &useins);
1393 assert (dout.n_audio() <= out.n_audio()); // sans midi bypass
1394 if (useins.n_audio() == 0) {
1397 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("Delegate configuration: %1 %2 %3\n", name(), useins, dout));
1399 if (_plugins.front()->configure_io (useins, dout) == false) {
1400 PluginIoReConfigure (); /* EMIT SIGNAL */
1401 _configured = false;
1407 if (_plugins.front()->configure_io (in, out) == false) {
1408 PluginIoReConfigure (); /* EMIT SIGNAL */
1409 _configured = false;
1415 bool mapping_changed = false;
1416 if (old_in == in && old_out == out
1418 && old_match.method == _match.method
1419 && _in_map.size() == _out_map.size()
1420 && _in_map.size() == get_count ()
1422 /* If the configuration has not changed, keep the mapping */
1423 if (old_internal != _configured_internal) {
1424 mapping_changed = sanitize_maps ();
1426 } else if (_match.custom_cfg && _configured) {
1427 mapping_changed = sanitize_maps ();
1430 if (is_channelstrip ()) { _maps_from_state = false; }
1432 if (_maps_from_state) {
1433 _maps_from_state = false;
1434 mapping_changed = true;
1437 /* generate a new mapping */
1438 mapping_changed = reset_map (false);
1442 if (mapping_changed) {
1443 PluginMapChanged (); /* EMIT SIGNAL */
1446 if (DEBUG_ENABLED(DEBUG::ChanMapping)) {
1449 DEBUG_STR_APPEND(a, "\n--------<<--------\n");
1450 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
1452 DEBUG_STR_APPEND(a, "----><----\n");
1454 DEBUG_STR_APPEND(a, string_compose ("Channel Map for %1 plugin %2\n", name(), pc));
1455 DEBUG_STR_APPEND(a, " * Inputs:\n");
1456 DEBUG_STR_APPEND(a, _in_map[pc]);
1457 DEBUG_STR_APPEND(a, " * Outputs:\n");
1458 DEBUG_STR_APPEND(a, _out_map[pc]);
1460 DEBUG_STR_APPEND(a, " * Thru:\n");
1461 DEBUG_STR_APPEND(a, _thru_map);
1462 DEBUG_STR_APPEND(a, "-------->>--------\n");
1463 DEBUG_TRACE (DEBUG::ChanMapping, DEBUG_STR(a).str());
1468 _no_inplace = check_inplace ();
1469 _mapping_changed = false;
1471 /* only the "noinplace_buffers" thread buffers need to be this large,
1472 * this can be optimized. other buffers are fine with
1473 * ChanCount::max (natural_input_streams (), natural_output_streams())
1474 * and route.cc's max (configured_in, configured_out)
1476 * no-inplace copies "thru" outputs (to emulate in-place) for
1477 * all outputs (to prevent overwrite) into a temporary space
1478 * which also holds input buffers (in case the plugin does process
1479 * in-place and overwrites those).
1481 * this buffers need to be at least as
1482 * natural_input_streams () + possible outputs.
1484 * sidechain inputs add a constraint on the input:
1485 * configured input + sidechain (=_configured_internal)
1487 _required_buffers =ChanCount::max (_configured_internal,
1488 natural_input_streams () + ChanCount::max (_configured_out, natural_output_streams () * get_count ()));
1490 if (old_in != in || old_out != out || old_internal != _configured_internal
1491 || (old_match.method != _match.method && (old_match.method == Split || _match.method == Split))
1493 PluginIoReConfigure (); /* EMIT SIGNAL */
1496 _delaybuffers.configure (_configured_out, _plugins.front()->max_latency ());
1497 _latency_changed = true;
1499 // we don't know the analysis window size, so we must work with the
1500 // current buffer size here. each request for data fills in these
1501 // buffers and the analyser makes sure it gets enough data for the
1503 session().ensure_buffer_set (_signal_analysis_inputs, in);
1504 //_signal_analysis_inputs.set_count (in);
1506 session().ensure_buffer_set (_signal_analysis_outputs, out);
1507 //_signal_analysis_outputs.set_count (out);
1509 // std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
1512 return Processor::configure_io (in, out);
1515 /** Decide whether this PluginInsert can support a given IO configuration.
1516 * To do this, we run through a set of possible solutions in rough order of
1519 * @param in Required input channel count.
1520 * @param out Filled in with the output channel count if we return true.
1521 * @return true if the given IO configuration can be supported.
1524 PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
1527 _sidechain->can_support_io_configuration (in, out); // never fails, sets "out"
1529 return private_can_support_io_configuration (in, out).method != Impossible;
1532 /** A private version of can_support_io_configuration which returns the method
1533 * by which the configuration can be matched, rather than just whether or not
1537 PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
1539 if (_plugins.empty()) {
1544 if (is_channelstrip ()) {
1546 return Match (ExactMatch, 1);
1550 /* if a user specified a custom cfg, so be it. */
1552 PluginInfoPtr info = _plugins.front()->get_info();
1554 if (info->reconfigurable_io()) {
1555 return Match (Delegate, get_count(), _strict_io, true);
1557 return Match (ExactMatch, get_count(), _strict_io, true);
1561 /* try automatic configuration */
1562 Match m = PluginInsert::automatic_can_support_io_configuration (inx, out);
1564 PluginInfoPtr info = _plugins.front()->get_info();
1565 ChanCount inputs = info->n_inputs;
1566 ChanCount outputs = info->n_outputs;
1568 /* handle case strict-i/o */
1569 if (_strict_io && m.method != Impossible) {
1572 /* special case MIDI instruments */
1573 if (needs_midi_input ()) {
1574 // output = midi-bypass + at most master-out channels.
1575 ChanCount max_out (DataType::AUDIO, 2); // TODO use master-out
1576 max_out.set (DataType::MIDI, out.get(DataType::MIDI));
1577 out = ChanCount::min (out, max_out);
1578 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("special case strict-i/o instrument: %1\n", name()));
1584 if (inx.n_audio () != out.n_audio ()) { // ignore midi bypass
1585 /* replicate processor to match output count (generators and such)
1586 * at least enough to feed every output port. */
1587 uint32_t f = 1; // at least one. e.g. control data filters, no in, no out.
1588 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1589 uint32_t nout = outputs.get (*t);
1590 if (nout == 0 || inx.get(*t) == 0) { continue; }
1591 f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nout));
1594 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("special case strict-i/o generator: %1\n", name()));
1595 return Match (Replicate, f, _strict_io);
1606 if (m.method != Impossible) {
1610 ChanCount ns_inputs = inputs - sidechain_input_pins ();
1612 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("resolving 'Impossible' match for %1\n", name()));
1614 if (info->reconfigurable_io()) {
1617 if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
1618 if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
1619 bool const r = _plugins.front()->can_support_io_configuration (inx, out, &useins);
1621 // houston, we have a problem.
1622 return Match (Impossible, 0);
1624 return Match (Delegate, 1, _strict_io);
1627 ChanCount midi_bypass;
1628 if (inx.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
1629 midi_bypass.set (DataType::MIDI, 1);
1632 // add at least as many plugins so that output count matches input count (w/o sidechain pins)
1634 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1635 uint32_t nin = ns_inputs.get (*t);
1636 uint32_t nout = outputs.get (*t);
1637 if (nin == 0 || inx.get(*t) == 0) { continue; }
1638 // prefer floor() so the count won't overly increase IFF (nin < nout)
1639 f = max (f, (uint32_t) floor (inx.get(*t) / (float)nout));
1641 if (f > 0 && outputs * f >= _configured_out) {
1642 out = outputs * f + midi_bypass;
1643 return Match (Replicate, f, _strict_io);
1646 // add at least as many plugins needed to connect all inputs (w/o sidechain pins)
1648 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1649 uint32_t nin = ns_inputs.get (*t);
1650 if (nin == 0 || inx.get(*t) == 0) { continue; }
1651 f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin));
1654 out = outputs * f + midi_bypass;
1655 return Match (Replicate, f, _strict_io);
1658 // add at least as many plugins needed to connect all inputs
1660 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1661 uint32_t nin = inputs.get (*t);
1662 if (nin == 0 || inx.get(*t) == 0) { continue; }
1663 f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin));
1665 out = outputs * f + midi_bypass;
1666 return Match (Replicate, f, _strict_io);
1669 /* this is the original Ardour 3/4 behavior, mainly for backwards compatibility */
1671 PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
1673 if (_plugins.empty()) {
1677 PluginInfoPtr info = _plugins.front()->get_info();
1678 ChanCount in; in += inx;
1679 ChanCount midi_bypass;
1681 if (info->reconfigurable_io()) {
1682 /* Plugin has flexible I/O, so delegate to it
1683 * pre-seed outputs, plugin tries closest match
1686 if (out.n_midi () > 0 && out.n_audio () == 0) { out.set (DataType::AUDIO, 2); }
1687 if (out.n_audio () == 0) { out.set (DataType::AUDIO, 1); }
1688 bool const r = _plugins.front()->can_support_io_configuration (in, out);
1690 return Match (Impossible, 0);
1692 return Match (Delegate, 1);
1695 ChanCount inputs = info->n_inputs;
1696 ChanCount outputs = info->n_outputs;
1697 ChanCount ns_inputs = inputs - sidechain_input_pins ();
1699 if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
1700 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("bypassing midi-data around %1\n", name()));
1701 midi_bypass.set (DataType::MIDI, 1);
1703 if (in.get(DataType::MIDI) == 1 && inputs.get(DataType::MIDI) == 0) {
1704 DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("hiding midi-port from plugin %1\n", name()));
1705 in.set(DataType::MIDI, 0);
1708 // add internally provided sidechain ports
1709 ChanCount insc = in + sidechain_input_ports ();
1711 bool no_inputs = true;
1712 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1713 if (inputs.get (*t) != 0) {
1720 /* no inputs so we can take any input configuration since we throw it away */
1721 out = outputs + midi_bypass;
1722 return Match (NoInputs, 1);
1725 /* Plugin inputs match requested inputs + side-chain-ports exactly */
1726 if (inputs == insc) {
1727 out = outputs + midi_bypass;
1728 return Match (ExactMatch, 1);
1731 /* Plugin inputs matches without side-chain-pins */
1732 if (ns_inputs == in) {
1733 out = outputs + midi_bypass;
1734 return Match (ExactMatch, 1);
1737 /* We may be able to run more than one copy of the plugin within this insert
1738 to cope with the insert having more inputs than the plugin.
1739 We allow replication only for plugins with either zero or 1 inputs and outputs
1740 for every valid data type.
1744 bool can_replicate = true;
1745 for (DataType::iterator t = DataType::begin(); t != DataType::end() && can_replicate; ++t) {
1747 // ignore side-chains
1748 uint32_t nin = ns_inputs.get (*t);
1750 // No inputs of this type
1751 if (nin == 0 && in.get(*t) == 0) {
1755 if (nin != 1 || outputs.get (*t) != 1) {
1756 can_replicate = false;
1760 // Potential factor not set yet
1762 f = in.get(*t) / nin;
1765 // Factor for this type does not match another type, can not replicate
1766 if (f != (in.get(*t) / nin)) {
1767 can_replicate = false;
1772 if (can_replicate && f > 0) {
1773 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1774 out.set (*t, outputs.get(*t) * f);
1777 return Match (Replicate, f);
1780 /* If the processor has exactly one input of a given type, and
1781 the plugin has more, we can feed the single processor input
1782 to some or all of the plugin inputs. This is rather
1783 special-case-y, but the 1-to-many case is by far the
1784 simplest. How do I split thy 2 processor inputs to 3
1785 plugin inputs? Let me count the ways ...
1788 bool can_split = true;
1789 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1791 bool const can_split_type = (in.get (*t) == 1 && ns_inputs.get (*t) > 1);
1792 bool const nothing_to_do_for_type = (in.get (*t) == 0 && inputs.get (*t) == 0);
1794 if (!can_split_type && !nothing_to_do_for_type) {
1800 out = outputs + midi_bypass;
1801 return Match (Split, 1);
1804 /* If the plugin has more inputs than we want, we can `hide' some of them
1805 by feeding them silence.
1808 bool could_hide = false;
1809 bool cannot_hide = false;
1810 ChanCount hide_channels;
1812 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1813 if (inputs.get(*t) > in.get(*t)) {
1814 /* there is potential to hide, since the plugin has more inputs of type t than the insert */
1815 hide_channels.set (*t, inputs.get(*t) - in.get(*t));
1817 } else if (inputs.get(*t) < in.get(*t)) {
1818 /* we definitely cannot hide, since the plugin has fewer inputs of type t than the insert */
1823 if (could_hide && !cannot_hide) {
1824 out = outputs + midi_bypass;
1825 return Match (Hide, 1, false, false, hide_channels);
1828 return Match (Impossible, 0);
1833 PluginInsert::get_state ()
1835 return state (true);
1839 PluginInsert::state (bool full)
1841 XMLNode& node = Processor::state (full);
1843 node.add_property("type", _plugins[0]->state_node_name());
1844 node.add_property("unique-id", _plugins[0]->unique_id());
1845 node.add_property("count", string_compose("%1", _plugins.size()));
1847 /* remember actual i/o configuration (for later placeholder
1848 * in case the plugin goes missing) */
1849 node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
1850 node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
1852 /* save custom i/o config */
1853 node.add_property("custom", _custom_cfg ? "yes" : "no");
1854 for (uint32_t pc = 0; pc < get_count(); ++pc) {
1856 snprintf (tmp, sizeof(tmp), "InputMap-%d", pc);
1857 node.add_child_nocopy (* _in_map[pc].state (tmp));
1858 snprintf (tmp, sizeof(tmp), "OutputMap-%d", pc);
1859 node.add_child_nocopy (* _out_map[pc].state (tmp));
1861 node.add_child_nocopy (* _thru_map.state ("ThruMap"));
1864 node.add_child_nocopy (_sidechain->state (full));
1867 _plugins[0]->set_insert_id(this->id());
1868 node.add_child_nocopy (_plugins[0]->get_state());
1870 for (Controls::iterator c = controls().begin(); c != controls().end(); ++c) {
1871 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> ((*c).second);
1873 node.add_child_nocopy (ac->get_state());
1881 PluginInsert::set_control_ids (const XMLNode& node, int version)
1883 const XMLNodeList& nlist = node.children();
1884 XMLNodeConstIterator iter;
1885 set<Evoral::Parameter>::const_iterator p;
1887 for (iter = nlist.begin(); iter != nlist.end(); ++iter) {
1888 if ((*iter)->name() == Controllable::xml_node_name) {
1889 const XMLProperty* prop;
1891 uint32_t p = (uint32_t)-1;
1893 if ((prop = (*iter)->property (X_("symbol"))) != 0) {
1894 boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugins[0]);
1896 p = lv2plugin->port_index(prop->value().c_str());
1900 if (p == (uint32_t)-1 && (prop = (*iter)->property (X_("parameter"))) != 0) {
1901 p = atoi (prop->value());
1904 if (p != (uint32_t)-1) {
1906 /* this may create the new controllable */
1908 boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p));
1910 #ifndef NO_PLUGIN_STATE
1914 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
1916 ac->set_state (**iter, version);
1925 PluginInsert::set_state(const XMLNode& node, int version)
1927 XMLNodeList nlist = node.children();
1928 XMLNodeIterator niter;
1929 XMLPropertyList plist;
1930 const XMLProperty *prop;
1931 ARDOUR::PluginType type;
1933 if ((prop = node.property ("type")) == 0) {
1934 error << _("XML node describing plugin is missing the `type' field") << endmsg;
1938 if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
1939 type = ARDOUR::LADSPA;
1940 } else if (prop->value() == X_("lv2")) {
1942 } else if (prop->value() == X_("windows-vst")) {
1943 type = ARDOUR::Windows_VST;
1944 } else if (prop->value() == X_("lxvst")) {
1945 type = ARDOUR::LXVST;
1946 } else if (prop->value() == X_("audiounit")) {
1947 type = ARDOUR::AudioUnit;
1948 } else if (prop->value() == X_("luaproc")) {
1951 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
1957 prop = node.property ("unique-id");
1960 #ifdef WINDOWS_VST_SUPPORT
1961 /* older sessions contain VST plugins with only an "id" field.
1964 if (type == ARDOUR::Windows_VST) {
1965 prop = node.property ("id");
1969 #ifdef LXVST_SUPPORT
1970 /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/
1972 if (type == ARDOUR::LXVST) {
1973 prop = node.property ("id");
1979 error << _("Plugin has no unique ID field") << endmsg;
1984 boost::shared_ptr<Plugin> plugin = find_plugin (_session, prop->value(), type);
1986 /* treat linux and windows VST plugins equivalent if they have the same uniqueID
1987 * allow to move sessions windows <> linux */
1988 #ifdef LXVST_SUPPORT
1989 if (plugin == 0 && type == ARDOUR::Windows_VST) {
1990 type = ARDOUR::LXVST;
1991 plugin = find_plugin (_session, prop->value(), type);
1995 #ifdef WINDOWS_VST_SUPPORT
1996 if (plugin == 0 && type == ARDOUR::LXVST) {
1997 type = ARDOUR::Windows_VST;
1998 plugin = find_plugin (_session, prop->value(), type);
2003 error << string_compose(
2004 _("Found a reference to a plugin (\"%1\") that is unknown.\n"
2005 "Perhaps it was removed or moved since it was last used."),
2011 if (type == ARDOUR::Lua) {
2012 XMLNode *ls = node.child (plugin->state_node_name().c_str());
2013 // we need to load the script to set the name and parameters.
2014 boost::shared_ptr<LuaProc> lp = boost::dynamic_pointer_cast<LuaProc>(plugin);
2016 lp->set_script_from_state (*ls);
2020 // The name of the PluginInsert comes from the plugin, nothing else
2021 _name = plugin->get_info()->name;
2025 // Processor::set_state() will set this, but too late
2026 // for it to be available when setting up plugin
2027 // state. We can't call Processor::set_state() until
2028 // the plugins themselves are created and added.
2032 if (_plugins.empty()) {
2033 /* if we are adding the first plugin, we will need to set
2034 up automatable controls.
2036 add_plugin (plugin);
2037 create_automatable_parameters ();
2038 set_control_ids (node, version);
2041 if ((prop = node.property ("count")) != 0) {
2042 sscanf (prop->value().c_str(), "%u", &count);
2045 if (_plugins.size() != count) {
2046 for (uint32_t n = 1; n < count; ++n) {
2047 add_plugin (plugin_factory (plugin));
2051 Processor::set_state (node, version);
2053 PBD::ID new_id = this->id();
2054 PBD::ID old_id = this->id();
2056 if ((prop = node.property ("id")) != 0) {
2057 old_id = prop->value ();
2060 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2062 /* find the node with the type-specific node name ("lv2", "ladspa", etc)
2063 and set all plugins to the same state.
2066 if ((*niter)->name() == plugin->state_node_name()) {
2068 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2069 /* Plugin state can include external files which are named after the ID.
2071 * If regenerate_xml_or_string_ids() is set, the ID will already have
2072 * been changed, so we need to use the old ID from the XML to load the
2073 * state and then update the ID.
2075 * When copying a plugin-state, route_ui takes care of of updating the ID,
2076 * but we need to call set_insert_id() to clear the cached plugin-state
2077 * and force a change.
2079 if (!regenerate_xml_or_string_ids ()) {
2080 (*i)->set_insert_id (new_id);
2082 (*i)->set_insert_id (old_id);
2085 (*i)->set_state (**niter, version);
2087 if (regenerate_xml_or_string_ids ()) {
2088 (*i)->set_insert_id (new_id);
2096 if (version < 3000) {
2098 /* Only 2.X sessions need a call to set_parameter_state() - in 3.X and above
2099 this is all handled by Automatable
2102 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2103 if ((*niter)->name() == "Redirect") {
2104 /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
2105 Processor::set_state (**niter, version);
2110 set_parameter_state_2X (node, version);
2113 if ((prop = node.property (X_("custom"))) != 0) {
2114 _custom_cfg = string_is_affirmative (prop->value());
2117 uint32_t in_maps = 0;
2118 uint32_t out_maps = 0;
2119 XMLNodeList kids = node.children ();
2120 for (XMLNodeIterator i = kids.begin(); i != kids.end(); ++i) {
2121 if ((*i)->name() == X_("ConfiguredOutput")) {
2122 _custom_out = ChanCount(**i);
2124 if (strncmp ((*i)->name ().c_str(), X_("InputMap-"), 9) == 0) {
2125 long pc = atol (&((*i)->name().c_str()[9]));
2126 if (pc >=0 && pc <= get_count()) {
2127 _in_map[pc] = ChanMapping (**i);
2131 if (strncmp ((*i)->name ().c_str(), X_("OutputMap-"), 10) == 0) {
2132 long pc = atol (&((*i)->name().c_str()[10]));
2133 if (pc >=0 && pc <= get_count()) {
2134 _out_map[pc] = ChanMapping (**i);
2138 if ((*i)->name () == "ThruMap") {
2139 _thru_map = ChanMapping (**i);
2142 // sidechain is a Processor (IO)
2143 if ((*i)->name () == Processor::state_node_name) {
2147 _sidechain->set_state (**i, version);
2151 if (in_maps == out_maps && out_maps >0 && out_maps == get_count()) {
2152 _maps_from_state = true;
2155 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2159 (*i)->deactivate ();
2163 PluginConfigChanged (); /* EMIT SIGNAL */
2168 PluginInsert::update_id (PBD::ID id)
2171 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2172 (*i)->set_insert_id (id);
2177 PluginInsert::set_state_dir (const std::string& d)
2179 // state() only saves the state of the first plugin
2180 _plugins[0]->set_state_dir (d);
2184 PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
2186 XMLNodeList nlist = node.children();
2187 XMLNodeIterator niter;
2189 /* look for port automation node */
2191 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2193 if ((*niter)->name() != port_automation_node_name) {
2199 XMLNodeConstIterator iter;
2204 cnodes = (*niter)->children ("port");
2206 for (iter = cnodes.begin(); iter != cnodes.end(); ++iter){
2210 if ((cprop = child->property("number")) != 0) {
2211 port = cprop->value().c_str();
2213 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
2217 sscanf (port, "%" PRIu32, &port_id);
2219 if (port_id >= _plugins[0]->parameter_count()) {
2220 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
2224 boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
2225 control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
2227 if (c && c->alist()) {
2228 if (!child->children().empty()) {
2229 c->alist()->set_state (*child->children().front(), version);
2231 /* In some cases 2.X saves lists with min_yval and max_yval
2232 being FLT_MIN and FLT_MAX respectively. This causes problems
2233 in A3 because these min/max values are used to compute
2234 where GUI control points should be drawn. If we see such
2235 values, `correct' them to the min/max of the appropriate
2239 float min_y = c->alist()->get_min_y ();
2240 float max_y = c->alist()->get_max_y ();
2242 ParameterDescriptor desc;
2243 _plugins.front()->get_parameter_descriptor (port_id, desc);
2245 if (min_y == FLT_MIN) {
2249 if (max_y == FLT_MAX) {
2253 c->alist()->set_yrange (min_y, max_y);
2256 error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
2268 PluginInsert::describe_parameter (Evoral::Parameter param)
2270 if (param.type() == PluginAutomation) {
2271 return _plugins[0]->describe_parameter (param);
2272 } else if (param.type() == PluginPropertyAutomation) {
2273 boost::shared_ptr<AutomationControl> c(automation_control(param));
2274 if (c && !c->desc().label.empty()) {
2275 return c->desc().label;
2278 return Automatable::describe_parameter(param);
2282 PluginInsert::signal_latency() const
2284 if (_user_latency) {
2285 return _user_latency;
2288 return _plugins[0]->signal_latency ();
2292 PluginInsert::type ()
2294 return plugin()->get_info()->type;
2297 PluginInsert::PluginControl::PluginControl (PluginInsert* p,
2298 const Evoral::Parameter& param,
2299 const ParameterDescriptor& desc,
2300 boost::shared_ptr<AutomationList> list)
2301 : AutomationControl (p->session(), param, desc, list, p->describe_parameter(param))
2305 alist()->reset_default (desc.normal);
2307 list->set_interpolation(Evoral::ControlList::Discrete);
2312 set_flags(Controllable::Toggle);
2316 /** @param val `user' value */
2318 PluginInsert::PluginControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
2321 _set_value (user_val, group_override);
2325 PluginInsert::PluginControl::set_value_unchecked (double user_val)
2327 /* used only by automation playback */
2328 _set_value (user_val, Controllable::NoGroup);
2332 PluginInsert::PluginControl::_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
2334 /* FIXME: probably should be taking out some lock here.. */
2336 for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
2337 (*i)->set_parameter (_list->parameter().id(), user_val);
2340 boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
2342 iasp->set_parameter (_list->parameter().id(), user_val);
2345 AutomationControl::set_value (user_val, group_override);
2349 PluginInsert::PluginControl::catch_up_with_external_value (double user_val)
2351 AutomationControl::set_value (user_val, Controllable::NoGroup);
2355 PluginInsert::PluginControl::get_state ()
2359 XMLNode& node (AutomationControl::get_state());
2360 ss << parameter().id();
2361 node.add_property (X_("parameter"), ss.str());
2363 boost::shared_ptr<LV2Plugin> lv2plugin = boost::dynamic_pointer_cast<LV2Plugin> (_plugin->_plugins[0]);
2365 node.add_property (X_("symbol"), lv2plugin->port_symbol (parameter().id()));
2372 /** @return `user' val */
2374 PluginInsert::PluginControl::get_value () const
2376 boost::shared_ptr<Plugin> plugin = _plugin->plugin (0);
2382 return plugin->get_parameter (_list->parameter().id());
2385 PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert* p,
2386 const Evoral::Parameter& param,
2387 const ParameterDescriptor& desc,
2388 boost::shared_ptr<AutomationList> list)
2389 : AutomationControl (p->session(), param, desc, list)
2393 alist()->set_yrange (desc.lower, desc.upper);
2394 alist()->reset_default (desc.normal);
2398 set_flags(Controllable::Toggle);
2403 PluginInsert::PluginPropertyControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition /* group_override*/)
2406 set_value_unchecked (user_val);
2411 PluginInsert::PluginPropertyControl::set_value_unchecked (double user_val)
2413 /* Old numeric set_value(), coerce to appropriate datatype if possible.
2414 This is lossy, but better than nothing until Ardour's automation system
2415 can handle various datatypes all the way down. */
2416 const Variant value(_desc.datatype, user_val);
2417 if (value.type() == Variant::NOTHING) {
2418 error << "set_value(double) called for non-numeric property" << endmsg;
2422 for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
2423 (*i)->set_property(_list->parameter().id(), value);
2427 AutomationControl::set_value (user_val, Controllable::NoGroup);
2431 PluginInsert::PluginPropertyControl::get_state ()
2435 XMLNode& node (AutomationControl::get_state());
2436 ss << parameter().id();
2437 node.add_property (X_("property"), ss.str());
2438 node.remove_property (X_("value"));
2444 PluginInsert::PluginPropertyControl::get_value () const
2446 return _value.to_double();
2449 boost::shared_ptr<Plugin>
2450 PluginInsert::get_impulse_analysis_plugin()
2452 boost::shared_ptr<Plugin> ret;
2453 if (_impulseAnalysisPlugin.expired()) {
2454 ret = plugin_factory(_plugins[0]);
2455 ret->configure_io (internal_input_streams (), internal_output_streams ());
2456 _impulseAnalysisPlugin = ret;
2458 ret = _impulseAnalysisPlugin.lock();
2465 PluginInsert::collect_signal_for_analysis (framecnt_t nframes)
2467 // called from outside the audio thread, so this should be safe
2468 // only do audio as analysis is (currently) only for audio plugins
2469 _signal_analysis_inputs.ensure_buffers( DataType::AUDIO, internal_input_streams().n_audio(), nframes);
2470 _signal_analysis_outputs.ensure_buffers( DataType::AUDIO, internal_output_streams().n_audio(), nframes);
2472 _signal_analysis_collected_nframes = 0;
2473 _signal_analysis_collect_nframes_max = nframes;
2476 /** Add a plugin to our list */
2478 PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
2480 plugin->set_insert_id (this->id());
2482 if (_plugins.empty()) {
2483 /* first (and probably only) plugin instance - connect to relevant signals */
2485 plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed_externally, this, _1, _2));
2486 plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1));
2487 plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1));
2488 plugin->LatencyChanged.connect_same_thread (*this, boost::bind (&PluginInsert::latency_changed, this, _1, _2));
2489 // cache sidechain port count
2490 _cached_sidechain_pins.reset ();
2491 const ChanCount& nis (plugin->get_info()->n_inputs);
2492 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
2493 for (uint32_t in = 0; in < nis.get (*t); ++in) {
2494 const Plugin::IOPortDescription& iod (plugin->describe_io_port (*t, true, in));
2495 if (iod.is_sidechain) {
2496 _cached_sidechain_pins.set (*t, 1 + _cached_sidechain_pins.n(*t));
2501 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
2502 boost::shared_ptr<VSTPlugin> vst = boost::dynamic_pointer_cast<VSTPlugin> (plugin);
2504 vst->set_insert (this, _plugins.size ());
2507 _plugins.push_back (plugin);
2511 PluginInsert::realtime_handle_transport_stopped ()
2513 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2514 (*i)->realtime_handle_transport_stopped ();
2519 PluginInsert::realtime_locate ()
2521 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2522 (*i)->realtime_locate ();
2527 PluginInsert::monitoring_changed ()
2529 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
2530 (*i)->monitoring_changed ();
2535 PluginInsert::latency_changed (framecnt_t, framecnt_t)
2537 // this is called in RT context, LatencyChanged is emitted after run()
2538 _latency_changed = true;
2542 PluginInsert::start_touch (uint32_t param_id)
2544 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
2546 ac->start_touch (session().audible_frame());
2551 PluginInsert::end_touch (uint32_t param_id)
2553 boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
2555 ac->stop_touch (true, session().audible_frame());
2559 std::ostream& operator<<(std::ostream& o, const ARDOUR::PluginInsert::Match& m)
2562 case PluginInsert::Impossible: o << "Impossible"; break;
2563 case PluginInsert::Delegate: o << "Delegate"; break;
2564 case PluginInsert::NoInputs: o << "NoInputs"; break;
2565 case PluginInsert::ExactMatch: o << "ExactMatch"; break;
2566 case PluginInsert::Replicate: o << "Replicate"; break;
2567 case PluginInsert::Split: o << "Split"; break;
2568 case PluginInsert::Hide: o << "Hide"; break;
2570 o << " cnt: " << m.plugins
2571 << (m.strict_io ? " strict-io" : "")
2572 << (m.custom_cfg ? " custom-cfg" : "");
2573 if (m.method == PluginInsert::Hide) {
2574 o << " hide: " << m.hide;