Rework Port class hierarchy a bit. Hopefully now simpler, and should
[ardour.git] / libs / ardour / plugin_insert.cc
1 /*
2     Copyright (C) 2000 Paul Davis 
3
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.
8
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.
13
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.
17
18 */
19
20 #include <string>
21
22 #include <sigc++/bind.h>
23
24 #include <pbd/failed_constructor.h>
25 #include <pbd/xml++.h>
26
27 #include <ardour/plugin_insert.h>
28 #include <ardour/plugin.h>
29 #include <ardour/port.h>
30 #include <ardour/route.h>
31 #include <ardour/ladspa_plugin.h>
32 #include <ardour/buffer_set.h>
33 #include <ardour/automation_list.h>
34 #include <ardour/audio_buffer.h>
35
36 #ifdef HAVE_SLV2
37 #include <ardour/lv2_plugin.h>
38 #endif
39
40 #ifdef VST_SUPPORT
41 #include <ardour/vst_plugin.h>
42 #endif
43
44 #ifdef HAVE_AUDIOUNITS
45 #include <ardour/audio_unit.h>
46 #endif
47
48 #include <ardour/audioengine.h>
49 #include <ardour/session.h>
50 #include <ardour/types.h>
51
52 #include "i18n.h"
53
54 using namespace std;
55 using namespace ARDOUR;
56 using namespace PBD;
57
58 const string PluginInsert::port_automation_node_name = "PortAutomation";
59
60 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placement placement)
61         : Processor (s, plug->name(), placement),
62           _signal_analysis_collected_nframes(0),
63           _signal_analysis_collect_nframes_max(0)
64 {
65         /* the first is the master */
66
67         _plugins.push_back (plug);
68
69         init ();
70
71         {
72                 Glib::Mutex::Lock em (_session.engine().process_lock());
73                 IO::PortCountChanged (max(input_streams(), output_streams()));
74         }
75
76         ProcessorCreated (this); /* EMIT SIGNAL */
77 }
78
79 PluginInsert::PluginInsert (Session& s, const XMLNode& node)
80         : Processor (s, "unnamed plugin insert", PreFader),
81           _signal_analysis_collected_nframes(0),
82           _signal_analysis_collect_nframes_max(0)
83 {
84         if (set_state (node)) {
85                 throw failed_constructor();
86         }
87
88         // XXX: This would dump all automation, which has already been loaded by
89         //      Processor. But this could also have been related to the Parameter change..
90         //      will look into this later.
91         //set_automatable ();
92
93         {
94                 Glib::Mutex::Lock em (_session.engine().process_lock());
95                 IO::PortCountChanged (max(input_streams(), output_streams()));
96         }
97 }
98
99 PluginInsert::PluginInsert (const PluginInsert& other)
100         : Processor (other._session, other._name, other.placement()),
101           _signal_analysis_collected_nframes(0),
102           _signal_analysis_collect_nframes_max(0)
103 {
104         uint32_t count = other._plugins.size();
105
106         /* make as many copies as requested */
107         for (uint32_t n = 0; n < count; ++n) {
108                 _plugins.push_back (plugin_factory (other.plugin (n)));
109         }
110
111         init ();
112
113         ProcessorCreated (this); /* EMIT SIGNAL */
114 }
115
116 bool
117 PluginInsert::set_count (uint32_t num)
118 {
119         bool require_state = !_plugins.empty();
120
121         /* this is a bad idea.... we shouldn't do this while active.
122            only a route holding their redirect_lock should be calling this 
123         */
124
125         if (num == 0) { 
126                 return false;
127         } else if (num > _plugins.size()) {
128                 uint32_t diff = num - _plugins.size();
129
130                 for (uint32_t n = 0; n < diff; ++n) {
131                         _plugins.push_back (plugin_factory (_plugins[0]));
132
133                         if (require_state) {
134                                 /* XXX do something */
135                         }
136                 }
137
138         } else if (num < _plugins.size()) {
139                 uint32_t diff = _plugins.size() - num;
140                 for (uint32_t n= 0; n < diff; ++n) {
141                         _plugins.pop_back();
142                 }
143         }
144
145         return true;
146 }
147
148 void
149 PluginInsert::init ()
150 {
151         set_automatable ();
152 }
153
154 PluginInsert::~PluginInsert ()
155 {
156         GoingAway (); /* EMIT SIGNAL */
157 }
158
159 void
160 PluginInsert::auto_state_changed (Evoral::Parameter which)
161 {
162         if (which.type() != PluginAutomation)
163                 return;
164
165         boost::shared_ptr<AutomationControl> c
166                         = boost::dynamic_pointer_cast<AutomationControl>(data().control (which));
167
168         if (c && ((AutomationList*)c->list().get())->automation_state() != Off) {
169                 _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
170         }
171 }
172
173 ChanCount
174 PluginInsert::output_streams() const
175 {
176         ChanCount out = _plugins.front()->get_info()->n_outputs;
177
178         if (out == ChanCount::INFINITE) {
179
180                 return _plugins.front()->output_streams ();
181
182         } else {
183
184                 out.set_audio (out.n_audio() * _plugins.size());
185                 out.set_midi (out.n_midi() * _plugins.size());
186
187                 return out;
188         }
189 }
190
191 ChanCount
192 PluginInsert::input_streams() const
193 {
194         ChanCount in = _plugins[0]->get_info()->n_inputs;
195         
196         if (in == ChanCount::INFINITE) {
197                 return _plugins[0]->input_streams ();
198         } else {
199                 in.set_audio (in.n_audio() * _plugins.size());
200                 in.set_midi (in.n_midi() * _plugins.size());
201
202                 return in;
203         }
204 }
205
206 ChanCount
207 PluginInsert::natural_output_streams() const
208 {
209         return _plugins[0]->get_info()->n_outputs;
210 }
211
212 ChanCount
213 PluginInsert::natural_input_streams() const
214 {
215         return _plugins[0]->get_info()->n_inputs;
216 }
217
218 bool
219 PluginInsert::is_generator() const
220 {
221         /* XXX more finesse is possible here. VST plugins have a
222            a specific "instrument" flag, for example.
223          */
224
225         return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
226 }
227
228 void
229 PluginInsert::set_automatable ()
230 {
231         set<Evoral::Parameter> a = _plugins.front()->automatable ();
232
233         Plugin::ParameterDescriptor desc;
234
235         for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
236                 if (i->type() == PluginAutomation) {
237                         can_automate (*i);
238                         _plugins.front()->get_parameter_descriptor(i->id(), desc);
239                         Evoral::Parameter param(*i);
240                         param.set_range(desc.lower, desc.upper, _plugins.front()->default_value(i->id()));
241                         boost::shared_ptr<AutomationList> list(new AutomationList(param));
242                         add_control(boost::shared_ptr<AutomationControl>(new PluginControl(this, *i, list)));
243                 }
244         }
245 }
246
247 void
248 PluginInsert::parameter_changed (Evoral::Parameter which, float val)
249 {
250         if (which.type() != PluginAutomation)
251                 return;
252
253         vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin();
254
255         /* don't set the first plugin, just all the slaves */
256
257         if (i != _plugins.end()) {
258                 ++i;
259                 for (; i != _plugins.end(); ++i) {
260                         (*i)->set_parameter (which, val);
261                 }
262         }
263 }
264
265 void
266 PluginInsert::set_block_size (nframes_t nframes)
267 {
268         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
269                 (*i)->set_block_size (nframes);
270         }
271 }
272
273 void
274 PluginInsert::activate ()
275 {
276         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
277                 (*i)->activate ();
278         }
279 }
280
281 void
282 PluginInsert::deactivate ()
283 {
284         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
285                 (*i)->deactivate ();
286         }
287 }
288
289 void
290 PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now)
291 {
292         // Calculate if, and how many frames we need to collect for analysis
293         nframes_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
294                                             _signal_analysis_collected_nframes);
295         if (nframes < collect_signal_nframes) { // we might not get all frames now
296                 collect_signal_nframes = nframes;
297         }
298
299         uint32_t in_index = 0;
300         uint32_t out_index = 0;
301
302         /* Note that we've already required that plugins
303            be able to handle in-place processing.
304         */
305
306         if (with_auto) {
307
308                 uint32_t n = 0;
309                 
310                 for (Controls::iterator li = data().controls().begin(); li != data().controls().end(); ++li, ++n) {
311                         
312                         boost::shared_ptr<AutomationControl> c
313                                 = boost::dynamic_pointer_cast<AutomationControl>(li->second);
314
315                         if (c->parameter().type() == PluginAutomation && c->automation_playback()) {
316                                 bool valid;
317
318                                 const float val = c->list()->rt_safe_eval (now, valid);                         
319
320                                 if (valid) {
321                                         c->set_value(val);
322                                 }
323
324                         } 
325                 }
326         }
327
328         if (collect_signal_nframes > 0) {
329                 // collect input
330                 //std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count,  " << bufs.available().n_audio() << " available" << std::endl;
331                 //std::cerr << "               streams " << input_streams().n_audio() << std::endl;
332                 //std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
333                 for (uint32_t i = 0; i < input_streams().n_audio(); ++i) {
334                         _signal_analysis_input_bufferset.get_audio(i).read_from(
335                                 bufs.get_audio(i),
336                                 collect_signal_nframes,
337                                 _signal_analysis_collected_nframes); // offset is for target buffer
338                 }
339         }
340
341         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
342                 (*i)->connect_and_run (bufs, in_index, out_index, nframes, offset);
343         }
344
345         if (collect_signal_nframes > 0) {
346                 // collect output
347                 //std::cerr << "       output, bufs " << bufs.count().n_audio() << " count,  " << bufs.available().n_audio() << " available" << std::endl;
348                 //std::cerr << "               streams " << output_streams().n_audio() << std::endl;
349                 for (uint32_t i = 0; i < output_streams().n_audio(); ++i) {
350                         _signal_analysis_output_bufferset.get_audio(i).read_from(
351                                 bufs.get_audio(i), 
352                                 collect_signal_nframes, 
353                                 _signal_analysis_collected_nframes); // offset is for target buffer
354                 }
355
356                 _signal_analysis_collected_nframes += collect_signal_nframes;
357                 assert(_signal_analysis_collected_nframes <= _signal_analysis_collect_nframes_max);
358
359                 if (_signal_analysis_collected_nframes == _signal_analysis_collect_nframes_max) {
360                         _signal_analysis_collect_nframes_max = 0;
361                         _signal_analysis_collected_nframes   = 0;
362
363                         AnalysisDataGathered(&_signal_analysis_input_bufferset, 
364                                              &_signal_analysis_output_bufferset);
365                 }
366         }
367         /* leave remaining channel buffers alone */
368 }
369
370 void
371 PluginInsert::silence (nframes_t nframes, nframes_t offset)
372 {
373         uint32_t in_index = 0;
374         uint32_t out_index = 0;
375
376         if (active()) {
377                 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
378                         (*i)->connect_and_run (_session.get_silent_buffers ((*i)->get_info()->n_inputs), in_index, out_index, nframes, offset);
379                 }
380         }
381 }
382         
383 void
384 PluginInsert::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
385 {
386         if (active()) {
387
388                 if (_session.transport_rolling()) {
389                         automation_run (bufs, nframes, offset);
390                 } else {
391                         connect_and_run (bufs, nframes, offset, false);
392                 }
393         } else {
394
395                 /* FIXME: type, audio only */
396
397                 uint32_t in = _plugins[0]->get_info()->n_inputs.n_audio();
398                 uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio();
399
400                 if (out > in) {
401
402                         /* not active, but something has make up for any channel count increase */
403                         
404                         for (uint32_t n = out - in; n < out; ++n) {
405                                 memcpy (bufs.get_audio(n).data(nframes, offset), bufs.get_audio(in - 1).data(nframes, offset), sizeof (Sample) * nframes);
406                         }
407                 }
408
409                 bufs.count().set_audio(out);
410         }
411 }
412
413 void
414 PluginInsert::set_parameter (Evoral::Parameter param, float val)
415 {
416         if (param.type() != PluginAutomation)
417                 return;
418
419         /* the others will be set from the event triggered by this */
420
421         _plugins[0]->set_parameter (param.id(), val);
422         
423         boost::shared_ptr<AutomationControl> ac
424                         = boost::dynamic_pointer_cast<AutomationControl>(data().control(param));
425         
426         if (ac) {
427                 ac->set_value(val);
428         } else {
429                 warning << "set_parameter called for nonexistant parameter "
430                         << EventTypeMap::instance().to_symbol(param) << endmsg;
431         }
432
433         _session.set_dirty();
434 }
435
436 float
437 PluginInsert::get_parameter (Evoral::Parameter param)
438 {
439         if (param.type() != PluginAutomation)
440                 return 0.0;
441         else
442                 return
443                 _plugins[0]->get_parameter (param.id());
444 }
445
446 void
447 PluginInsert::automation_run (BufferSet& bufs, nframes_t nframes, nframes_t offset)
448 {
449         Evoral::ControlEvent next_event (0, 0.0f);
450         nframes_t now = _session.transport_frame ();
451         nframes_t end = now + nframes;
452
453         Glib::Mutex::Lock lm (data().control_lock(), Glib::TRY_LOCK);
454
455         if (!lm.locked()) {
456                 connect_and_run (bufs, nframes, offset, false);
457                 return;
458         }
459         
460         if (!data().find_next_event (now, end, next_event)) {
461                 
462                 /* no events have a time within the relevant range */
463                 
464                 connect_and_run (bufs, nframes, offset, true, now);
465                 return;
466         }
467         
468         while (nframes) {
469
470                 nframes_t cnt = min (((nframes_t) ceil (next_event.when) - now), nframes);
471   
472                 connect_and_run (bufs, cnt, offset, true, now);
473                 
474                 nframes -= cnt;
475                 offset += cnt;
476                 now += cnt;
477
478                 if (!data().find_next_event (now, end, next_event)) {
479                         break;
480                 }
481         }
482   
483         /* cleanup anything that is left to do */
484   
485         if (nframes) {
486                 connect_and_run (bufs, nframes, offset, true, now);
487         }
488 }       
489
490 float
491 PluginInsert::default_parameter_value (const Evoral::Parameter& param)
492 {
493         if (param.type() != PluginAutomation)
494                 return 1.0;
495
496         if (_plugins.empty()) {
497                 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
498                       << endmsg;
499                 /*NOTREACHED*/
500         }
501
502         return _plugins[0]->default_value (param.id());
503 }
504
505 boost::shared_ptr<Plugin>
506 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
507 {
508         boost::shared_ptr<LadspaPlugin> lp;
509 #ifdef HAVE_SLV2
510         boost::shared_ptr<LV2Plugin> lv2p;
511 #endif
512 #ifdef VST_SUPPORT
513         boost::shared_ptr<VSTPlugin> vp;
514 #endif
515 #ifdef HAVE_AUDIOUNITS
516         boost::shared_ptr<AUPlugin> ap;
517 #endif
518
519         if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
520                 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
521 #ifdef HAVE_SLV2
522         } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
523                 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
524 #endif
525 #ifdef VST_SUPPORT
526         } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
527                 return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
528 #endif
529 #ifdef HAVE_AUDIOUNITS
530         } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
531                 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
532 #endif
533         }
534
535         fatal << string_compose (_("programming error: %1"),
536                           X_("unknown plugin type in PluginInsert::plugin_factory"))
537               << endmsg;
538         /*NOTREACHED*/
539         return boost::shared_ptr<Plugin> ((Plugin*) 0);
540 }
541
542 bool
543 PluginInsert::configure_io (ChanCount in, ChanCount out)
544 {
545         if (set_count (count_for_configuration (in, out)) < 0) {
546                 return false;
547         }
548
549         /* if we're running replicated plugins, each plugin has
550            the same i/o configuration and we may need to announce how many
551            output streams there are.
552
553            if we running a single plugin, we need to configure it.
554         */
555
556         if (_plugins.front()->configure_io (in, out) < 0) {
557                 return false;
558         }
559
560         // we don't know the analysis window size, so we must work with the
561         // current buffer size here. each request for data fills in these
562         // buffers and the analyser makes sure it gets enough data for the 
563         // analysis window
564         _signal_analysis_input_bufferset.ensure_buffers (in,  session().engine().frames_per_cycle());
565         _signal_analysis_input_bufferset.set_count(in);
566
567         _signal_analysis_output_bufferset.ensure_buffers(out, session().engine().frames_per_cycle());
568         _signal_analysis_output_bufferset.set_count(out);
569
570
571         return Processor::configure_io (in, out);
572 }
573
574 bool
575 PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
576 {
577         if (_plugins.front()->reconfigurable_io()) {
578                 /* plugin has flexible I/O, so delegate to it */
579                 return _plugins.front()->can_support_io_configuration (in, out);
580         }
581
582         ChanCount outputs = _plugins[0]->get_info()->n_outputs;
583         ChanCount inputs = _plugins[0]->get_info()->n_inputs;
584
585         if ((inputs.n_total() == 0)
586                         || (inputs.n_total() == 1 && outputs == inputs)
587                         || (inputs.n_total() == 1 && outputs == inputs
588                                 && ((inputs.n_audio() == 0 && in.n_audio() == 0)
589                                         || (inputs.n_midi() == 0 && in.n_midi() == 0)))
590                         || (inputs == in)) {
591                 out = outputs;
592                 return true;
593         }
594
595         bool can_replicate = true;
596
597         /* if number of inputs is a factor of the requested input
598            configuration for every type, we can replicate.
599         */
600         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
601                 if (inputs.get(*t) >= in.get(*t) || (inputs.get(*t) % in.get(*t) != 0)) {
602                         can_replicate = false;
603                         break;
604                 }
605         }
606
607         if (!can_replicate || (in.n_total() % inputs.n_total() != 0)) {
608                 return false;
609         }
610
611         if (inputs.n_total() == 0) {
612                 /* instrument plugin, always legal, but throws away any existing streams */
613                 out = outputs;
614         } else if (inputs.n_total() == 1 && outputs == inputs
615                         && ((inputs.n_audio() == 0 && in.n_audio() == 0)
616                             || (inputs.n_midi() == 0 && in.n_midi() == 0))) {
617                 /* mono, single-typed plugin, replicate as needed to match in */
618                 out = in;
619         } else if (inputs == in) {
620                 /* exact match */
621                 out = outputs;
622         } else {
623                 /* replicate - note that we've already verified that
624                    the replication count is constant across all data types.
625                 */
626                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
627                         out.set (*t, outputs.get(*t) * (in.get(*t) / inputs.get(*t)));
628                 }
629         }
630                 
631         return true;
632 }
633
634 /* Number of plugin instances required to support a given channel configuration.
635  * (private helper)
636  */
637 int32_t
638 PluginInsert::count_for_configuration (ChanCount in, ChanCount out) const
639 {
640         if (_plugins.front()->reconfigurable_io()) {
641                 /* plugin has flexible I/O, so the answer is always 1 */
642                 /* this could change if we ever decide to replicate AU's */
643                 return 1;
644         }
645
646         // FIXME: take 'out' into consideration
647         
648         ChanCount outputs = _plugins[0]->get_info()->n_outputs;
649         ChanCount inputs = _plugins[0]->get_info()->n_inputs;
650
651         if (inputs.n_total() == 0) {
652                 /* instrument plugin, always legal, but throws away any existing streams */
653                 return 1;
654         }
655
656         if (inputs.n_total() == 1 && outputs == inputs
657                         && ((inputs.n_audio() == 0 && in.n_audio() == 0)
658                                 || (inputs.n_midi() == 0 && in.n_midi() == 0))) {
659                 /* mono plugin, replicate as needed to match in */
660                 return in.n_total();
661         }
662
663         if (inputs == in) {
664                 /* exact match */
665                 return 1;
666         }
667
668         // assumes in is valid, so we must be replicating
669         if (inputs.n_total() < in.n_total()
670                         && (in.n_total() % inputs.n_total() == 0)) {
671
672                 return in.n_total() / inputs.n_total();
673         }
674
675         /* err... */
676         return 0;
677 }
678
679 XMLNode&
680 PluginInsert::get_state(void)
681 {
682         return state (true);
683 }
684
685 XMLNode&
686 PluginInsert::state (bool full)
687 {
688         XMLNode& node = Processor::state (full);
689
690         node.add_property ("type", _plugins[0]->state_node_name());
691         node.add_property("unique-id", _plugins[0]->unique_id());
692         node.add_property("count", string_compose("%1", _plugins.size()));
693         node.add_child_nocopy (_plugins[0]->get_state());
694
695         /* add port automation state */
696         //XMLNode *autonode = new XMLNode(port_automation_node_name);
697         set<Evoral::Parameter> automatable = _plugins[0]->automatable();
698         
699         for (set<Evoral::Parameter>::iterator x = automatable.begin(); x != automatable.end(); ++x) {
700                 
701                 /*XMLNode* child = new XMLNode("port");
702                 snprintf(buf, sizeof(buf), "%" PRIu32, *x);
703                 child->add_property("number", string(buf));
704                 
705                 child->add_child_nocopy (automation_list (*x).state (full));
706                 autonode->add_child_nocopy (*child);
707                 */
708                 //autonode->add_child_nocopy (((AutomationList*)data().control(*x)->list().get())->state (full));
709         }
710
711         //node.add_child_nocopy (*autonode);
712         
713         return node;
714 }
715
716 int
717 PluginInsert::set_state(const XMLNode& node)
718 {
719         XMLNodeList nlist = node.children();
720         XMLNodeIterator niter;
721         XMLPropertyList plist;
722         const XMLProperty *prop;
723         ARDOUR::PluginType type;
724
725         if ((prop = node.property ("type")) == 0) {
726                 error << _("XML node describing insert is missing the `type' field") << endmsg;
727                 return -1;
728         }
729
730         if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
731                 type = ARDOUR::LADSPA;
732         } else if (prop->value() == X_("lv2")) {
733                 type = ARDOUR::LV2;
734         } else if (prop->value() == X_("vst")) {
735                 type = ARDOUR::VST;
736         } else {
737                 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
738                                   prop->value())
739                       << endmsg;
740                 return -1;
741         }
742         
743         prop = node.property ("unique-id");
744         if (prop == 0) {
745                 error << _("Plugin has no unique ID field") << endmsg;
746                 return -1;
747         }
748
749         boost::shared_ptr<Plugin> plugin;
750         
751         plugin = find_plugin (_session, prop->value(), type);   
752
753         if (plugin == 0) {
754                 error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
755                                    "Perhaps it was removed or moved since it was last used."), prop->value()) 
756                       << endmsg;
757                 return -1;
758         }
759
760         uint32_t count = 1;
761
762         if ((prop = node.property ("count")) != 0) {
763                 sscanf (prop->value().c_str(), "%u", &count);
764         }
765
766         if (_plugins.size() != count) {
767                 
768                 _plugins.push_back (plugin);
769                 
770                 for (uint32_t n=1; n < count; ++n) {
771                         _plugins.push_back (plugin_factory (plugin));
772                 }
773         }
774         
775         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
776                 if ((*niter)->name() == plugin->state_node_name()) {
777                         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
778                                 (*i)->set_state (**niter);
779                         }
780                         break;
781                 }
782         } 
783
784         const XMLNode* insert_node = &node;
785
786         // legacy sessions: search for child IOProcessor node
787         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
788                 if ((*niter)->name() == "IOProcessor") {
789                         insert_node = *niter;
790                         break;
791                 }
792         }
793         
794         Processor::set_state (*insert_node);
795
796         /* look for port automation node */
797         
798         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
799
800                 if ((*niter)->name() != port_automation_node_name) {
801                         continue;
802                 }
803
804                 XMLNodeList cnodes;
805                 XMLProperty *cprop;
806                 XMLNodeConstIterator iter;
807                 XMLNode *child;
808                 const char *port;
809                 uint32_t port_id;
810                 
811                 cnodes = (*niter)->children ("port");
812                 
813                 for(iter = cnodes.begin(); iter != cnodes.end(); ++iter){
814                         
815                         child = *iter;
816                         
817                         if ((cprop = child->property("number")) != 0) {
818                                 port = cprop->value().c_str();
819                         } else {
820                                 warning << _("PluginInsert: Auto: no plugin port number") << endmsg;
821                                 continue;
822                         }
823                         
824                         sscanf (port, "%" PRIu32, &port_id);
825                         
826                         if (port_id >= _plugins[0]->parameter_count()) {
827                                 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
828                                 continue;
829                         }
830
831                         boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
832                                         data().control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
833
834                         if (!child->children().empty()) {
835                                 c->alist()->set_state (*child->children().front());
836                         } else {
837                                 if ((cprop = child->property("auto")) != 0) {
838                                         
839                                         /* old school */
840
841                                         int x;
842                                         sscanf (cprop->value().c_str(), "0x%x", &x);
843                                         c->alist()->set_automation_state (AutoState (x));
844
845                                 } else {
846                                         
847                                         /* missing */
848                                         
849                                         c->alist()->set_automation_state (Off);
850                                 }
851                         }
852
853                 }
854
855                 /* done */
856
857                 break;
858         } 
859
860         if (niter == nlist.end()) {
861                 warning << string_compose(_("XML node describing a port automation is missing the `%1' information"), port_automation_node_name) << endmsg;
862         }
863         
864         // The name of the PluginInsert comes from the plugin, nothing else
865         _name = plugin->get_info()->name;
866         
867         return 0;
868 }
869
870 string
871 PluginInsert::describe_parameter (Evoral::Parameter param)
872 {
873         if (param.type() != PluginAutomation)
874                 return Automatable::describe_parameter(param);
875
876         return _plugins[0]->describe_parameter (param);
877 }
878
879 ARDOUR::nframes_t 
880 PluginInsert::signal_latency() const
881 {
882         if (_user_latency) {
883                 return _user_latency;
884         }
885
886         return _plugins[0]->signal_latency ();
887 }
888
889 ARDOUR::PluginType
890 PluginInsert::type ()
891 {
892         boost::shared_ptr<LadspaPlugin> lp;
893 #ifdef VST_SUPPORT
894         boost::shared_ptr<VSTPlugin> vp;
895 #endif
896 #ifdef HAVE_AUDIOUNITS
897         boost::shared_ptr<AUPlugin> ap;
898 #endif
899         
900         PluginPtr other = plugin ();
901
902         if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
903                 return ARDOUR::LADSPA;
904 #ifdef VST_SUPPORT
905         } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
906                 return ARDOUR::VST;
907 #endif
908 #ifdef HAVE_AUDIOUNITS
909         } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
910                 return ARDOUR::AudioUnit;
911 #endif
912         } else {
913                 /* NOT REACHED */
914                 return (ARDOUR::PluginType) 0;
915         }
916 }
917
918 PluginInsert::PluginControl::PluginControl (PluginInsert* p, const Evoral::Parameter &param, boost::shared_ptr<AutomationList> list)
919         : AutomationControl (p->session(), param, list, p->describe_parameter(param))
920         , _plugin (p)
921 {
922         Plugin::ParameterDescriptor desc;
923         p->plugin(0)->get_parameter_descriptor (param.id(), desc);
924         _logarithmic = desc.logarithmic;
925         _toggled = desc.toggled;
926 }
927          
928 void
929 PluginInsert::PluginControl::set_value (float val)
930 {
931         /* FIXME: probably should be taking out some lock here.. */
932         
933         if (_toggled) {
934                 if (val > 0.5) {
935                         val = 1.0;
936                 } else {
937                         val = 0.0;
938                 }
939         } else {
940                         
941                 /*const float range = _list->get_max_y() - _list->get_min_y();
942                 const float lower = _list->get_min_y();
943
944                 if (!_logarithmic) {
945                         val = lower + (range * val);
946                 } else {
947                         float log_lower = 0.0f;
948                         if (lower > 0.0f) {
949                                 log_lower = log(lower);
950                         }
951
952                         val = exp(log_lower + log(range) * val);
953                 }*/
954
955         }
956
957         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugin->_plugins.begin();
958                         i != _plugin->_plugins.end(); ++i) {
959                 (*i)->set_parameter (_list->parameter().id(), val);
960         }
961
962         boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
963         if (iasp) {
964                 iasp->set_parameter (_list->parameter().id(), val);
965         }
966
967         AutomationControl::set_value(val);
968 }
969
970 float
971 PluginInsert::PluginControl::get_value (void) const
972 {
973         /* FIXME: probably should be taking out some lock here.. */
974         
975         float val = _plugin->get_parameter (_list->parameter());
976
977         return val;
978
979         /*if (_toggled) {
980                 
981                 return val;
982                 
983         } else {
984                 
985                 if (_logarithmic) {
986                         val = log(val);
987                 }
988                 
989                 return ((val - lower) / range);
990         }*/
991 }
992
993 boost::shared_ptr<Plugin>
994 PluginInsert::get_impulse_analysis_plugin()
995 {
996         boost::shared_ptr<Plugin> ret;
997         if (_impulseAnalysisPlugin.expired()) {
998                 ret = plugin_factory(_plugins[0]);
999                 _impulseAnalysisPlugin = ret;
1000         } else {
1001                 ret = _impulseAnalysisPlugin.lock();
1002         }
1003
1004         return ret;
1005 }
1006