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"
27 #include "pbd/failed_constructor.h"
28 #include "pbd/xml++.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"
48 #ifdef HAVE_AUDIOUNITS
49 #include "ardour/audio_unit.h"
52 #include "ardour/audioengine.h"
53 #include "ardour/session.h"
54 #include "ardour/types.h"
59 using namespace ARDOUR
;
62 const string
PluginInsert::port_automation_node_name
= "PortAutomation";
64 PluginInsert::PluginInsert (Session
& s
, boost::shared_ptr
<Plugin
> plug
)
65 : Processor (s
, (plug
? plug
->name() : string ("toBeRenamed")))
66 , _signal_analysis_collected_nframes(0)
67 , _signal_analysis_collect_nframes_max(0)
69 /* the first is the master */
72 _plugins
.push_back (plug
);
75 Glib::Mutex::Lock
em (_session
.engine().process_lock());
76 IO::PortCountChanged (max(input_streams(), output_streams()));
81 PluginInsert::set_count (uint32_t num
)
83 bool require_state
= !_plugins
.empty();
85 /* this is a bad idea.... we shouldn't do this while active.
86 only a route holding their redirect_lock should be calling this
91 } else if (num
> _plugins
.size()) {
92 uint32_t diff
= num
- _plugins
.size();
94 for (uint32_t n
= 0; n
< diff
; ++n
) {
95 _plugins
.push_back (plugin_factory (_plugins
[0]));
98 /* XXX do something */
102 } else if (num
< _plugins
.size()) {
103 uint32_t diff
= _plugins
.size() - num
;
104 for (uint32_t n
= 0; n
< diff
; ++n
) {
112 PluginInsert::~PluginInsert ()
117 PluginInsert::auto_state_changed (Evoral::Parameter which
)
119 if (which
.type() != PluginAutomation
)
122 boost::shared_ptr
<AutomationControl
> c
123 = boost::dynamic_pointer_cast
<AutomationControl
>(control (which
));
125 if (c
&& ((AutomationList
*)c
->list().get())->automation_state() != Off
) {
126 _plugins
[0]->set_parameter (which
.id(), c
->list()->eval (_session
.transport_frame()));
131 PluginInsert::output_streams() const
133 ChanCount out
= _plugins
.front()->get_info()->n_outputs
;
135 if (out
== ChanCount::INFINITE
) {
136 return _plugins
.front()->output_streams ();
138 out
.set_audio (out
.n_audio() * _plugins
.size());
139 out
.set_midi (out
.n_midi() * _plugins
.size());
145 PluginInsert::input_streams() const
147 ChanCount in
= _plugins
[0]->get_info()->n_inputs
;
149 if (in
== ChanCount::INFINITE
) {
150 return _plugins
[0]->input_streams ();
152 in
.set_audio (in
.n_audio() * _plugins
.size());
153 in
.set_midi (in
.n_midi() * _plugins
.size());
159 PluginInsert::natural_output_streams() const
161 return _plugins
[0]->get_info()->n_outputs
;
165 PluginInsert::natural_input_streams() const
167 return _plugins
[0]->get_info()->n_inputs
;
171 PluginInsert::is_generator() const
173 /* XXX more finesse is possible here. VST plugins have a
174 a specific "instrument" flag, for example.
177 return _plugins
[0]->get_info()->n_inputs
.n_audio() == 0;
181 PluginInsert::set_automatable ()
183 set
<Evoral::Parameter
> a
= _plugins
.front()->automatable ();
185 Plugin::ParameterDescriptor desc
;
187 for (set
<Evoral::Parameter
>::iterator i
= a
.begin(); i
!= a
.end(); ++i
) {
188 if (i
->type() == PluginAutomation
) {
190 Evoral::Parameter
param(*i
);
192 _plugins
.front()->get_parameter_descriptor(i
->id(), desc
);
194 /* the Parameter belonging to the actual plugin doesn't have its range set
195 but we want the Controllable related to this Parameter to have those limits.
198 param
.set_range (desc
.lower
, desc
.upper
, _plugins
.front()->default_value(i
->id()));
199 can_automate (param
);
200 boost::shared_ptr
<AutomationList
> list(new AutomationList(param
));
201 add_control (boost::shared_ptr
<AutomationControl
>(new PluginControl(this, param
, list
)));
207 PluginInsert::parameter_changed (Evoral::Parameter which
, float val
)
209 if (which
.type() != PluginAutomation
)
212 Plugins::iterator i
= _plugins
.begin();
214 /* don't set the first plugin, just all the slaves */
216 if (i
!= _plugins
.end()) {
218 for (; i
!= _plugins
.end(); ++i
) {
219 (*i
)->set_parameter (which
, val
);
225 PluginInsert::set_block_size (nframes_t nframes
)
227 for (Plugins::iterator i
= _plugins
.begin(); i
!= _plugins
.end(); ++i
) {
228 (*i
)->set_block_size (nframes
);
233 PluginInsert::activate ()
235 Processor::activate ();
237 for (Plugins::iterator i
= _plugins
.begin(); i
!= _plugins
.end(); ++i
) {
243 PluginInsert::deactivate ()
245 Processor::deactivate ();
247 for (Plugins::iterator i
= _plugins
.begin(); i
!= _plugins
.end(); ++i
) {
253 PluginInsert::connect_and_run (BufferSet
& bufs
, nframes_t nframes
, nframes_t offset
, bool with_auto
, nframes_t now
)
255 // Calculate if, and how many frames we need to collect for analysis
256 nframes_t collect_signal_nframes
= (_signal_analysis_collect_nframes_max
-
257 _signal_analysis_collected_nframes
);
258 if (nframes
< collect_signal_nframes
) { // we might not get all frames now
259 collect_signal_nframes
= nframes
;
262 ChanMapping
in_map(input_streams());
263 ChanMapping
out_map(output_streams());
265 /* Note that we've already required that plugins
266 be able to handle in-place processing.
273 for (Controls::iterator li
= controls().begin(); li
!= controls().end(); ++li
, ++n
) {
275 boost::shared_ptr
<AutomationControl
> c
276 = boost::dynamic_pointer_cast
<AutomationControl
>(li
->second
);
278 if (c
->parameter().type() == PluginAutomation
&& c
->automation_playback()) {
281 const float val
= c
->list()->rt_safe_eval (now
, valid
);
291 if (collect_signal_nframes
> 0) {
293 //std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
294 //std::cerr << " streams " << input_streams().n_audio() << std::endl;
295 //std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
297 _signal_analysis_inputs
.set_count(input_streams());
299 for (uint32_t i
= 0; i
< input_streams().n_audio(); ++i
) {
300 _signal_analysis_inputs
.get_audio(i
).read_from(
302 collect_signal_nframes
,
303 _signal_analysis_collected_nframes
); // offset is for target buffer
308 for (Plugins::iterator i
= _plugins
.begin(); i
!= _plugins
.end(); ++i
) {
309 (*i
)->connect_and_run(bufs
, in_map
, out_map
, nframes
, offset
);
310 for (DataType::iterator t
= DataType::begin(); t
!= DataType::end(); ++t
) {
311 in_map
.offset_to(*t
, natural_input_streams().get(*t
));
312 out_map
.offset_to(*t
, natural_output_streams().get(*t
));
316 if (collect_signal_nframes
> 0) {
318 //std::cerr << " output, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
319 //std::cerr << " streams " << output_streams().n_audio() << std::endl;
321 _signal_analysis_outputs
.set_count(output_streams());
323 for (uint32_t i
= 0; i
< output_streams().n_audio(); ++i
) {
324 _signal_analysis_outputs
.get_audio(i
).read_from(
326 collect_signal_nframes
,
327 _signal_analysis_collected_nframes
); // offset is for target buffer
330 _signal_analysis_collected_nframes
+= collect_signal_nframes
;
331 assert(_signal_analysis_collected_nframes
<= _signal_analysis_collect_nframes_max
);
333 if (_signal_analysis_collected_nframes
== _signal_analysis_collect_nframes_max
) {
334 _signal_analysis_collect_nframes_max
= 0;
335 _signal_analysis_collected_nframes
= 0;
337 AnalysisDataGathered(&_signal_analysis_inputs
,
338 &_signal_analysis_outputs
);
341 /* leave remaining channel buffers alone */
345 PluginInsert::silence (nframes_t nframes
)
347 ChanMapping
in_map(input_streams());
348 ChanMapping
out_map(output_streams());
351 for (Plugins::iterator i
= _plugins
.begin(); i
!= _plugins
.end(); ++i
) {
352 (*i
)->connect_and_run (_session
.get_silent_buffers ((*i
)->get_info()->n_inputs
), in_map
, out_map
, nframes
, 0);
358 PluginInsert::run (BufferSet
& bufs
, sframes_t
/*start_frame*/, sframes_t
/*end_frame*/, nframes_t nframes
, bool)
360 if (_active
|| _pending_active
) {
362 if (_session
.transport_rolling()) {
363 automation_run (bufs
, nframes
);
365 connect_and_run (bufs
, nframes
, 0, false);
370 /* FIXME: type, audio only */
372 uint32_t in
= _plugins
[0]->get_info()->n_inputs
.n_audio();
373 uint32_t out
= _plugins
[0]->get_info()->n_outputs
.n_audio();
377 /* not active, but something has make up for any channel count increase */
379 for (uint32_t n
= out
- in
; n
< out
; ++n
) {
380 memcpy (bufs
.get_audio(n
).data(), bufs
.get_audio(in
- 1).data(), sizeof (Sample
) * nframes
);
384 bufs
.count().set_audio(out
);
387 _active
= _pending_active
;
391 PluginInsert::set_parameter (Evoral::Parameter param
, float val
)
393 if (param
.type() != PluginAutomation
)
396 /* the others will be set from the event triggered by this */
398 _plugins
[0]->set_parameter (param
.id(), val
);
400 boost::shared_ptr
<AutomationControl
> ac
401 = boost::dynamic_pointer_cast
<AutomationControl
>(control(param
));
406 warning
<< "set_parameter called for nonexistant parameter "
407 << EventTypeMap::instance().to_symbol(param
) << endmsg
;
410 _session
.set_dirty();
414 PluginInsert::get_parameter (Evoral::Parameter param
)
416 if (param
.type() != PluginAutomation
) {
419 assert (!_plugins
.empty ());
420 return _plugins
[0]->get_parameter (param
.id());
425 PluginInsert::automation_run (BufferSet
& bufs
, nframes_t nframes
)
427 Evoral::ControlEvent
next_event (0, 0.0f
);
428 nframes_t now
= _session
.transport_frame ();
429 nframes_t end
= now
+ nframes
;
430 nframes_t offset
= 0;
432 Glib::Mutex::Lock
lm (control_lock(), Glib::TRY_LOCK
);
435 connect_and_run (bufs
, nframes
, offset
, false);
439 if (!find_next_event (now
, end
, next_event
)) {
441 /* no events have a time within the relevant range */
443 connect_and_run (bufs
, nframes
, offset
, true, now
);
449 nframes_t cnt
= min (((nframes_t
) ceil (next_event
.when
) - now
), nframes
);
451 connect_and_run (bufs
, cnt
, offset
, true, now
);
457 if (!find_next_event (now
, end
, next_event
)) {
462 /* cleanup anything that is left to do */
465 connect_and_run (bufs
, nframes
, offset
, true, now
);
470 PluginInsert::default_parameter_value (const Evoral::Parameter
& param
)
472 if (param
.type() != PluginAutomation
)
475 if (_plugins
.empty()) {
476 fatal
<< _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
481 return _plugins
[0]->default_value (param
.id());
484 boost::shared_ptr
<Plugin
>
485 PluginInsert::plugin_factory (boost::shared_ptr
<Plugin
> other
)
487 boost::shared_ptr
<LadspaPlugin
> lp
;
489 boost::shared_ptr
<LV2Plugin
> lv2p
;
492 boost::shared_ptr
<VSTPlugin
> vp
;
494 #ifdef HAVE_AUDIOUNITS
495 boost::shared_ptr
<AUPlugin
> ap
;
498 if ((lp
= boost::dynamic_pointer_cast
<LadspaPlugin
> (other
)) != 0) {
499 return boost::shared_ptr
<Plugin
> (new LadspaPlugin (*lp
));
501 } else if ((lv2p
= boost::dynamic_pointer_cast
<LV2Plugin
> (other
)) != 0) {
502 return boost::shared_ptr
<Plugin
> (new LV2Plugin (*lv2p
));
505 } else if ((vp
= boost::dynamic_pointer_cast
<VSTPlugin
> (other
)) != 0) {
506 return boost::shared_ptr
<Plugin
> (new VSTPlugin (*vp
));
508 #ifdef HAVE_AUDIOUNITS
509 } else if ((ap
= boost::dynamic_pointer_cast
<AUPlugin
> (other
)) != 0) {
510 return boost::shared_ptr
<Plugin
> (new AUPlugin (*ap
));
514 fatal
<< string_compose (_("programming error: %1"),
515 X_("unknown plugin type in PluginInsert::plugin_factory"))
518 return boost::shared_ptr
<Plugin
> ((Plugin
*) 0);
522 PluginInsert::configure_io (ChanCount in
, ChanCount out
)
524 if (set_count (count_for_configuration (in
, out
)) < 0) {
528 /* if we're running replicated plugins, each plugin has
529 the same i/o configuration and we may need to announce how many
530 output streams there are.
532 if we running a single plugin, we need to configure it.
535 if (_plugins
.front()->configure_io (in
, out
) < 0) {
539 // we don't know the analysis window size, so we must work with the
540 // current buffer size here. each request for data fills in these
541 // buffers and the analyser makes sure it gets enough data for the
543 session().ensure_buffer_set (_signal_analysis_inputs
, in
);
544 //_signal_analysis_inputs.set_count (in);
546 session().ensure_buffer_set (_signal_analysis_outputs
, out
);
547 //_signal_analysis_outputs.set_count (out);
549 // std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
551 return Processor::configure_io (in
, out
);
555 PluginInsert::can_support_io_configuration (const ChanCount
& in
, ChanCount
& out
) const
557 // Plugin has flexible I/O, so delegate to it
558 if (_plugins
.front()->reconfigurable_io()) {
559 return _plugins
.front()->can_support_io_configuration (in
, out
);
562 ChanCount inputs
= _plugins
[0]->get_info()->n_inputs
;
563 ChanCount outputs
= _plugins
[0]->get_info()->n_outputs
;
565 // Plugin inputs match requested inputs exactly
571 // See if replication is possible
572 // We can replicate if there exists a single factor f such that, for every type,
573 // the number of plugin inputs * f = the requested number of inputs
575 bool can_replicate
= true;
576 for (DataType::iterator t
= DataType::begin(); t
!= DataType::end(); ++t
) {
577 // No inputs of this type
578 if (inputs
.get(*t
) == 0 && in
.get(*t
) == 0) {
581 // Plugin has more inputs than requested, can not replicate
582 } else if (inputs
.get(*t
) >= in
.get(*t
)) {
583 can_replicate
= false;
586 // Plugin inputs is not a factor of requested inputs, can not replicate
587 } else if (inputs
.get(*t
) == 0 || in
.get(*t
) % inputs
.get(*t
) != 0) {
588 can_replicate
= false;
591 // Potential factor not set yet
593 f
= in
.get(*t
) / inputs
.get(*t
);;
596 // Factor for this type does not match another type, can not replicate
597 if (f
!= (in
.get(*t
) / inputs
.get(*t
))) {
598 can_replicate
= false;
604 for (DataType::iterator t
= DataType::begin(); t
!= DataType::end(); ++t
) {
605 out
.set (*t
, outputs
.get(*t
) * f
);
613 /* Number of plugin instances required to support a given channel configuration.
617 PluginInsert::count_for_configuration (ChanCount in
, ChanCount
/*out*/) const
619 if (_plugins
.front()->reconfigurable_io()) {
620 /* plugin has flexible I/O, so the answer is always 1 */
621 /* this could change if we ever decide to replicate AU's */
625 // FIXME: take 'out' into consideration
627 ChanCount outputs
= _plugins
[0]->get_info()->n_outputs
;
628 ChanCount inputs
= _plugins
[0]->get_info()->n_inputs
;
630 if (inputs
.n_total() == 0) {
631 /* instrument plugin, always legal, but throws away any existing streams */
635 if (inputs
.n_total() == 1 && outputs
== inputs
636 && ((inputs
.n_audio() == 0 && in
.n_audio() == 0)
637 || (inputs
.n_midi() == 0 && in
.n_midi() == 0))) {
638 /* mono plugin, replicate as needed to match in */
647 // assumes in is valid, so we must be replicating
648 if (inputs
.n_total() < in
.n_total()
649 && (in
.n_total() % inputs
.n_total() == 0)) {
651 return in
.n_total() / inputs
.n_total();
659 PluginInsert::get_state(void)
665 PluginInsert::state (bool full
)
667 XMLNode
& node
= Processor::state (full
);
669 node
.add_property("type", _plugins
[0]->state_node_name());
670 node
.add_property("unique-id", _plugins
[0]->unique_id());
671 node
.add_property("count", string_compose("%1", _plugins
.size()));
672 node
.add_child_nocopy (_plugins
[0]->get_state());
674 /* add port automation state */
675 XMLNode
*autonode
= new XMLNode(port_automation_node_name
);
676 set
<Evoral::Parameter
> automatable
= _plugins
[0]->automatable();
678 for (set
<Evoral::Parameter
>::iterator x
= automatable
.begin(); x
!= automatable
.end(); ++x
) {
680 /*XMLNode* child = new XMLNode("port");
681 snprintf(buf, sizeof(buf), "%" PRIu32, *x);
682 child->add_property("number", string(buf));
684 child->add_child_nocopy (automation_list (*x).state (full));
685 autonode->add_child_nocopy (*child);
687 AutomationList
* list
= dynamic_cast<AutomationList
*>(control(*x
)->list().get());
688 autonode
->add_child_nocopy (list
->state (full
));
691 node
.add_child_nocopy (*autonode
);
697 PluginInsert::set_state(const XMLNode
& node
, int version
)
699 XMLNodeList nlist
= node
.children();
700 XMLNodeIterator niter
;
701 XMLPropertyList plist
;
702 const XMLProperty
*prop
;
703 ARDOUR::PluginType type
;
705 if ((prop
= node
.property ("type")) == 0) {
706 error
<< _("XML node describing plugin is missing the `type' field") << endmsg
;
710 if (prop
->value() == X_("ladspa") || prop
->value() == X_("Ladspa")) { /* handle old school sessions */
711 type
= ARDOUR::LADSPA
;
712 } else if (prop
->value() == X_("lv2")) {
714 } else if (prop
->value() == X_("vst")) {
716 } else if (prop
->value() == X_("audiounit")) {
717 type
= ARDOUR::AudioUnit
;
719 error
<< string_compose (_("unknown plugin type %1 in plugin insert state"),
725 prop
= node
.property ("unique-id");
729 /* older sessions contain VST plugins with only an "id" field.
732 if (type
== ARDOUR::VST
) {
733 prop
= node
.property ("id");
739 error
<< _("Plugin has no unique ID field") << endmsg
;
744 boost::shared_ptr
<Plugin
> plugin
;
746 plugin
= find_plugin (_session
, prop
->value(), type
);
749 error
<< string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
750 "Perhaps it was removed or moved since it was last used."), prop
->value())
756 bool need_automatables
= true;
758 if (_plugins
.empty()) {
759 /* if we are adding the first plugin, we will need to set
760 up automatable controls.
762 need_automatables
= true;
765 if ((prop
= node
.property ("count")) != 0) {
766 sscanf (prop
->value().c_str(), "%u", &count
);
769 if (_plugins
.size() != count
) {
771 _plugins
.push_back (plugin
);
773 for (uint32_t n
= 1; n
< count
; ++n
) {
774 _plugins
.push_back (plugin_factory (plugin
));
778 if (need_automatables
) {
782 /* Handle the node list for this Processor (or Insert if an A2 session) */
783 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
785 if ((*niter
)->name() == plugin
->state_node_name()) {
787 for (Plugins::iterator i
= _plugins
.begin(); i
!= _plugins
.end(); ++i
) {
788 (*i
)->set_state (**niter
, version
);
794 Processor::set_state (node
, version
);
796 if (version
< 3000) {
798 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
799 if ((*niter
)->name() == "Redirect") {
800 /* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
801 Processor::set_state (**niter
, version
);
806 set_parameter_state_2X (node
, version
);
810 set_parameter_state (node
, version
);
813 // The name of the PluginInsert comes from the plugin, nothing else
814 _name
= plugin
->get_info()->name
;
816 /* catch up on I/O */
819 Glib::Mutex::Lock
em (_session
.engine().process_lock());
820 IO::PortCountChanged (max(input_streams(), output_streams()));
827 PluginInsert::set_parameter_state (const XMLNode
& node
, int version
)
829 XMLNodeList nlist
= node
.children();
830 XMLNodeIterator niter
;
832 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
834 if ((*niter
)->name() != port_automation_node_name
) {
840 XMLNodeConstIterator iter
;
845 cnodes
= (*niter
)->children ("AutomationList");
847 for (iter
= cnodes
.begin(); iter
!= cnodes
.end(); ++iter
) {
851 /* XXX this code knows way too much about the internal details of an AutomationList state node */
853 if ((cprop
= child
->property("automation-id")) != 0) {
854 port
= cprop
->value().c_str();
856 warning
<< _("PluginInsert: Auto: no plugin parameter number seen") << endmsg
;
860 if (sscanf (port
, "parameter-%" PRIu32
, &port_id
) != 1) {
861 warning
<< _("PluginInsert: Auto: no parameter number found") << endmsg
;
865 if (port_id
>= _plugins
[0]->parameter_count()) {
866 warning
<< _("PluginInsert: Auto: plugin parameter out of range") << endmsg
;
870 boost::shared_ptr
<AutomationControl
> c
= boost::dynamic_pointer_cast
<AutomationControl
>(
871 control(Evoral::Parameter(PluginAutomation
, 0, port_id
), true));
874 c
->alist()->set_state (*child
, version
);
876 error
<< string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id
) << endmsg
;
887 PluginInsert::set_parameter_state_2X (const XMLNode
& node
, int version
)
889 XMLNodeList nlist
= node
.children();
890 XMLNodeIterator niter
;
892 /* look for port automation node */
894 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
896 if ((*niter
)->name() != port_automation_node_name
) {
902 XMLNodeConstIterator iter
;
907 cnodes
= (*niter
)->children ("port");
909 for (iter
= cnodes
.begin(); iter
!= cnodes
.end(); ++iter
){
913 if ((cprop
= child
->property("number")) != 0) {
914 port
= cprop
->value().c_str();
916 warning
<< _("PluginInsert: Auto: no ladspa port number") << endmsg
;
920 sscanf (port
, "%" PRIu32
, &port_id
);
922 if (port_id
>= _plugins
[0]->parameter_count()) {
923 warning
<< _("PluginInsert: Auto: port id out of range") << endmsg
;
927 boost::shared_ptr
<AutomationControl
> c
= boost::dynamic_pointer_cast
<AutomationControl
>(
928 control(Evoral::Parameter(PluginAutomation
, 0, port_id
), true));
931 if (!child
->children().empty()) {
932 c
->alist()->set_state (*child
->children().front(), version
);
935 error
<< string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id
) << endmsg
;
947 PluginInsert::describe_parameter (Evoral::Parameter param
)
949 if (param
.type() != PluginAutomation
)
950 return Automatable::describe_parameter(param
);
952 return _plugins
[0]->describe_parameter (param
);
956 PluginInsert::signal_latency() const
959 return _user_latency
;
962 return _plugins
[0]->signal_latency ();
966 PluginInsert::type ()
968 return plugin()->get_info()->type
;
971 PluginInsert::PluginControl::PluginControl (PluginInsert
* p
, const Evoral::Parameter
¶m
, boost::shared_ptr
<AutomationList
> list
)
972 : AutomationControl (p
->session(), param
, list
, p
->describe_parameter(param
))
975 Plugin::ParameterDescriptor desc
;
976 p
->plugin(0)->get_parameter_descriptor (param
.id(), desc
);
977 _logarithmic
= desc
.logarithmic
;
978 _toggled
= desc
.toggled
;
982 PluginInsert::PluginControl::set_value (float val
)
984 /* FIXME: probably should be taking out some lock here.. */
994 /*const float range = _list->get_max_y() - _list->get_min_y();
995 const float lower = _list->get_min_y();
998 val = lower + (range * val);
1000 float log_lower = 0.0f;
1002 log_lower = log(lower);
1005 val = exp(log_lower + log(range) * val);
1010 for (Plugins::iterator i
= _plugin
->_plugins
.begin();
1011 i
!= _plugin
->_plugins
.end(); ++i
) {
1012 (*i
)->set_parameter (_list
->parameter().id(), val
);
1015 boost::shared_ptr
<Plugin
> iasp
= _plugin
->_impulseAnalysisPlugin
.lock();
1017 iasp
->set_parameter (_list
->parameter().id(), val
);
1020 AutomationControl::set_value(val
);
1024 PluginInsert::PluginControl::get_value (void) const
1026 /* FIXME: probably should be taking out some lock here.. */
1028 float val
= _plugin
->get_parameter (_list
->parameter());
1042 return ((val - lower) / range);
1046 boost::shared_ptr
<Plugin
>
1047 PluginInsert::get_impulse_analysis_plugin()
1049 boost::shared_ptr
<Plugin
> ret
;
1050 if (_impulseAnalysisPlugin
.expired()) {
1051 ret
= plugin_factory(_plugins
[0]);
1052 _impulseAnalysisPlugin
= ret
;
1054 ret
= _impulseAnalysisPlugin
.lock();
1061 PluginInsert::collect_signal_for_analysis(nframes_t nframes
)
1063 // called from outside the audio thread, so this should be safe
1064 // only do audio as analysis is (currently) only for audio plugins
1065 _signal_analysis_inputs
.ensure_buffers( DataType::AUDIO
, input_streams().n_audio(), nframes
);
1066 _signal_analysis_outputs
.ensure_buffers( DataType::AUDIO
, output_streams().n_audio(), nframes
);
1068 _signal_analysis_collected_nframes
= 0;
1069 _signal_analysis_collect_nframes_max
= nframes
;