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