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