Remove beat entry from meter dialog (beats are not allowed in API), clean up some...
[ardour.git] / libs / ardour / 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/insert.h>
28 #include <ardour/plugin.h>
29 #include <ardour/port.h>
30 #include <ardour/route.h>
31 #include <ardour/ladspa_plugin.h>
32
33 #ifdef HAVE_SLV2
34 #include <ardour/lv2_plugin.h>
35 #endif
36
37 #ifdef VST_SUPPORT
38 #include <ardour/vst_plugin.h>
39 #endif
40
41 #ifdef HAVE_AUDIOUNITS
42 #include <ardour/audio_unit.h>
43 #endif
44
45 #include <ardour/audioengine.h>
46 #include <ardour/session.h>
47 #include <ardour/types.h>
48
49 #include "i18n.h"
50
51 using namespace std;
52 using namespace ARDOUR;
53 using namespace PBD;
54
55 Insert::Insert(Session& s, string name, Placement p)
56         : Redirect (s, name, p)
57 {
58 }
59
60 Insert::Insert(Session& s, string name, Placement p, int imin, int imax, int omin, int omax)
61         : Redirect (s, name, p, imin, imax, omin, omax)
62 {
63 }
64
65 /***************************************************************
66  Plugin inserts: send data through a plugin
67  ***************************************************************/
68
69 const string PluginInsert::port_automation_node_name = "PortAutomation";
70
71 PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placement placement)
72         : Insert (s, plug->name(), placement)
73 {
74         /* the first is the master */
75
76         _plugins.push_back (plug);
77
78         _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
79         
80         init ();
81
82         if (_plugins[0]->fixed_io()) {
83                 Glib::Mutex::Lock em (_session.engine().process_lock());
84                 IO::MoreOutputs (output_streams ());
85         }
86
87         RedirectCreated (this); /* EMIT SIGNAL */
88 }
89
90 PluginInsert::PluginInsert (Session& s, const XMLNode& node)
91         : Insert (s, "will change", PreFader)
92 {
93         if (set_state (node)) {
94                 throw failed_constructor();
95         }
96
97         set_automatable ();
98
99         _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
100
101         if (_plugins[0]->fixed_io()) {
102                 Glib::Mutex::Lock em (_session.engine().process_lock());
103                 IO::MoreOutputs (output_streams());
104         }
105 }
106
107 PluginInsert::PluginInsert (const PluginInsert& other)
108         : Insert (other._session, other.plugin()->name(), other.placement())
109 {
110         uint32_t count = other._plugins.size();
111
112         /* make as many copies as requested */
113         for (uint32_t n = 0; n < count; ++n) {
114                 _plugins.push_back (plugin_factory (other.plugin (n)));
115         }
116
117
118         _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
119
120         init ();
121
122         RedirectCreated (this); /* EMIT SIGNAL */
123 }
124
125 int
126 PluginInsert::set_count (uint32_t num)
127 {
128         bool require_state = !_plugins.empty();
129
130         /* this is a bad idea.... we shouldn't do this while active.
131            only a route holding their redirect_lock should be calling this 
132         */
133
134         if (num == 0) { 
135                 return -1;
136         } else if (num > _plugins.size()) {
137                 uint32_t diff = num - _plugins.size();
138
139                 for (uint32_t n = 0; n < diff; ++n) {
140                         _plugins.push_back (plugin_factory (_plugins[0]));
141
142                         if (require_state) {
143                                 /* XXX do something */
144                         }
145                 }
146
147         } else if (num < _plugins.size()) {
148                 uint32_t diff = _plugins.size() - num;
149                 for (uint32_t n= 0; n < diff; ++n) {
150                         _plugins.pop_back();
151                 }
152         }
153
154         return 0;
155 }
156
157 void
158 PluginInsert::init ()
159 {
160         set_automatable ();
161
162         set<uint32_t>::iterator s;
163 }
164
165 PluginInsert::~PluginInsert ()
166 {
167         GoingAway (); /* EMIT SIGNAL */
168 }
169
170 void
171 PluginInsert::automation_list_creation_callback (uint32_t which, AutomationList& alist)
172 {
173         alist.automation_state_changed.connect (sigc::bind (mem_fun (*this, &PluginInsert::auto_state_changed), (which)));
174 }
175
176 void
177 PluginInsert::auto_state_changed (uint32_t which)
178 {
179         AutomationList& alist (automation_list (which));
180
181         if (alist.automation_state() != Off) {
182                 _plugins[0]->set_parameter (which, alist.eval (_session.transport_frame()));
183         }
184 }
185
186 uint32_t
187 PluginInsert::output_streams() const
188 {
189         int32_t out = _plugins[0]->get_info()->n_outputs;
190
191         if (out < 0) {
192                 return _plugins[0]->output_streams ();
193         } else {
194                 return out * _plugins.size();
195         }
196 }
197
198 uint32_t
199 PluginInsert::input_streams() const
200 {
201         int32_t in = _plugins[0]->get_info()->n_inputs;
202         if (in < 0) {
203                 return _plugins[0]->input_streams ();
204         } else {
205                 return in * _plugins.size();
206         }
207 }
208
209 uint32_t
210 PluginInsert::natural_output_streams() const
211 {
212         return _plugins[0]->get_info()->n_outputs;
213 }
214
215 uint32_t
216 PluginInsert::natural_input_streams() const
217 {
218         return _plugins[0]->get_info()->n_inputs;
219 }
220
221 bool
222 PluginInsert::is_generator() const
223 {
224         /* XXX more finesse is possible here. VST plugins have a
225            a specific "instrument" flag, for example.
226          */
227
228         return _plugins[0]->get_info()->n_inputs == 0;
229 }
230
231 void
232 PluginInsert::set_automatable ()
233 {
234         set<uint32_t> a;
235         
236         a = _plugins.front()->automatable ();
237
238         for (set<uint32_t>::iterator i = a.begin(); i != a.end(); ++i) {
239                 can_automate (*i);
240         }
241 }
242
243 void
244 PluginInsert::parameter_changed (uint32_t which, float val)
245 {
246         vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin();
247
248         /* don't set the first plugin, just all the slaves */
249
250         if (i != _plugins.end()) {
251                 ++i;
252                 for (; i != _plugins.end(); ++i) {
253                         (*i)->set_parameter (which, val);
254                 }
255         }
256 }
257
258 void
259 PluginInsert::set_block_size (nframes_t nframes)
260 {
261         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
262                 (*i)->set_block_size (nframes);
263         }
264 }
265
266 void
267 PluginInsert::activate ()
268 {
269         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
270                 (*i)->activate ();
271         }
272 }
273
274 void
275 PluginInsert::deactivate ()
276 {
277         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
278                 (*i)->deactivate ();
279         }
280 }
281
282 void
283 PluginInsert::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now)
284 {
285         int32_t in_index = 0;
286         int32_t out_index = 0;
287
288         /* Note that we've already required that plugins
289            be able to handle in-place processing.
290         */
291
292         if (with_auto) {
293
294                 map<uint32_t,AutomationList*>::iterator li;
295                 uint32_t n;
296                 
297                 for (n = 0, li = parameter_automation.begin(); li != parameter_automation.end(); ++li, ++n) {
298                         
299                         AutomationList& alist (*((*li).second));
300
301                         if (alist.automation_playback()) {
302                                 bool valid;
303
304                                 float val = alist.rt_safe_eval (now, valid);                            
305
306                                 if (valid) {
307                                         /* set the first plugin, the others will be set via signals */
308                                         _plugins[0]->set_parameter ((*li).first, val);
309                                 }
310
311                         } 
312                 }
313         }
314
315         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
316                 (*i)->connect_and_run (bufs, nbufs, in_index, out_index, nframes, offset);
317         }
318
319         /* leave remaining channel buffers alone */
320 }
321
322 void
323 PluginInsert::automation_snapshot (nframes_t now, bool force)
324 {
325         map<uint32_t,AutomationList*>::iterator li;
326         
327         for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
328                 
329                 AutomationList *alist = ((*li).second);
330                 if (alist != 0 && alist->automation_write ()) {
331                         
332                         float val = _plugins[0]->get_parameter ((*li).first);
333                         alist->rt_add (now, val);
334                         last_automation_snapshot = now;
335                 }
336         }
337 }
338
339 void
340 PluginInsert::transport_stopped (nframes_t now)
341 {
342         map<uint32_t,AutomationList*>::iterator li;
343
344         for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) {
345                 AutomationList& alist (*(li->second));
346                 alist.reposition_for_rt_add (now);
347
348                 if (alist.automation_state() != Off) {
349                         _plugins[0]->set_parameter (li->first, alist.eval (now));
350                 }
351         }
352 }
353
354 void
355 PluginInsert::silence (nframes_t nframes, nframes_t offset)
356 {
357         int32_t in_index = 0;
358         int32_t out_index = 0;
359
360         uint32_t n;
361
362         if (active()) {
363                 for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
364                         n = (*i) -> get_info()->n_inputs;
365                         (*i)->connect_and_run (_session.get_silent_buffers (n), n, in_index, out_index, nframes, offset);
366                 }
367         }
368 }
369         
370 void
371 PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset)
372 {
373         if (active()) {
374
375                 if (_session.transport_rolling()) {
376                         automation_run (bufs, nbufs, nframes, offset);
377                 } else {
378                         connect_and_run (bufs, nbufs, nframes, offset, false);
379                 }
380
381         } else {
382
383                 uint32_t in = _plugins[0]->get_info()->n_inputs;
384                 uint32_t out = _plugins[0]->get_info()->n_outputs;
385
386                 if (in < 0 || out < 0) {
387                         
388                 } else {
389
390                         if (out > in) {
391                                 
392                                 /* not active, but something has make up for any channel count increase */
393                                 
394                                 for (uint32_t n = out - in; n < out; ++n) {
395                                         memcpy (bufs[n], bufs[in - 1], sizeof (Sample) * nframes);
396                                 }
397                         }
398                 }
399         }
400 }
401
402 void
403 PluginInsert::set_parameter (uint32_t port, float val)
404 {
405         /* the others will be set from the event triggered by this */
406
407         _plugins[0]->set_parameter (port, val);
408         
409         if (automation_list (port).automation_write()) {
410                 automation_list (port).add (_session.audible_frame(), val);
411         }
412
413         _session.set_dirty();
414 }
415
416 void
417 PluginInsert::automation_run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset)
418 {
419         ControlEvent next_event (0, 0.0f);
420         nframes_t now = _session.transport_frame ();
421         nframes_t end = now + nframes;
422
423         Glib::Mutex::Lock lm (_automation_lock, Glib::TRY_LOCK);
424
425         if (!lm.locked()) {
426                 connect_and_run (bufs, nbufs, nframes, offset, false);
427                 return;
428         }
429         
430         if (!find_next_event (now, end, next_event)) {
431                 
432                 /* no events have a time within the relevant range */
433                 
434                 connect_and_run (bufs, nbufs, nframes, offset, true, now);
435                 return;
436         }
437         
438         while (nframes) {
439
440                 nframes_t cnt = min (((nframes_t) ceil (next_event.when) - now), nframes);
441   
442                 connect_and_run (bufs, nbufs, cnt, offset, true, now);
443                 
444                 nframes -= cnt;
445                 offset += cnt;
446                 now += cnt;
447
448                 if (!find_next_event (now, end, next_event)) {
449                         break;
450                 }
451         }
452   
453         /* cleanup anything that is left to do */
454   
455         if (nframes) {
456                 connect_and_run (bufs, nbufs, nframes, offset, true, now);
457         }
458 }       
459
460 float
461 PluginInsert::default_parameter_value (uint32_t port)
462 {
463         if (_plugins.empty()) {
464                 fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
465                       << endmsg;
466                 /*NOTREACHED*/
467         }
468
469         return _plugins[0]->default_value (port);
470 }
471         
472 void
473 PluginInsert::set_port_automation_state (uint32_t port, AutoState s)
474 {
475         if (port < _plugins[0]->parameter_count()) {
476                 
477                 AutomationList& al = automation_list (port);
478
479                 if (s != al.automation_state()) {
480                         al.set_automation_state (s);
481                         _session.set_dirty ();
482                 }
483         }
484 }
485
486 AutoState
487 PluginInsert::get_port_automation_state (uint32_t port)
488 {
489         if (port < _plugins[0]->parameter_count()) {
490                 return automation_list (port).automation_state();
491         } else {
492                 return Off;
493         }
494 }
495
496 void
497 PluginInsert::protect_automation ()
498 {
499         set<uint32_t> automated_params;
500
501         what_has_automation (automated_params);
502
503         for (set<uint32_t>::iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
504
505                 AutomationList& al = automation_list (*i);
506
507                 switch (al.automation_state()) {
508                 case Write:
509                         al.set_automation_state (Off);
510                         break;
511                 case Touch:
512                         al.set_automation_state (Play);
513                         break;
514                 default:
515                         break;
516                 }
517         }
518 }
519
520 boost::shared_ptr<Plugin>
521 PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
522 {
523         boost::shared_ptr<LadspaPlugin> lp;
524 #ifdef HAVE_SLV2
525         boost::shared_ptr<LV2Plugin> lv2p;
526 #endif
527 #ifdef VST_SUPPORT
528         boost::shared_ptr<VSTPlugin> vp;
529 #endif
530 #ifdef HAVE_AUDIOUNITS
531         boost::shared_ptr<AUPlugin> ap;
532 #endif
533
534         if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
535                 return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
536 #ifdef HAVE_SLV2
537         } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
538                 return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
539 #endif
540 #ifdef VST_SUPPORT
541         } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
542                 return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
543 #endif
544 #ifdef HAVE_AUDIOUNITS
545         } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
546                 return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
547 #endif
548         }
549
550         fatal << string_compose (_("programming error: %1"),
551                           X_("unknown plugin type in PluginInsert::plugin_factory"))
552               << endmsg;
553         /*NOTREACHED*/
554         return boost::shared_ptr<Plugin> ((Plugin*) 0);
555 }
556
557 int32_t
558 PluginInsert::compute_output_streams (int32_t cnt) const
559 {
560         int32_t outputs;
561
562         if ((outputs = _plugins[0]->get_info()->n_outputs) < 0) {
563                 // have to ask the plugin itself, because it has flexible I/O
564                 return _plugins[0]->compute_output_streams (cnt);
565         }
566
567         return outputs * cnt;
568 }
569
570 int32_t
571 PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out)
572 {
573         return set_count (magic);
574 }
575
576 int32_t 
577 PluginInsert::can_support_input_configuration (int32_t in) const
578 {
579         int32_t outputs = _plugins[0]->get_info()->n_outputs;
580         int32_t inputs = _plugins[0]->get_info()->n_inputs;
581
582         if (outputs < 0 || inputs < 0) {
583                 /* have to ask the plugin because its got reconfigurable I/O
584                  */
585                 return _plugins[0]->can_support_input_configuration (in);
586         }
587
588         if (inputs == 0) {
589
590                 /* instrument plugin, always legal, but it throws
591                    away any existing active streams.
592                 */
593
594                 return 1;
595         }
596
597         if (outputs == 1 && inputs == 1) {
598                 /* mono plugin, replicate as needed */
599                 return in;
600         }
601
602         if (inputs == in) {
603                 /* exact match */
604                 return 1;
605         }
606
607         if ((inputs < in) && (inputs % in == 0)) {
608
609                 /* number of inputs is a factor of the requested input
610                    configuration, so we can replicate.
611                 */
612
613                 return in/inputs;
614         }
615
616         /* sorry */
617
618         return -1;
619 }
620
621 XMLNode&
622 PluginInsert::get_state(void)
623 {
624         return state (true);
625 }
626
627 XMLNode&
628 PluginInsert::state (bool full)
629 {
630         char buf[256];
631         XMLNode *node = new XMLNode("Insert");
632
633         node->add_child_nocopy (Redirect::state (full));
634
635         node->add_property ("type", _plugins[0]->state_node_name());
636         node->add_property("unique-id", _plugins[0]->unique_id());
637         node->add_property("count", string_compose("%1", _plugins.size()));
638         node->add_child_nocopy (_plugins[0]->get_state());
639
640         /* add controllables */
641
642         XMLNode* control_node = new XMLNode (X_("controls"));
643
644         for (uint32_t x = 0; x < _plugins[0]->parameter_count(); ++x) {
645                 Controllable* c = _plugins[0]->get_nth_control (x, true);
646                 if (c) {
647                         XMLNode& controllable_state (c->get_state());
648                         controllable_state.add_property ("parameter", to_string (x, std::dec));
649                         control_node->add_child_nocopy (controllable_state);
650                 }
651         }
652         node->add_child_nocopy (*control_node);
653
654         /* add port automation state */
655         XMLNode *autonode = new XMLNode(port_automation_node_name);
656         set<uint32_t> automatable = _plugins[0]->automatable();
657
658         for (set<uint32_t>::iterator x =  automatable.begin(); x != automatable.end(); ++x) {
659
660                 XMLNode* child = new XMLNode("port");
661                 snprintf(buf, sizeof(buf), "%" PRIu32, *x);
662                 child->add_property("number", string(buf));
663
664                 child->add_child_nocopy (automation_list (*x).state (full));
665                 autonode->add_child_nocopy (*child);
666         }
667
668         node->add_child_nocopy (*autonode);
669         
670         return *node;
671 }
672
673 int
674 PluginInsert::set_state(const XMLNode& node)
675 {
676         XMLNodeList nlist = node.children();
677         XMLNodeIterator niter;
678         XMLPropertyList plist;
679         const XMLProperty *prop;
680         ARDOUR::PluginType type;
681
682         if ((prop = node.property ("type")) == 0) {
683                 error << _("XML node describing insert is missing the `type' field") << endmsg;
684                 return -1;
685         }
686
687         if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
688                 type = ARDOUR::LADSPA;
689         } else if (prop->value() == X_("lv2")) {
690                 type = ARDOUR::LV2;
691         } else if (prop->value() == X_("vst")) {
692                 type = ARDOUR::VST;
693         } else if (prop->value() == X_("audiounit")) {
694                 type = ARDOUR::AudioUnit;
695         } else {
696                 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
697                                   prop->value())
698                       << endmsg;
699                 return -1;
700         }
701
702         prop = node.property ("unique-id");
703         if (prop == 0) {
704 #ifdef VST_SUPPORT
705                 /* older sessions contain VST plugins with only an "id" field.
706                  */
707                 
708                 if (type == ARDOUR::VST) {
709                         if (prop = node.property ("id")) {
710                         }
711                 }
712 #endif          
713                 /* recheck  */
714
715                 if (prop == 0) {
716                         error << _("Plugin has no unique ID field") << endmsg;
717                         return -1;
718                 }
719         }
720
721         boost::shared_ptr<Plugin> plugin;
722
723         plugin = find_plugin (_session, prop->value(), type);   
724
725         if (plugin == 0) {
726                 error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
727                                    "Perhaps it was removed or moved since it was last used."), prop->value()) 
728                       << endmsg;
729                 return -1;
730         }
731
732         uint32_t count = 1;
733
734         if ((prop = node.property ("count")) != 0) {
735                 sscanf (prop->value().c_str(), "%u", &count);
736         }
737
738         if (_plugins.size() != count) {
739                 
740                 _plugins.push_back (plugin);
741                 
742                 for (uint32_t n=1; n < count; ++n) {
743                         _plugins.push_back (plugin_factory (plugin));
744                 }
745         }
746         
747         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
748                 if ((*niter)->name() == plugin->state_node_name()) {
749                         for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
750                                 (*i)->set_state (**niter);
751                         }
752                         break;
753                 }
754         } 
755
756         if (niter == nlist.end()) {
757                 error << string_compose(_("XML node describing a plugin insert is missing the `%1' information"), plugin->state_node_name()) << endmsg;
758                 return -1;
759         }
760
761         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
762                 if ((*niter)->name() == Redirect::state_node_name) {
763                         Redirect::set_state (**niter);
764                         break;
765                 }
766         }
767
768         if (niter == nlist.end()) {
769                 error << _("XML node describing insert is missing a Redirect node") << endmsg;
770                 return -1;
771         }
772
773         /* look for controllables node */
774         
775         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
776
777                 if ((*niter)->name() != X_("controls")) {
778                         continue;
779                 }
780                 
781                 XMLNodeList grandchildren ((*niter)->children());
782                 XMLProperty* prop;
783                 XMLNodeIterator gciter;
784                 uint32_t param;
785                 
786                 for (gciter = grandchildren.begin(); gciter != grandchildren.end(); ++gciter) {
787                         if ((prop = (*gciter)->property (X_("parameter"))) != 0) {
788                                 param = atoi (prop->value());
789                                 /* force creation of controllable for this parameter */
790                                 _plugins[0]->make_nth_control (param, **gciter);
791                         } 
792                 }
793
794                 break;
795         }
796                 
797         /* look for port automation node */
798         
799         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
800
801                 if ((*niter)->name() != port_automation_node_name) {
802                         continue;
803                 }
804
805                 XMLNodeList cnodes;
806                 XMLProperty *cprop;
807                 XMLNodeConstIterator iter;
808                 XMLNode *child;
809                 const char *port;
810                 uint32_t port_id;
811                 
812                 cnodes = (*niter)->children ("port");
813                 
814                 for(iter = cnodes.begin(); iter != cnodes.end(); ++iter){
815                         
816                         child = *iter;
817                         
818                         if ((cprop = child->property("number")) != 0) {
819                                 port = cprop->value().c_str();
820                         } else {
821                                 warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
822                                 continue;
823                         }
824                         
825                         sscanf (port, "%" PRIu32, &port_id);
826                         
827                         if (port_id >= _plugins[0]->parameter_count()) {
828                                 warning << _("PluginInsert: Auto: port id out of range") << endmsg;
829                                 continue;
830                         }
831
832                         if (!child->children().empty()) {
833                                 automation_list (port_id).set_state (*child->children().front());
834                         } else {
835                                 if ((cprop = child->property("auto")) != 0) {
836                                         
837                                         /* old school */
838
839                                         int x;
840                                         sscanf (cprop->value().c_str(), "0x%x", &x);
841                                         automation_list (port_id).set_automation_state (AutoState (x));
842
843                                 } else {
844                                         
845                                         /* missing */
846                                         
847                                         automation_list (port_id).set_automation_state (Off);
848                                 }
849                         }
850
851                 }
852
853                 /* done */
854
855                 break;
856         } 
857
858         if (niter == nlist.end()) {
859                 warning << string_compose(_("XML node describing a port automation is missing the `%1' information"), port_automation_node_name) << endmsg;
860         }
861         
862         // The name of the PluginInsert comes from the plugin, nothing else
863         set_name(plugin->get_info()->name,this);
864         
865         return 0;
866 }
867
868 string
869 PluginInsert::describe_parameter (uint32_t what)
870 {
871         return _plugins[0]->describe_parameter (what);
872 }
873
874 nframes_t 
875 PluginInsert::latency() 
876 {
877         return _plugins[0]->latency ();
878 }
879         
880 ARDOUR::PluginType
881 PluginInsert::type ()
882 {
883         boost::shared_ptr<LadspaPlugin> lp;
884 #ifdef VST_SUPPORT
885         boost::shared_ptr<VSTPlugin> vp;
886 #endif
887 #ifdef HAVE_AUDIOUNITS
888         boost::shared_ptr<AUPlugin> ap;
889 #endif
890         
891         PluginPtr other = plugin ();
892
893         if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
894                 return ARDOUR::LADSPA;
895 #ifdef VST_SUPPORT
896         } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
897                 return ARDOUR::VST;
898 #endif
899 #ifdef HAVE_AUDIOUNITS
900         } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
901                 return ARDOUR::AudioUnit;
902 #endif
903         } else {
904                 /* NOT REACHED */
905                 return (ARDOUR::PluginType) 0;
906         }
907 }
908
909 /***************************************************************
910  Port inserts: send output to a port, pick up input at a port
911  ***************************************************************/
912
913 PortInsert::PortInsert (Session& s, Placement p)
914         : Insert (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
915 {
916         init ();
917         RedirectCreated (this); /* EMIT SIGNAL */
918
919 }
920
921 PortInsert::PortInsert (const PortInsert& other)
922         : Insert (other._session, string_compose (_("insert %1"), (bitslot = other._session.next_insert_id()) + 1), other.placement(), 1, -1, 1, -1)
923 {
924         init ();
925         RedirectCreated (this); /* EMIT SIGNAL */
926 }
927
928 void
929 PortInsert::init ()
930 {
931         if (add_input_port ("", this)) {
932                 error << _("PortInsert: cannot add input port") << endmsg;
933                 throw failed_constructor();
934         }
935         
936         if (add_output_port ("", this)) {
937                 error << _("PortInsert: cannot add output port") << endmsg;
938                 throw failed_constructor();
939         }
940 }
941
942 PortInsert::PortInsert (Session& s, const XMLNode& node)
943         : Insert (s, "will change", PreFader)
944 {
945         bitslot = 0xffffffff;
946         if (set_state (node)) {
947                 throw failed_constructor();
948         }
949
950         RedirectCreated (this); /* EMIT SIGNAL */
951 }
952
953 PortInsert::~PortInsert ()
954 {
955         GoingAway ();
956 }
957
958 void
959 PortInsert::run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset)
960 {
961         if (n_outputs() == 0) {
962                 return;
963         }
964
965         if (!active()) {
966                 /* deliver silence */
967                 silence (nframes, offset);
968                 return;
969         }
970
971         uint32_t n;
972         vector<Port*>::iterator o;
973         vector<Port*>::iterator i;
974
975         /* deliver output */
976
977         for (o = _outputs.begin(), n = 0; o != _outputs.end(); ++o, ++n) {
978                 memcpy ((*o)->get_buffer (nframes) + offset, bufs[min(nbufs,n)], sizeof (Sample) * nframes);
979                 (*o)->mark_silence (false);
980         }
981         
982         /* collect input */
983         
984         for (i = _inputs.begin(), n = 0; i != _inputs.end(); ++i, ++n) {
985                 memcpy (bufs[min(nbufs,n)], (*i)->get_buffer (nframes) + offset, sizeof (Sample) * nframes);
986         }
987 }
988
989 XMLNode&
990 PortInsert::get_state(void)
991 {
992         return state (true);
993 }
994
995 XMLNode&
996 PortInsert::state (bool full)
997 {
998         XMLNode *node = new XMLNode("Insert");
999         char buf[32];
1000         node->add_child_nocopy (Redirect::state(full)); 
1001         node->add_property ("type", "port");
1002         snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
1003         node->add_property ("bitslot", buf);
1004
1005         return *node;
1006 }
1007
1008 int
1009 PortInsert::set_state(const XMLNode& node)
1010 {
1011         XMLNodeList nlist = node.children();
1012         XMLNodeIterator niter;
1013         XMLPropertyList plist;
1014         const XMLProperty *prop;
1015
1016         if ((prop = node.property ("type")) == 0) {
1017                 error << _("XML node describing insert is missing the `type' field") << endmsg;
1018                 return -1;
1019         }
1020         
1021         if (prop->value() != "port") {
1022                 error << _("non-port insert XML used for port plugin insert") << endmsg;
1023                 return -1;
1024         }
1025
1026         if ((prop = node.property ("bitslot")) == 0) {
1027                 bitslot = _session.next_insert_id();
1028         } else {
1029                 uint32_t old_bitslot = bitslot;
1030                 sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
1031
1032                 if (old_bitslot != bitslot) {
1033                         _session.mark_insert_id (bitslot);
1034                 }
1035         }
1036
1037         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1038                 if ((*niter)->name() == Redirect::state_node_name) {
1039                         Redirect::set_state (**niter);
1040                         break;
1041                 }
1042         }
1043
1044         if (niter == nlist.end()) {
1045                 error << _("XML node describing insert is missing a Redirect node") << endmsg;
1046                 return -1;
1047         }
1048
1049         return 0;
1050 }
1051
1052 nframes_t 
1053 PortInsert::latency() 
1054 {
1055         /* because we deliver and collect within the same cycle,
1056            all I/O is necessarily delayed by at least frames_per_cycle().
1057
1058            if the return port for insert has its own latency, we
1059            need to take that into account too.
1060         */
1061
1062         return _session.engine().frames_per_cycle() + input_latency();
1063 }
1064
1065 int32_t
1066 PortInsert::can_support_input_configuration (int32_t in) const
1067 {
1068         if (input_maximum() == -1 && output_maximum() == -1) {
1069
1070                 /* not configured yet */
1071
1072                 return 1; /* we can support anything the first time we're asked */
1073
1074         } else {
1075
1076                 /* the "input" config for a port insert corresponds to how
1077                    many output ports it will have.
1078                 */
1079
1080                 if (output_maximum() == in) {
1081                         return 1;
1082                 } 
1083         }
1084
1085         return -1;
1086 }
1087
1088 int32_t
1089 PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out)
1090 {
1091         /* do not allow configuration to be changed outside the range of
1092            the last request config. or something like that.
1093         */
1094
1095
1096         /* this is a bit odd: 
1097
1098            the number of inputs we are required to handle corresponds 
1099            to the number of output ports we need.
1100
1101            the number of outputs we are required to have corresponds
1102            to the number of input ports we need.
1103         */
1104
1105         set_output_maximum (in);
1106         set_output_minimum (in);
1107         set_input_maximum (out);
1108         set_input_minimum (out);
1109
1110         if (in < 0) {
1111                 in = n_outputs ();
1112         } 
1113
1114         if (out < 0) {
1115                 out = n_inputs ();
1116         }
1117
1118         return ensure_io (out, in, false, this);
1119 }
1120
1121 int32_t
1122 PortInsert::compute_output_streams (int32_t cnt) const
1123 {
1124         /* puzzling, eh? think about it ... */
1125         return n_inputs ();
1126 }
1127
1128 uint32_t
1129 PortInsert::output_streams() const
1130 {
1131         return n_inputs ();
1132 }
1133
1134 uint32_t
1135 PortInsert::input_streams() const
1136 {
1137         return n_outputs ();
1138 }
1139