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/event_type_map.h"
34 #include "ardour/ladspa_plugin.h"
35 #include "ardour/plugin.h"
36 #include "ardour/plugin_insert.h"
37 #include "ardour/port.h"
38 #include "ardour/route.h"
41 #include "ardour/lv2_plugin.h"
45 #include "ardour/vst_plugin.h"
49 #include "ardour/lxvst_plugin.h"
52 #ifdef HAVE_AUDIOUNITS
53 #include "ardour/audio_unit.h"
56 #include "ardour/audioengine.h"
57 #include "ardour/session.h"
58 #include "ardour/types.h"
63 using namespace ARDOUR;
66 const string PluginInsert::port_automation_node_name = "PortAutomation";
68 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
69 : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
70 , _signal_analysis_collected_nframes(0)
71 , _signal_analysis_collect_nframes_max(0)
74 /* the first is the master */
78 create_automatable_parameters ();
80 Glib::Mutex::Lock em (_session.engine().process_lock());
81 IO::PortCountChanged (max(input_streams(), output_streams()));
86 PluginInsert::set_count (uint32_t num)
88 bool require_state = !_plugins.empty();
90 /* this is a bad idea.... we shouldn't do this while active.
91 only a route holding their redirect_lock should be calling this
96 } else if (num > _plugins.size()) {
97 uint32_t diff = num - _plugins.size();
99 for (uint32_t n = 0; n < diff; ++n) {
100 add_plugin_with_activation (plugin_factory (_plugins[0]));
103 /* XXX do something */
107 } else if (num < _plugins.size()) {
108 uint32_t diff = _plugins.size() - num;
109 for (uint32_t n= 0; n < diff; ++n) {
117 PluginInsert::~PluginInsert ()
122 PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, AutoState s)
124 if (which.type() != PluginAutomation)
127 boost::shared_ptr<AutomationControl> c
128 = boost::dynamic_pointer_cast<AutomationControl>(control (which));
131 _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
136 PluginInsert::output_streams() const
138 ChanCount out = _plugins.front()->get_info()->n_outputs;
140 if (out == ChanCount::INFINITE) {
141 return _plugins.front()->output_streams ();
143 out.set_audio (out.n_audio() * _plugins.size());
144 out.set_midi (out.n_midi() * _plugins.size());
150 PluginInsert::input_streams() const
152 ChanCount in = _plugins[0]->get_info()->n_inputs;
156 /* we are splitting 1 processor input to multiple plugin inputs,
157 so we have a maximum of 1 stream of each type.
159 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
160 if (in.get (*t) > 1) {
166 } else if (in == ChanCount::INFINITE) {
167 return _plugins[0]->input_streams ();
169 in.set_audio (in.n_audio() * _plugins.size());
170 in.set_midi (in.n_midi() * _plugins.size());
176 PluginInsert::natural_output_streams() const
178 return _plugins[0]->get_info()->n_outputs;
182 PluginInsert::natural_input_streams() const
184 return _plugins[0]->get_info()->n_inputs;
188 PluginInsert::has_no_inputs() const
190 return _plugins[0]->get_info()->n_inputs == ChanCount::ZERO;
194 PluginInsert::has_no_audio_inputs() const
196 return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
200 PluginInsert::is_midi_instrument() const
202 /* XXX more finesse is possible here. VST plugins have a
203 a specific "instrument" flag, for example.
205 PluginInfoPtr pi = _plugins[0]->get_info();
207 return pi->n_inputs.n_midi() != 0 &&
208 pi->n_outputs.n_audio() > 0;
212 PluginInsert::create_automatable_parameters ()
214 assert (!_plugins.empty());
216 set<Evoral::Parameter> a = _plugins.front()->automatable ();
218 Plugin::ParameterDescriptor desc;
220 for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
221 if (i->type() == PluginAutomation) {
223 Evoral::Parameter param(*i);
225 _plugins.front()->get_parameter_descriptor(i->id(), desc);
227 /* the Parameter belonging to the actual plugin doesn't have its range set
228 but we want the Controllable related to this Parameter to have those limits.
231 param.set_range (desc.lower, desc.upper, _plugins.front()->default_value(i->id()), desc.toggled);
232 can_automate (param);
233 boost::shared_ptr<AutomationList> list(new AutomationList(param));
234 add_control (boost::shared_ptr<AutomationControl> (new PluginControl(this, param, list)));
240 PluginInsert::parameter_changed (Evoral::Parameter which, float val)
242 if (which.type() != PluginAutomation)
245 Plugins::iterator i = _plugins.begin();
247 /* don't set the first plugin, just all the slaves */
249 if (i != _plugins.end()) {
251 for (; i != _plugins.end(); ++i) {
252 (*i)->set_parameter (which, val);
258 PluginInsert::set_block_size (pframes_t nframes)
261 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
262 if ((*i)->set_block_size (nframes) != 0) {
270 PluginInsert::activate ()
272 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
276 Processor::activate ();
280 PluginInsert::deactivate ()
282 Processor::deactivate ();
284 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
290 PluginInsert::flush ()
292 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
298 PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t offset, bool with_auto, framepos_t now)
300 // Calculate if, and how many frames we need to collect for analysis
301 framecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
302 _signal_analysis_collected_nframes);
303 if (nframes < collect_signal_nframes) { // we might not get all frames now
304 collect_signal_nframes = nframes;
307 ChanMapping in_map(input_streams());
308 ChanMapping out_map(output_streams());
311 /* fix the input mapping so that we have maps for each of the plugin's inputs */
312 in_map = ChanMapping (natural_input_streams ());
314 /* copy the first stream's buffer contents to the others */
315 /* XXX: audio only */
316 Sample const * mono = bufs.get_audio (in_map.get (DataType::AUDIO, 0)).data (offset);
317 for (uint32_t i = input_streams().n_audio(); i < natural_input_streams().n_audio(); ++i) {
318 memcpy (bufs.get_audio (in_map.get (DataType::AUDIO, i)).data (offset), mono, sizeof (Sample) * nframes);
322 /* Note that we've already required that plugins
323 be able to handle in-place processing.
330 for (Controls::iterator li = controls().begin(); li != controls().end(); ++li, ++n) {
332 boost::shared_ptr<AutomationControl> c
333 = boost::dynamic_pointer_cast<AutomationControl>(li->second);
335 if (c->parameter().type() == PluginAutomation && c->automation_playback()) {
338 const float val = c->list()->rt_safe_eval (now, valid);
348 if (collect_signal_nframes > 0) {
350 //std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
351 //std::cerr << " streams " << input_streams().n_audio() << std::endl;
352 //std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
354 _signal_analysis_inputs.set_count(input_streams());
356 for (uint32_t i = 0; i < input_streams().n_audio(); ++i) {
357 _signal_analysis_inputs.get_audio(i).read_from(
359 collect_signal_nframes,
360 _signal_analysis_collected_nframes); // offset is for target buffer
365 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
366 (*i)->connect_and_run(bufs, in_map, out_map, nframes, offset);
367 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
368 in_map.offset_to(*t, natural_input_streams().get(*t));
369 out_map.offset_to(*t, natural_output_streams().get(*t));
373 if (collect_signal_nframes > 0) {
375 //std::cerr << " output, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
376 //std::cerr << " streams " << output_streams().n_audio() << std::endl;
378 _signal_analysis_outputs.set_count(output_streams());
380 for (uint32_t i = 0; i < output_streams().n_audio(); ++i) {
381 _signal_analysis_outputs.get_audio(i).read_from(
383 collect_signal_nframes,
384 _signal_analysis_collected_nframes); // offset is for target buffer
387 _signal_analysis_collected_nframes += collect_signal_nframes;
388 assert(_signal_analysis_collected_nframes <= _signal_analysis_collect_nframes_max);
390 if (_signal_analysis_collected_nframes == _signal_analysis_collect_nframes_max) {
391 _signal_analysis_collect_nframes_max = 0;
392 _signal_analysis_collected_nframes = 0;
394 AnalysisDataGathered(&_signal_analysis_inputs,
395 &_signal_analysis_outputs);
398 /* leave remaining channel buffers alone */
402 PluginInsert::silence (framecnt_t nframes)
408 ChanMapping in_map(input_streams());
409 ChanMapping out_map(output_streams());
412 /* fix the input mapping so that we have maps for each of the plugin's inputs */
413 in_map = ChanMapping (natural_input_streams ());
416 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
417 (*i)->connect_and_run (_session.get_silent_buffers ((*i)->get_info()->n_inputs), in_map, out_map, nframes, 0);
422 PluginInsert::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, pframes_t nframes, bool)
424 if (_pending_active) {
425 /* run as normal if we are active or moving from inactive to active */
427 if (_session.transport_rolling()) {
428 automation_run (bufs, nframes);
430 connect_and_run (bufs, nframes, 0, false);
435 if (has_no_audio_inputs()) {
437 /* silence all (audio) outputs. Should really declick
438 * at the transitions of "active"
441 uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio();
443 for (uint32_t n = 0; n < out; ++n) {
444 bufs.get_audio (n).silence (nframes);
447 bufs.count().set_audio (out);
451 /* does this need to be done with MIDI? it appears not */
453 uint32_t in = _plugins[0]->get_info()->n_inputs.n_audio();
454 uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio();
458 /* not active, but something has make up for any channel count increase */
460 for (uint32_t n = out - in; n < out; ++n) {
461 memcpy (bufs.get_audio(n).data(), bufs.get_audio(in - 1).data(), sizeof (Sample) * nframes);
465 bufs.count().set_audio (out);
469 _active = _pending_active;
473 PluginInsert::set_parameter (Evoral::Parameter param, float val)
475 if (param.type() != PluginAutomation) {
479 /* the others will be set from the event triggered by this */
481 _plugins[0]->set_parameter (param.id(), val);
483 boost::shared_ptr<AutomationControl> ac
484 = boost::dynamic_pointer_cast<AutomationControl>(control(param));
489 warning << "set_parameter called for nonexistant parameter "
490 << EventTypeMap::instance().to_symbol(param) << endmsg;
493 _session.set_dirty();
497 PluginInsert::get_parameter (Evoral::Parameter param)
499 if (param.type() != PluginAutomation) {
502 assert (!_plugins.empty ());
503 return _plugins[0]->get_parameter (param.id());
508 PluginInsert::automation_run (BufferSet& bufs, pframes_t nframes)
510 Evoral::ControlEvent next_event (0, 0.0f);
511 framepos_t now = _session.transport_frame ();
512 framepos_t end = now + nframes;
513 framecnt_t offset = 0;
515 Glib::Mutex::Lock lm (control_lock(), Glib::TRY_LOCK);
518 connect_and_run (bufs, nframes, offset, false);
522 if (!find_next_event (now, end, next_event) || requires_fixed_sized_buffers()) {
524 /* no events have a time within the relevant range */
526 connect_and_run (bufs, nframes, offset, true, now);
532 framecnt_t cnt = min (((framecnt_t) ceil (next_event.when) - now), (framecnt_t) nframes);
534 connect_and_run (bufs, cnt, offset, true, now);
540 if (!find_next_event (now, end, next_event)) {
545 /* cleanup anything that is left to do */
548 connect_and_run (bufs, nframes, offset, true, now);
553 PluginInsert::default_parameter_value (const Evoral::Parameter& param)
555 if (param.type() != PluginAutomation)
558 if (_plugins.empty()) {
559 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
564 return _plugins[0]->default_value (param.id());
567 boost::shared_ptr<Plugin>
568 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
570 boost::shared_ptr<LadspaPlugin> lp;
572 boost::shared_ptr<LV2Plugin> lv2p;
575 boost::shared_ptr<VSTPlugin> vp;
578 boost::shared_ptr<LXVSTPlugin> lxvp;
580 #ifdef HAVE_AUDIOUNITS
581 boost::shared_ptr<AUPlugin> ap;
584 if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
585 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
587 } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
588 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
591 } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
592 return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
595 } else if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (other)) != 0) {
596 return boost::shared_ptr<Plugin> (new LXVSTPlugin (*lxvp));
598 #ifdef HAVE_AUDIOUNITS
599 } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
600 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
604 fatal << string_compose (_("programming error: %1"),
605 X_("unknown plugin type in PluginInsert::plugin_factory"))
608 return boost::shared_ptr<Plugin> ((Plugin*) 0);
612 PluginInsert::configure_io (ChanCount in, ChanCount out)
614 if (set_count (count_for_configuration (in, out)) == false) {
615 set_splitting (false);
619 if (_plugins.front()->get_info()->n_inputs <= in) {
620 set_splitting (false);
621 if (_plugins.front()->configure_io (in, out) == false) {
625 /* we must be splitting a single processor input to
626 multiple plugin inputs
628 set_splitting (true);
629 _plugins.front()->configure_io (_plugins.front()->get_info()->n_inputs, out);
632 // we don't know the analysis window size, so we must work with the
633 // current buffer size here. each request for data fills in these
634 // buffers and the analyser makes sure it gets enough data for the
636 session().ensure_buffer_set (_signal_analysis_inputs, in);
637 //_signal_analysis_inputs.set_count (in);
639 session().ensure_buffer_set (_signal_analysis_outputs, out);
640 //_signal_analysis_outputs.set_count (out);
642 // std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
644 return Processor::configure_io (in, out);
648 PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
650 // Plugin has flexible I/O, so delegate to it
651 if (_plugins.front()->reconfigurable_io()) {
652 return _plugins.front()->can_support_io_configuration (in, out);
655 ChanCount inputs = _plugins[0]->get_info()->n_inputs;
656 ChanCount outputs = _plugins[0]->get_info()->n_outputs;
658 bool no_inputs = true;
659 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
660 if (inputs.get (*t) != 0) {
667 /* no inputs so we can take any input configuration since we throw it away */
672 // Plugin inputs match requested inputs exactly
678 // See if replication is possible
679 // We allow replication only for plugins with either zero or 1 inputs and outputs
680 // for every valid data type.
682 bool can_replicate = true;
683 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
685 uint32_t nin = inputs.get (*t);
687 // No inputs of this type
688 if (nin == 0 && in.get(*t) == 0) {
692 if (nin != 1 || outputs.get (*t) != 1) {
693 can_replicate = false;
697 // Potential factor not set yet
700 f = in.get(*t) / nin;
703 // Factor for this type does not match another type, can not replicate
704 if (f != (in.get(*t) / nin)) {
705 can_replicate = false;
711 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
712 out.set (*t, outputs.get(*t) * f);
717 /* If the processor has exactly one input of a given type, and
718 the plugin has more, we can feed the single processor input
719 to some or all of the plugin inputs. This is rather
720 special-case-y, but the 1-to-many case is by far the
721 simplest. How do I split thy 2 processor inputs to 3
722 plugin inputs? Let me count the ways ...
725 bool can_split = true;
726 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
728 bool const can_split_type = (in.get (*t) == 1 && inputs.get (*t) > 1);
729 bool const nothing_to_do_for_type = (in.get (*t) == 0 && inputs.get (*t) == 0);
731 if (!can_split_type && !nothing_to_do_for_type) {
744 /* Number of plugin instances required to support a given channel configuration.
748 PluginInsert::count_for_configuration (ChanCount in, ChanCount /*out*/) const
750 if (_plugins.front()->reconfigurable_io()) {
751 /* plugin has flexible I/O, so the answer is always 1 */
752 /* this could change if we ever decide to replicate AU's */
756 // FIXME: take 'out' into consideration
758 ChanCount outputs = _plugins[0]->get_info()->n_outputs;
759 ChanCount inputs = _plugins[0]->get_info()->n_inputs;
761 if (inputs.n_total() == 0) {
762 /* instrument plugin, always legal, but throws away any existing streams */
766 if (inputs.n_total() == 1 && outputs == inputs
767 && ((inputs.n_audio() == 0 && in.n_audio() == 0)
768 || (inputs.n_midi() == 0 && in.n_midi() == 0))) {
769 /* mono plugin, replicate as needed to match in */
779 /* more plugin inputs than processor inputs, so we are splitting */
783 // assumes in is valid, so we must be replicating
784 if (inputs.n_total() < in.n_total()
785 && (in.n_total() % inputs.n_total() == 0)) {
787 return in.n_total() / inputs.n_total();
795 PluginInsert::get_state(void)
801 PluginInsert::state (bool full)
803 XMLNode& node = Processor::state (full);
805 node.add_property("type", _plugins[0]->state_node_name());
806 node.add_property("unique-id", _plugins[0]->unique_id());
807 node.add_property("count", string_compose("%1", _plugins.size()));
808 node.add_child_nocopy (_plugins[0]->get_state());
810 for (Controls::iterator c = controls().begin(); c != controls().end(); ++c) {
811 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> ((*c).second);
813 node.add_child_nocopy (ac->get_state());
821 PluginInsert::set_control_ids (const XMLNode& node, int version)
823 const XMLNodeList& nlist = node.children();
824 XMLNodeConstIterator iter;
825 set<Evoral::Parameter>::const_iterator p;
827 for (iter = nlist.begin(); iter != nlist.end(); ++iter) {
828 if ((*iter)->name() == Controllable::xml_node_name) {
829 const XMLProperty* prop;
831 if ((prop = (*iter)->property (X_("parameter"))) != 0) {
832 uint32_t p = atoi (prop->value());
833 boost::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginAutomation, 0, p));
837 boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (c);
839 ac->set_state (**iter, version);
847 PluginInsert::set_state(const XMLNode& node, int version)
849 XMLNodeList nlist = node.children();
850 XMLNodeIterator niter;
851 XMLPropertyList plist;
852 const XMLProperty *prop;
853 ARDOUR::PluginType type;
855 if ((prop = node.property ("type")) == 0) {
856 error << _("XML node describing plugin is missing the `type' field") << endmsg;
860 if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
861 type = ARDOUR::LADSPA;
862 } else if (prop->value() == X_("lv2")) {
864 } else if (prop->value() == X_("vst")) {
866 } else if (prop->value() == X_("lxvst")) {
867 type = ARDOUR::LXVST;
868 } else if (prop->value() == X_("audiounit")) {
869 type = ARDOUR::AudioUnit;
871 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
877 prop = node.property ("unique-id");
881 /* older sessions contain VST plugins with only an "id" field.
884 if (type == ARDOUR::VST) {
885 prop = node.property ("id");
890 /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/
892 if (type == ARDOUR::LXVST) {
893 prop = node.property ("id");
899 error << _("Plugin has no unique ID field") << endmsg;
904 boost::shared_ptr<Plugin> plugin = find_plugin (_session, prop->value(), type);
907 error << string_compose(
908 _("Found a reference to a plugin (\"%1\") that is unknown.\n"
909 "Perhaps it was removed or moved since it was last used."),
915 // The name of the PluginInsert comes from the plugin, nothing else
916 _name = plugin->get_info()->name;
920 // Processor::set_state() will set this, but too late
921 // for it to be available when setting up plugin
922 // state. We can't call Processor::set_state() until
923 // the plugins themselves are created and added.
925 if ((prop = node.property ("id")) != 0) {
929 if (_plugins.empty()) {
930 /* if we are adding the first plugin, we will need to set
931 up automatable controls.
934 create_automatable_parameters ();
935 set_control_ids (node, version);
938 if ((prop = node.property ("count")) != 0) {
939 sscanf (prop->value().c_str(), "%u", &count);
942 if (_plugins.size() != count) {
943 for (uint32_t n = 1; n < count; ++n) {
944 add_plugin (plugin_factory (plugin));
948 Processor::set_state (node, version);
950 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
952 /* find the node with the type-specific node name ("lv2", "ladspa", etc)
953 and set all plugins to the same state.
956 if ((*niter)->name() == plugin->state_node_name()) {
958 plugin->set_state (**niter, version);
960 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
961 (*i)->set_state (**niter, version);
968 if (version < 3000) {
970 /* Only 2.X sessions need a call to set_parameter_state() - in 3.X and above
971 this is all handled by Automatable
974 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
975 if ((*niter)->name() == "Redirect") {
976 /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
977 Processor::set_state (**niter, version);
982 set_parameter_state_2X (node, version);
985 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
993 /* catch up on I/O */
996 Glib::Mutex::Lock em (_session.engine().process_lock());
997 IO::PortCountChanged (max(input_streams(), output_streams()));
1004 PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
1006 XMLNodeList nlist = node.children();
1007 XMLNodeIterator niter;
1009 /* look for port automation node */
1011 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1013 if ((*niter)->name() != port_automation_node_name) {
1019 XMLNodeConstIterator iter;
1024 cnodes = (*niter)->children ("port");
1026 for (iter = cnodes.begin(); iter != cnodes.end(); ++iter){
1030 if ((cprop = child->property("number")) != 0) {
1031 port = cprop->value().c_str();
1033 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
1037 sscanf (port, "%" PRIu32, &port_id);
1039 if (port_id >= _plugins[0]->parameter_count()) {
1040 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
1044 boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
1045 control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
1048 if (!child->children().empty()) {
1049 c->alist()->set_state (*child->children().front(), version);
1051 /* In some cases 2.X saves lists with min_yval and max_yval
1052 being FLT_MIN and FLT_MAX respectively. This causes problems
1053 in A3 because these min/max values are used to compute
1054 where GUI control points should be drawn. If we see such
1055 values, `correct' them to the min/max of the appropriate
1059 float min_y = c->alist()->get_min_y ();
1060 float max_y = c->alist()->get_max_y ();
1062 Plugin::ParameterDescriptor desc;
1063 _plugins.front()->get_parameter_descriptor (port_id, desc);
1065 if (min_y == FLT_MIN) {
1069 if (max_y == FLT_MAX) {
1073 c->alist()->set_yrange (min_y, max_y);
1076 error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
1088 PluginInsert::describe_parameter (Evoral::Parameter param)
1090 if (param.type() != PluginAutomation) {
1091 return Automatable::describe_parameter(param);
1094 return _plugins[0]->describe_parameter (param);
1098 PluginInsert::signal_latency() const
1100 if (_user_latency) {
1101 return _user_latency;
1104 return _plugins[0]->signal_latency ();
1108 PluginInsert::type ()
1110 return plugin()->get_info()->type;
1113 PluginInsert::PluginControl::PluginControl (PluginInsert* p, const Evoral::Parameter ¶m, boost::shared_ptr<AutomationList> list)
1114 : AutomationControl (p->session(), param, list, p->describe_parameter(param))
1117 Plugin::ParameterDescriptor desc;
1118 p->plugin(0)->get_parameter_descriptor (param.id(), desc);
1119 _logarithmic = desc.logarithmic;
1120 _sr_dependent = desc.sr_dependent;
1121 _toggled = desc.toggled;
1124 /** @param val `user' value */
1126 PluginInsert::PluginControl::set_value (double user_val)
1128 /* FIXME: probably should be taking out some lock here.. */
1130 double const plugin_val = user_to_plugin (user_val);
1132 for (Plugins::iterator i = _plugin->_plugins.begin(); i != _plugin->_plugins.end(); ++i) {
1133 (*i)->set_parameter (_list->parameter().id(), plugin_val);
1136 boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
1138 iasp->set_parameter (_list->parameter().id(), plugin_val);
1141 AutomationControl::set_value (user_val);
1145 PluginInsert::PluginControl::user_to_plugin (double val) const
1147 /* no known transformations at this time */
1152 PluginInsert::PluginControl::user_to_ui (double val) const
1166 PluginInsert::PluginControl::ui_to_user (double val) const
1175 /** Convert plugin values to UI values. See pbd/controllable.h */
1177 PluginInsert::PluginControl::plugin_to_ui (double val) const
1179 return user_to_ui (plugin_to_user (val));
1183 PluginInsert::PluginControl::plugin_to_user (double val) const
1185 /* no known transformations at this time */
1190 PluginInsert::PluginControl::get_state ()
1194 XMLNode& node (AutomationControl::get_state());
1195 ss << parameter().id();
1196 node.add_property (X_("parameter"), ss.str());
1201 /** @return `user' val */
1203 PluginInsert::PluginControl::get_value () const
1205 /* FIXME: probably should be taking out some lock here.. */
1207 return plugin_to_user (_plugin->get_parameter (_list->parameter()));
1210 boost::shared_ptr<Plugin>
1211 PluginInsert::get_impulse_analysis_plugin()
1213 boost::shared_ptr<Plugin> ret;
1214 if (_impulseAnalysisPlugin.expired()) {
1215 ret = plugin_factory(_plugins[0]);
1216 _impulseAnalysisPlugin = ret;
1218 ret = _impulseAnalysisPlugin.lock();
1225 PluginInsert::collect_signal_for_analysis (framecnt_t nframes)
1227 // called from outside the audio thread, so this should be safe
1228 // only do audio as analysis is (currently) only for audio plugins
1229 _signal_analysis_inputs.ensure_buffers( DataType::AUDIO, input_streams().n_audio(), nframes);
1230 _signal_analysis_outputs.ensure_buffers( DataType::AUDIO, output_streams().n_audio(), nframes);
1232 _signal_analysis_collected_nframes = 0;
1233 _signal_analysis_collect_nframes_max = nframes;
1236 /** Add a plugin to our list and activate it if we have already been activated */
1238 PluginInsert::add_plugin_with_activation (boost::shared_ptr<Plugin> plugin)
1240 plugin->set_insert_info (this);
1241 _plugins.push_back (plugin);
1243 plugin->activate ();
1247 /** Add a plugin to our list */
1249 PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
1251 plugin->set_insert_info (this);
1252 _plugins.push_back (plugin);
1256 PluginInsert::realtime_handle_transport_stopped ()
1258 for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
1259 (*i)->realtime_handle_transport_stopped ();
1264 PluginInsert::set_splitting (bool s)
1266 if (_splitting == s) {
1271 SplittingChanged (); /* EMIT SIGNAL */