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