pulling trunk
[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 #include <ardour/vst_plugin.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/session.h>
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace ARDOUR;
41 //using namespace sigc;
42
43 Insert::Insert(Session& s, Placement p)
44         : Redirect (s, s.next_insert_name(), p)
45 {
46 }
47
48
49 Insert::Insert(Session& s, Placement p, int imin, int imax, int omin, int omax)
50         : Redirect (s, s.next_insert_name(), p, imin, imax, omin, omax)
51 {
52 }
53
54 Insert::Insert(Session& s, string name, Placement p)
55         : Redirect (s, name, p)
56 {
57 }
58
59 /***************************************************************
60  Plugin inserts: send data through a plugin
61  ***************************************************************/
62
63 const string PluginInsert::port_automation_node_name = "PortAutomation";
64
65 PluginInsert::PluginInsert (Session& s, Plugin& plug, Placement placement)
66         : Insert (s, plug.name(), placement)
67 {
68         /* the first is the master */
69
70         _plugins.push_back(&plug);
71
72         _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
73         
74         init ();
75
76         save_state (_("initial state"));
77
78         {
79                 Glib::Mutex::Lock em (_session.engine().process_lock());
80                 IO::MoreOutputs (output_streams ());
81         }
82
83         RedirectCreated (this); /* EMIT SIGNAL */
84 }
85
86 PluginInsert::PluginInsert (Session& s, const XMLNode& node)
87         : Insert (s, "will change", PreFader)
88 {
89         if (set_state (node)) {
90                 throw failed_constructor();
91         }
92
93         set_automatable ();
94
95         save_state (_("initial state"));
96
97         _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
98
99         {
100                 Glib::Mutex::Lock em (_session.engine().process_lock());
101                 IO::MoreOutputs (output_streams());
102         }
103 }
104
105 PluginInsert::PluginInsert (const PluginInsert& other)
106         : Insert (other._session, other.plugin().name(), other.placement())
107 {
108         uint32_t count = other._plugins.size();
109
110         /* make as many copies as requested */
111         for (uint32_t n = 0; n < count; ++n) {
112                 _plugins.push_back (plugin_factory (other.plugin()));
113         }
114
115
116         _plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
117
118         init ();
119
120         save_state (_("initial state"));
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                         Plugin * plug = _plugins.back();
151                         _plugins.pop_back();
152                         delete plug;
153                 }
154         }
155
156         return 0;
157 }
158
159 void
160 PluginInsert::init ()
161 {
162         set_automatable ();
163
164         set<uint32_t>::iterator s;
165 }
166
167 PluginInsert::~PluginInsert ()
168 {
169         GoingAway (this); /* EMIT SIGNAL */
170         
171         while (!_plugins.empty()) {
172                 Plugin* p = _plugins.back();
173                 _plugins.pop_back();
174                 delete p;
175         }
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<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<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<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
267                 (*i)->activate ();
268         }
269 }
270
271 void
272 PluginInsert::deactivate ()
273 {
274         for (vector<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<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<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 Plugin*
510 PluginInsert::plugin_factory (Plugin& other)
511 {
512         LadspaPlugin* lp;
513 #ifdef VST_SUPPORT
514         VSTPlugin* vp;
515 #endif
516
517         if ((lp = dynamic_cast<LadspaPlugin*> (&other)) != 0) {
518                 return new LadspaPlugin (*lp);
519 #ifdef VST_SUPPORT
520         } else if ((vp = dynamic_cast<VSTPlugin*> (&other)) != 0) {
521                 return new VSTPlugin (*vp);
522 #endif
523         }
524
525         fatal << string_compose (_("programming error: %1"),
526                           X_("unknown plugin type in PluginInsert::plugin_factory"))
527               << endmsg;
528         /*NOTREACHED*/
529         return 0;
530 }
531
532 int32_t
533 PluginInsert::compute_output_streams (int32_t cnt) const
534 {
535         return _plugins[0]->get_info().n_outputs * cnt;
536 }
537
538 int32_t
539 PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out)
540 {
541         return set_count (magic);
542 }
543
544 int32_t 
545 PluginInsert::can_support_input_configuration (int32_t in) const
546 {
547         int32_t outputs = _plugins[0]->get_info().n_outputs;
548         int32_t inputs = _plugins[0]->get_info().n_inputs;
549
550         if (inputs == 0) {
551
552                 /* instrument plugin, always legal, but it throws
553                    away any existing active streams.
554                 */
555
556                 return 1;
557         }
558
559         if (outputs == 1 && inputs == 1) {
560                 /* mono plugin, replicate as needed */
561                 return in;
562         }
563
564         if (inputs == in) {
565                 /* exact match */
566                 return 1;
567         }
568
569         if ((inputs < in) && (inputs % in == 0)) {
570
571                 /* number of inputs is a factor of the requested input
572                    configuration, so we can replicate.
573                 */
574
575                 return in/inputs;
576         }
577
578         /* sorry */
579
580         return -1;
581 }
582
583 XMLNode&
584 PluginInsert::get_state(void)
585 {
586         return state (true);
587 }
588
589 XMLNode&
590 PluginInsert::state (bool full)
591 {
592         char buf[256];
593         XMLNode *node = new XMLNode("Insert");
594
595         node->add_child_nocopy (Redirect::state (full));
596
597         node->add_property ("type", _plugins[0]->state_node_name());
598         snprintf(buf, sizeof(buf), "%s", _plugins[0]->name());
599         node->add_property("id", string(buf));
600         if (_plugins[0]->state_node_name() == "ladspa") {
601                 char buf[32];
602                 snprintf (buf, 31, "%ld", _plugins[0]->get_info().unique_id); 
603                 node->add_property("unique-id", string(buf));
604         }
605         node->add_property("count", string_compose("%1", _plugins.size()));
606         node->add_child_nocopy (_plugins[0]->get_state());
607
608         /* add port automation state */
609         XMLNode *autonode = new XMLNode(port_automation_node_name);
610         set<uint32_t> automatable = _plugins[0]->automatable();
611
612         for (set<uint32_t>::iterator x =  automatable.begin(); x != automatable.end(); ++x) {
613
614                 XMLNode* child = new XMLNode("port");
615                 snprintf(buf, sizeof(buf), "%" PRIu32, *x);
616                 child->add_property("number", string(buf));
617                 
618                 if (full) {
619                         snprintf(buf, sizeof(buf), "0x%x", automation_list (*x).automation_state ());
620                 } else {
621                         snprintf(buf, sizeof(buf), "0x%x", ARDOUR::Off);
622                 }
623                 child->add_property("auto", string(buf));
624                 
625                 autonode->add_child_nocopy (*child);
626         }
627
628         node->add_child_nocopy (*autonode);
629         
630         return *node;
631 }
632
633 int
634 PluginInsert::set_state(const XMLNode& node)
635 {
636         XMLNodeList nlist = node.children();
637         XMLNodeIterator niter;
638         XMLPropertyList plist;
639         const XMLProperty *prop;
640         long unique = 0;
641         PluginInfo::Type type;
642
643         if ((prop = node.property ("type")) == 0) {
644                 error << _("XML node describing insert is missing the `type' field") << endmsg;
645                 return -1;
646         }
647
648         if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
649                 type = PluginInfo::LADSPA;
650         } else if (prop->value() == X_("vst")) {
651                 type = PluginInfo::VST;
652         } else {
653                 error << string_compose (_("unknown plugin type %1 in plugin insert state"),
654                                   prop->value())
655                       << endmsg;
656                 return -1;
657         }
658
659         prop = node.property ("unique-id");
660         if (prop != 0) {
661                 unique = atol(prop->value().c_str());
662         }
663
664         if ((prop = node.property ("id")) == 0) {
665                 error << _("XML node describing insert is missing the `id' field") << endmsg;
666                 return -1;
667         }
668
669         Plugin* plugin;
670         
671         if (unique != 0) {
672                 plugin = find_plugin (_session, "", unique, type);      
673         } else {
674                 plugin = find_plugin (_session, prop->value(), 0, type);        
675         }
676
677         if (plugin == 0) {
678                 error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
679                                    "Perhaps it was removed or moved since it was last used."), prop->value()) 
680                       << endmsg;
681                 return -1;
682         }
683
684         uint32_t count = 1;
685
686         if ((prop = node.property ("count")) != 0) {
687                 sscanf (prop->value().c_str(), "%u", &count);
688         }
689
690         if (_plugins.size() != count) {
691                 
692                 _plugins.push_back (plugin);
693                 
694                 for (uint32_t n=1; n < count; ++n) {
695                         _plugins.push_back (plugin_factory (*plugin));
696                 }
697         }
698         
699         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
700                 if ((*niter)->name() == plugin->state_node_name()) {
701                         for (vector<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
702                                 (*i)->set_state (**niter);
703                         }
704                         break;
705                 }
706         } 
707
708         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
709                 if ((*niter)->name() == Redirect::state_node_name) {
710                         Redirect::set_state (**niter);
711                         break;
712                 }
713         }
714
715         if (niter == nlist.end()) {
716                 error << _("XML node describing insert is missing a Redirect node") << endmsg;
717                 return -1;
718         }
719
720         if (niter == nlist.end()) {
721                 error << string_compose(_("XML node describing a plugin insert is missing the `%1' information"), plugin->state_node_name()) << endmsg;
722                 return -1;
723         }
724         
725         /* look for port automation node */
726         
727         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
728                 if ((*niter)->name() == port_automation_node_name) {
729                         XMLNodeList cnodes;
730                         XMLProperty *cprop;
731                         XMLNodeConstIterator iter;
732                         XMLNode *child;
733                         const char *port;
734                         uint32_t port_id;
735
736                         cnodes = (*niter)->children ("port");
737         
738                         for(iter = cnodes.begin(); iter != cnodes.end(); ++iter){
739                                 
740                                 child = *iter;
741                                 
742                                 if ((cprop = child->property("number")) != 0) {
743                                         port = cprop->value().c_str();
744                                 } else {
745                                         warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
746                                         continue;
747                                 }
748
749                                 sscanf (port, "%" PRIu32, &port_id);
750
751                                 if (port_id >= _plugins[0]->parameter_count()) {
752                                         warning << _("PluginInsert: Auto: port id out of range") << endmsg;
753                                         continue;
754                                 }
755                                 
756                                 if ((cprop = child->property("auto")) != 0) {
757                                         int x;
758                                         sscanf (cprop->value().c_str(), "0x%x", &x);
759                                         automation_list (port_id).set_automation_state (AutoState (x));
760                                 }
761                         }
762                         
763                         break;
764                 }
765         } 
766
767         if (niter == nlist.end()) {
768                 warning << string_compose(_("XML node describing a port automation is missing the `%1' information"), port_automation_node_name) << endmsg;
769         }
770         
771         // The name of the PluginInsert comes from the plugin, nothing else
772         set_name(plugin->get_info().name,this);
773         
774         return 0;
775 }
776
777 string
778 PluginInsert::describe_parameter (uint32_t what)
779 {
780         return _plugins[0]->describe_parameter (what);
781 }
782
783 void
784 PluginInsert::reset_midi_control (MIDI::Port* port, bool on)
785 {
786         _plugins[0]->reset_midi_control (port, on);
787 }
788
789 void
790 PluginInsert::send_all_midi_feedback ()
791 {
792         _plugins[0]->send_all_midi_feedback();
793 }
794
795 jack_nframes_t 
796 PluginInsert::latency() 
797 {
798         return _plugins[0]->latency ();
799 }
800         
801 void
802 PluginInsert::store_state (PluginInsertState& state) const
803 {
804         Redirect::store_state (state);
805         _plugins[0]->store_state (state.plugin_state);
806 }
807
808 Change
809 PluginInsert::restore_state (StateManager::State& state)
810 {
811         PluginInsertState* pistate = dynamic_cast<PluginInsertState*> (&state);
812
813         Redirect::restore_state (state);
814
815         _plugins[0]->restore_state (pistate->plugin_state);
816
817         return Change (0);
818 }
819
820 StateManager::State*
821 PluginInsert::state_factory (std::string why) const
822 {
823         PluginInsertState* state = new PluginInsertState (why);
824
825         store_state (*state);
826
827         return state;
828 }
829
830 /***************************************************************
831  Port inserts: send output to a port, pick up input at a port
832  ***************************************************************/
833
834 PortInsert::PortInsert (Session& s, Placement p)
835         : Insert (s, p, 1, -1, 1, -1)
836 {
837         init ();
838         save_state (_("initial state"));
839         RedirectCreated (this); /* EMIT SIGNAL */
840 }
841
842 PortInsert::PortInsert (const PortInsert& other)
843         : Insert (other._session, other.placement(), 1, -1, 1, -1)
844 {
845         init ();
846         save_state (_("initial state"));
847         RedirectCreated (this); /* EMIT SIGNAL */
848 }
849
850 void
851 PortInsert::init ()
852 {
853         if (add_input_port ("", this)) {
854                 error << _("PortInsert: cannot add input port") << endmsg;
855                 throw failed_constructor();
856         }
857         
858         if (add_output_port ("", this)) {
859                 error << _("PortInsert: cannot add output port") << endmsg;
860                 throw failed_constructor();
861         }
862 }
863
864 PortInsert::PortInsert (Session& s, const XMLNode& node)
865         : Insert (s, "will change", PreFader)
866 {
867         if (set_state (node)) {
868                 throw failed_constructor();
869         }
870
871         RedirectCreated (this); /* EMIT SIGNAL */
872 }
873
874 PortInsert::~PortInsert ()
875 {
876         GoingAway (this);
877 }
878
879 void
880 PortInsert::run (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
881 {
882         if (n_outputs() == 0) {
883                 return;
884         }
885
886         if (!active()) {
887                 /* deliver silence */
888                 silence (nframes, offset);
889                 return;
890         }
891
892         uint32_t n;
893         vector<Port*>::iterator o;
894         vector<Port*>::iterator i;
895
896         /* deliver output */
897
898         for (o = _outputs.begin(), n = 0; o != _outputs.end(); ++o, ++n) {
899                 memcpy ((*o)->get_buffer (nframes) + offset, bufs[min(nbufs,n)], sizeof (Sample) * nframes);
900                 (*o)->mark_silence (false);
901         }
902         
903         /* collect input */
904         
905         for (i = _inputs.begin(), n = 0; i != _inputs.end(); ++i, ++n) {
906                 memcpy (bufs[min(nbufs,n)], (*i)->get_buffer (nframes) + offset, sizeof (Sample) * nframes);
907         }
908 }
909
910 XMLNode&
911 PortInsert::get_state(void)
912 {
913         return state (true);
914 }
915
916 XMLNode&
917 PortInsert::state (bool full)
918 {
919         XMLNode *node = new XMLNode("Insert");
920
921         node->add_child_nocopy (Redirect::state(full)); 
922         node->add_property("type", "port");
923
924         return *node;
925 }
926
927 int
928 PortInsert::set_state(const XMLNode& node)
929 {
930         XMLNodeList nlist = node.children();
931         XMLNodeIterator niter;
932         XMLPropertyList plist;
933         const XMLProperty *prop;
934
935         if ((prop = node.property ("type")) == 0) {
936                 error << _("XML node describing insert is missing the `type' field") << endmsg;
937                 return -1;
938         }
939         
940         if (prop->value() != "port") {
941                 error << _("non-port insert XML used for port plugin insert") << endmsg;
942                 return -1;
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 jack_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() == -1 && output_maximum() == -1) {
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() == 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 (in);
1014         set_output_minimum (in);
1015         set_input_maximum (out);
1016         set_input_minimum (out);
1017
1018         if (in < 0) {
1019                 in = n_outputs ();
1020         } 
1021
1022         if (out < 0) {
1023                 out = n_inputs ();
1024         }
1025
1026         return ensure_io (out, 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 ();
1034 }
1035
1036 uint32_t
1037 PortInsert::output_streams() const
1038 {
1039         return n_inputs ();
1040 }
1041
1042 uint32_t
1043 PortInsert::input_streams() const
1044 {
1045         return n_outputs ();
1046 }