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.
22 #include <sigc++/bind.h>
24 #include <pbd/failed_constructor.h>
25 #include <pbd/xml++.h>
26 #include <pbd/stacktrace.h>
28 #include <ardour/insert.h>
29 #include <ardour/plugin.h>
30 #include <ardour/port.h>
31 #include <ardour/route.h>
32 #include <ardour/ladspa_plugin.h>
35 #include <ardour/lv2_plugin.h>
39 #include <ardour/vst_plugin.h>
42 #ifdef HAVE_AUDIOUNITS
43 #include <ardour/audio_unit.h>
46 #include <ardour/audioengine.h>
47 #include <ardour/session.h>
48 #include <ardour/types.h>
53 using namespace ARDOUR;
56 Insert::Insert(Session& s, string name, Placement p)
57 : Redirect (s, name, p)
61 Insert::Insert(Session& s, string name, Placement p, int imin, int imax, int omin, int omax)
62 : Redirect (s, name, p, imin, imax, omin, omax)
66 /***************************************************************
67 Plugin inserts: send data through a plugin
68 ***************************************************************/
70 const string PluginInsert::port_automation_node_name = "PortAutomation";
72 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placement placement)
73 : Insert (s, plug->name(), placement)
75 /* the first is the master */
77 _plugins.push_back (plug);
79 _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
83 RedirectCreated (this); /* EMIT SIGNAL */
86 PluginInsert::PluginInsert (Session& s, const XMLNode& node)
87 : Insert (s, "will change", PreFader)
89 if (set_state (node)) {
90 throw failed_constructor();
93 _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
96 PluginInsert::PluginInsert (const PluginInsert& other)
97 : Insert (other._session, other.plugin()->name(), other.placement())
99 uint32_t count = other._plugins.size();
101 /* make as many copies as requested */
102 for (uint32_t n = 0; n < count; ++n) {
103 _plugins.push_back (plugin_factory (other.plugin (n)));
107 _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
111 RedirectCreated (this); /* EMIT SIGNAL */
115 PluginInsert::set_count (uint32_t num)
117 bool require_state = !_plugins.empty();
119 /* this is a bad idea.... we shouldn't do this while active.
120 only a route holding their redirect_lock should be calling this
125 } else if (num > _plugins.size()) {
126 uint32_t diff = num - _plugins.size();
128 for (uint32_t n = 0; n < diff; ++n) {
129 _plugins.push_back (plugin_factory (_plugins[0]));
132 /* XXX do something */
136 } else if (num < _plugins.size()) {
137 uint32_t diff = _plugins.size() - num;
138 for (uint32_t n= 0; n < diff; ++n) {
147 PluginInsert::init ()
152 PluginInsert::~PluginInsert ()
154 GoingAway (); /* EMIT SIGNAL */
158 PluginInsert::automation_list_creation_callback (uint32_t which, AutomationList& alist)
160 alist.automation_state_changed.connect (sigc::bind (mem_fun (*this, &PluginInsert::auto_state_changed), (which)));
164 PluginInsert::auto_state_changed (uint32_t which)
166 AutomationList& alist (automation_list (which));
168 if (alist.automation_state() != Off) {
169 _plugins[0]->set_parameter (which, alist.eval (_session.transport_frame()));
174 PluginInsert::output_streams() const
176 int32_t out = _plugins[0]->get_info()->n_outputs;
179 return _plugins[0]->output_streams ();
181 return out * _plugins.size();
186 PluginInsert::input_streams() const
188 int32_t in = _plugins[0]->get_info()->n_inputs;
191 return _plugins[0]->input_streams ();
193 return in * _plugins.size();
198 PluginInsert::natural_output_streams() const
200 return _plugins[0]->get_info()->n_outputs;
204 PluginInsert::natural_input_streams() const
206 return _plugins[0]->get_info()->n_inputs;
210 PluginInsert::is_generator() const
212 /* XXX more finesse is possible here. VST plugins have a
213 a specific "instrument" flag, for example.
216 return _plugins[0]->get_info()->n_inputs == 0;
220 PluginInsert::set_automatable ()
222 /* fill the parameter automation list with null AutomationLists */
224 parameter_automation.assign (_plugins.front()->parameter_count(), (AutomationList*) 0);
228 a = _plugins.front()->automatable ();
230 for (set<uint32_t>::iterator i = a.begin(); i != a.end(); ++i) {
236 PluginInsert::parameter_changed (uint32_t which, float val)
238 vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin();
240 /* don't set the first plugin, just all the slaves */
242 if (i != _plugins.end()) {
244 for (; i != _plugins.end(); ++i) {
245 (*i)->set_parameter (which, val);
251 PluginInsert::set_block_size (nframes_t nframes)
253 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
254 (*i)->set_block_size (nframes);
259 PluginInsert::activate ()
261 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
267 PluginInsert::deactivate ()
269 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
275 PluginInsert::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now)
277 int32_t in_index = 0;
278 int32_t out_index = 0;
280 /* Note that we've already required that plugins
281 be able to handle in-place processing.
284 // cerr << "Connect and run for " << _plugins[0]->name() << " auto ? " << with_auto << " nf = " << nframes << " off = " << offset << endl;
288 vector<AutomationList*>::iterator li;
291 for (n = 0, li = parameter_automation.begin(); li != parameter_automation.end(); ++li, ++n) {
293 AutomationList* alist = *li;
295 if (alist && alist->automation_playback()) {
298 float val = alist->rt_safe_eval (now, valid);
301 /* set the first plugin, the others will be set via signals */
302 // cerr << "\t@ " << now << " param[" << n << "] = " << val << endl;
303 _plugins[0]->set_parameter (n, val);
310 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
311 (*i)->connect_and_run (bufs, nbufs, in_index, out_index, nframes, offset);
316 PluginInsert::automation_snapshot (nframes_t now, bool force)
318 vector<AutomationList*>::iterator li;
321 for (n = 0, li = parameter_automation.begin(); li != parameter_automation.end(); ++li, ++n) {
323 AutomationList *alist = *li;
325 if (alist && alist->automation_write ()) {
327 float val = _plugins[0]->get_parameter (n);
328 alist->rt_add (now, val);
329 last_automation_snapshot = now;
335 PluginInsert::transport_stopped (nframes_t now)
337 vector<AutomationList*>::iterator li;
340 for (n = 0, li = parameter_automation.begin(); li != parameter_automation.end(); ++li, ++n) {
342 AutomationList* alist = *li;
345 alist->reposition_for_rt_add (now);
346 if (alist->automation_state() != Off) {
347 _plugins[0]->set_parameter (n, alist->eval (now));
354 PluginInsert::silence (nframes_t nframes)
356 int32_t in_index = 0;
357 int32_t out_index = 0;
361 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
363 (*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, 0);
369 PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
373 if (_session.transport_rolling()) {
374 automation_run (bufs, nbufs, nframes);
376 connect_and_run (bufs, nbufs, nframes, 0, false);
381 uint32_t in = input_streams ();
382 uint32_t out = output_streams ();
386 /* not active, but something has make up for any channel count increase,
387 so copy the last buffer to the extras.
390 for (uint32_t n = out - in; n < out && n < nbufs; ++n) {
391 memcpy (bufs[n], bufs[in - 1], sizeof (Sample) * nframes);
398 PluginInsert::set_parameter (uint32_t port, float val)
400 /* the others will be set from the event triggered by this */
402 float last_val = _plugins[0]->get_parameter (port);
403 Plugin::ParameterDescriptor desc;
404 _plugins[0]->get_parameter_descriptor(port, desc);
406 _plugins[0]->set_parameter (port, val);
408 if (automation_list (port).automation_write()) {
409 if ( desc.toggled ) //store the previous value just before this so any interpolation works right
410 automation_list (port).add (_session.audible_frame()-1, last_val);
411 automation_list (port).add (_session.audible_frame(), val);
414 _session.set_dirty();
418 PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
420 ControlEvent next_event (0, 0.0f);
421 nframes_t now = _session.transport_frame ();
422 nframes_t end = now + nframes;
423 nframes_t offset = 0;
425 Glib::Mutex::Lock lm (_automation_lock, Glib::TRY_LOCK);
428 connect_and_run (bufs, nbufs, nframes, 0, false, now);
432 if (!find_next_event (now, end, next_event)) {
433 /* no events have a time within the relevant range */
434 connect_and_run (bufs, nbufs, nframes, 0, true, now);
439 nframes_t cnt = min (((nframes_t) ceil (next_event.when) - now), nframes);
441 connect_and_run (bufs, nbufs, cnt, offset, true, now);
447 if (!find_next_event (now, end, next_event)) {
452 /* cleanup anything that is left to do */
455 connect_and_run (bufs, nbufs, nframes, offset, true, now);
461 PluginInsert::default_parameter_value (uint32_t port)
463 if (_plugins.empty()) {
464 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
469 return _plugins[0]->default_value (port);
473 PluginInsert::set_port_automation_state (uint32_t port, AutoState s)
475 if (port < _plugins[0]->parameter_count()) {
477 AutomationList& al = automation_list (port);
479 if (s != al.automation_state()) {
480 al.set_automation_state (s);
481 _session.set_dirty ();
487 PluginInsert::get_port_automation_state (uint32_t port)
489 if (port < _plugins[0]->parameter_count()) {
490 return automation_list (port).automation_state();
497 PluginInsert::protect_automation ()
499 set<uint32_t> automated_params;
501 what_has_automation (automated_params);
503 for (set<uint32_t>::iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
505 AutomationList& al = automation_list (*i);
507 switch (al.automation_state()) {
509 al.set_automation_state (Off);
512 al.set_automation_state (Play);
520 boost::shared_ptr<Plugin>
521 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
523 boost::shared_ptr<LadspaPlugin> lp;
525 boost::shared_ptr<LV2Plugin> lv2p;
528 boost::shared_ptr<VSTPlugin> vp;
530 #ifdef HAVE_AUDIOUNITS
531 boost::shared_ptr<AUPlugin> ap;
534 if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
535 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
537 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
538 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
541 } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
542 return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
544 #ifdef HAVE_AUDIOUNITS
545 } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
546 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
550 fatal << string_compose (_("programming error: %1"),
551 X_("unknown plugin type in PluginInsert::plugin_factory"))
554 return boost::shared_ptr<Plugin> ((Plugin*) 0);
558 PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out)
562 if ((ret = set_count (magic)) < 0) {
566 /* if we're running replicated plugins, each plugin has
567 the same i/o configuration and we may need to announce how many
568 output streams there are.
570 if we running a single plugin, we need to configure it.
573 return _plugins[0]->configure_io (in, out);
577 PluginInsert::can_do (int32_t in, int32_t& out)
579 return _plugins[0]->can_do (in, out);
583 PluginInsert::get_state(void)
589 PluginInsert::state (bool full)
592 XMLNode *node = new XMLNode("Insert");
594 node->add_child_nocopy (Redirect::state (full));
596 node->add_property ("type", _plugins[0]->state_node_name());
597 node->add_property("unique-id", _plugins[0]->unique_id());
598 node->add_property("count", string_compose("%1", _plugins.size()));
599 node->add_child_nocopy (_plugins[0]->get_state());
601 /* add controllables */
603 XMLNode* control_node = new XMLNode (X_("controls"));
605 for (uint32_t x = 0; x < _plugins[0]->parameter_count(); ++x) {
606 Controllable* c = _plugins[0]->get_nth_control (x, true);
608 XMLNode& controllable_state (c->get_state());
609 controllable_state.add_property ("parameter", to_string (x, std::dec));
610 control_node->add_child_nocopy (controllable_state);
613 node->add_child_nocopy (*control_node);
615 /* add port automation state */
616 XMLNode *autonode = new XMLNode(port_automation_node_name);
617 set<uint32_t> automatable = _plugins[0]->automatable();
619 for (set<uint32_t>::iterator x = automatable.begin(); x != automatable.end(); ++x) {
621 XMLNode* child = new XMLNode("port");
622 snprintf(buf, sizeof(buf), "%" PRIu32, *x);
623 child->add_property("number", string(buf));
626 LV2Plugin* lv2p = dynamic_cast<LV2Plugin*>(_plugins[0].get());
628 child->add_property("symbol", string(lv2p->port_symbol(*x)));
632 child->add_child_nocopy (automation_list (*x).state (full));
633 autonode->add_child_nocopy (*child);
636 node->add_child_nocopy (*autonode);
642 PluginInsert::set_state(const XMLNode& node)
644 XMLNodeList nlist = node.children();
645 XMLNodeIterator niter;
646 XMLPropertyList plist;
647 const XMLProperty *prop;
648 ARDOUR::PluginType type;
650 if ((prop = node.property ("type")) == 0) {
651 error << _("XML node describing insert is missing the `type' field") << endmsg;
655 if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
656 type = ARDOUR::LADSPA;
657 } else if (prop->value() == X_("lv2")) {
659 } else if (prop->value() == X_("vst")) {
661 } else if (prop->value() == X_("audiounit")) {
662 type = ARDOUR::AudioUnit;
664 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
670 prop = node.property ("unique-id");
673 /* older sessions contain VST plugins with only an "id" field.
676 if (type == ARDOUR::VST) {
677 prop = node.property ("id");
683 error << _("Plugin has no unique ID field") << endmsg;
688 boost::shared_ptr<Plugin> plugin;
690 plugin = find_plugin (_session, prop->value(), type);
693 error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
694 "Perhaps it was removed or moved since it was last used."), prop->value())
701 if ((prop = node.property ("count")) != 0) {
702 sscanf (prop->value().c_str(), "%u", &count);
705 if (_plugins.size() != count) {
707 _plugins.push_back (plugin);
709 for (uint32_t n=1; n < count; ++n) {
710 _plugins.push_back (plugin_factory (plugin));
714 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
715 if ((*niter)->name() == plugin->state_node_name()) {
716 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
717 (*i)->set_state (**niter);
723 if (niter == nlist.end()) {
724 error << string_compose(_("XML node describing a plugin insert is missing the `%1' information"), plugin->state_node_name()) << endmsg;
728 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
729 if ((*niter)->name() == Redirect::state_node_name) {
730 Redirect::set_state (**niter);
735 if (niter == nlist.end()) {
736 error << _("XML node describing insert is missing a Redirect node") << endmsg;
740 /* look for controllables node */
742 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
744 if ((*niter)->name() != X_("controls")) {
748 XMLNodeList grandchildren ((*niter)->children());
750 XMLNodeIterator gciter;
753 for (gciter = grandchildren.begin(); gciter != grandchildren.end(); ++gciter) {
754 if ((prop = (*gciter)->property (X_("parameter"))) != 0) {
755 param = atoi (prop->value());
756 /* force creation of controllable for this parameter */
757 _plugins[0]->make_nth_control (param, **gciter);
766 /* look for port automation node */
768 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
770 if ((*niter)->name() != port_automation_node_name) {
776 XMLNodeConstIterator iter;
781 cnodes = (*niter)->children ("port");
783 for(iter = cnodes.begin(); iter != cnodes.end(); ++iter){
787 if ((cprop = child->property("number")) != 0) {
788 port = cprop->value().c_str();
790 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
794 sscanf (port, "%" PRIu32, &port_id);
796 if (port_id >= _plugins[0]->parameter_count()) {
797 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
801 if (!child->children().empty()) {
802 automation_list (port_id).set_state (*child->children().front());
804 if ((cprop = child->property("auto")) != 0) {
809 sscanf (cprop->value().c_str(), "0x%x", &x);
810 automation_list (port_id).set_automation_state (AutoState (x));
816 automation_list (port_id).set_automation_state (Off);
827 if (niter == nlist.end()) {
828 warning << string_compose(_("XML node describing a port automation is missing the `%1' information"), port_automation_node_name) << endmsg;
831 // The name of the PluginInsert comes from the plugin, nothing else
832 set_name(plugin->get_info()->name,this);
838 PluginInsert::describe_parameter (uint32_t what)
840 return _plugins[0]->describe_parameter (what);
844 PluginInsert::latency()
846 return _plugins[0]->latency ();
850 PluginInsert::type ()
852 boost::shared_ptr<LadspaPlugin> lp;
854 boost::shared_ptr<VSTPlugin> vp;
856 #ifdef HAVE_AUDIOUNITS
857 boost::shared_ptr<AUPlugin> ap;
860 boost::shared_ptr<LV2Plugin> lv2p;
863 PluginPtr other = plugin ();
865 if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
866 return ARDOUR::LADSPA;
868 } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
871 #ifdef HAVE_AUDIOUNITS
872 } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
873 return ARDOUR::AudioUnit;
876 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
880 error << "Unknown plugin type" << endmsg;
882 return (ARDOUR::PluginType) 0;
886 /***************************************************************
887 Port inserts: send output to a port, pick up input at a port
888 ***************************************************************/
890 PortInsert::PortInsert (Session& s, Placement p)
891 : Insert (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
894 RedirectCreated (this); /* EMIT SIGNAL */
898 PortInsert::PortInsert (const PortInsert& other)
899 : Insert (other._session, string_compose (_("insert %1"), (bitslot = other._session.next_insert_id()) + 1), other.placement(), 1, -1, 1, -1)
902 RedirectCreated (this); /* EMIT SIGNAL */
910 PortInsert::PortInsert (Session& s, const XMLNode& node)
911 : Insert (s, "will change", PreFader)
913 bitslot = 0xffffffff;
914 if (set_state (node)) {
915 throw failed_constructor();
918 RedirectCreated (this); /* EMIT SIGNAL */
921 PortInsert::~PortInsert ()
927 PortInsert::run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
929 if (n_outputs() == 0) {
934 /* deliver silence */
940 vector<Port*>::iterator o;
941 vector<Port*>::iterator i;
945 for (o = _outputs.begin(), n = 0; o != _outputs.end(); ++o, ++n) {
946 memcpy (get_output_buffer (n, nframes), bufs[min(nbufs,n)], sizeof (Sample) * nframes);
947 (*o)->mark_silence (false);
952 for (i = _inputs.begin(), n = 0; i != _inputs.end(); ++i, ++n) {
953 memcpy (bufs[min(nbufs,n)], get_input_buffer (n, nframes), sizeof (Sample) * nframes);
958 PortInsert::get_state(void)
964 PortInsert::state (bool full)
966 XMLNode *node = new XMLNode("Insert");
968 node->add_child_nocopy (Redirect::state(full));
969 node->add_property ("type", "port");
970 snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
971 node->add_property ("bitslot", buf);
977 PortInsert::set_state(const XMLNode& node)
979 XMLNodeList nlist = node.children();
980 XMLNodeIterator niter;
981 XMLPropertyList plist;
982 const XMLProperty *prop;
984 if ((prop = node.property ("type")) == 0) {
985 error << _("XML node describing insert is missing the `type' field") << endmsg;
989 if (prop->value() != "port") {
990 error << _("non-port insert XML used for port plugin insert") << endmsg;
994 if ((prop = node.property ("bitslot")) == 0) {
995 bitslot = _session.next_insert_id();
997 uint32_t old_bitslot = bitslot;
998 sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
1000 if (old_bitslot != bitslot) {
1001 _session.mark_insert_id (bitslot);
1005 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1006 if ((*niter)->name() == Redirect::state_node_name) {
1007 Redirect::set_state (**niter);
1012 if (niter == nlist.end()) {
1013 error << _("XML node describing insert is missing a Redirect node") << endmsg;
1021 PortInsert::latency()
1023 /* because we deliver and collect within the same cycle,
1024 all I/O is necessarily delayed by at least frames_per_cycle().
1026 if the return port for insert has its own latency, we
1027 need to take that into account too.
1030 return _session.engine().frames_per_cycle() + input_latency();
1034 PortInsert::can_do (int32_t in, int32_t& out)
1036 if (input_maximum() == -1 && output_maximum() == -1) {
1038 /* not configured yet */
1045 /* the "input" config for a port insert corresponds to how
1046 many output ports it will have.
1049 if (output_maximum() == in) {
1059 PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out)
1061 /* do not allow configuration to be changed outside the range of
1062 the last request config. or something like that.
1065 set_output_maximum (in);
1066 set_output_minimum (in);
1067 set_input_maximum (out);
1068 set_input_minimum (out);
1070 /* this can be momentarily confusing:
1072 the number of inputs we are required to handle corresponds
1073 to the number of output ports we need.
1075 the number of outputs we are required to have corresponds
1076 to the number of input ports we need.
1087 return ensure_io (out, in, false, this);
1091 PortInsert::output_streams() const
1097 PortInsert::input_streams() const
1099 return n_outputs ();