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