Separate audio and MIDI disk buffer size (and track read ahead) parameters.
[ardour.git] / libs / ardour / io.cc
1 /*
2     Copyright (C) 2000-2006 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 #include <fstream>
20 #include <algorithm>
21 #include <unistd.h>
22 #include <locale.h>
23 #include <errno.h>
24
25 #include <sigc++/bind.h>
26
27 #include <glibmm/thread.h>
28
29 #include <pbd/xml++.h>
30 #include <pbd/replace_all.h>
31 #include <pbd/unknown_type.h>
32
33 #include <ardour/audioengine.h>
34 #include <ardour/io.h>
35 #include <ardour/route.h>
36 #include <ardour/port.h>
37 #include <ardour/audio_port.h>
38 #include <ardour/midi_port.h>
39 #include <ardour/auto_bundle.h>
40 #include <ardour/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/buffer_set.h>
44 #include <ardour/meter.h>
45 #include <ardour/amp.h>
46
47 #include "i18n.h"
48
49 #include <cmath>
50
51 /*
52   A bug in OS X's cmath that causes isnan() and isinf() to be 
53   "undeclared". the following works around that
54 */
55
56 #if defined(__APPLE__) && defined(__MACH__)
57 extern "C" int isnan (double);
58 extern "C" int isinf (double);
59 #endif
60
61 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
62
63 using namespace std;
64 using namespace ARDOUR;
65 using namespace PBD;
66
67 const string                 IO::state_node_name = "IO";
68 bool                         IO::connecting_legal = false;
69 bool                         IO::ports_legal = false;
70 bool                         IO::panners_legal = false;
71 sigc::signal<void>           IO::Meter;
72 sigc::signal<int>            IO::ConnectingLegal;
73 sigc::signal<int>            IO::PortsLegal;
74 sigc::signal<int>            IO::PannersLegal;
75 sigc::signal<void,ChanCount> IO::PortCountChanged;
76 sigc::signal<int>            IO::PortsCreated;
77
78 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
79
80 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
81    others can be imagined. 
82 */
83
84 #if 0
85 static gain_t direct_control_to_gain (double fract) { 
86         /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
87         /* this maxes at +6dB */
88         return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
89 }
90
91 static double direct_gain_to_control (gain_t gain) { 
92         /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
93         if (gain == 0) return 0.0;
94         
95         return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
96 }
97 #endif
98
99 /** @param default_type The type of port that will be created by ensure_io
100  * and friends if no type is explicitly requested (to avoid breakage).
101  */
102 IO::IO (Session& s, const string& name,
103         int input_min, int input_max, int output_min, int output_max,
104         DataType default_type, bool public_ports)
105         : Automatable (s, name),
106           _output_buffers (new BufferSet()),
107           _active(true),
108           _default_type (default_type),
109           _public_ports (public_ports),
110           _input_minimum (ChanCount::ZERO),
111           _input_maximum (ChanCount::INFINITE),
112           _output_minimum (ChanCount::ZERO),
113           _output_maximum (ChanCount::INFINITE)
114 {
115         _panner = new Panner (name, _session);
116         _meter = new PeakMeter (_session);
117
118         if (input_min > 0) {
119                 _input_minimum = ChanCount(_default_type, input_min);
120         }
121         if (input_max >= 0) {
122                 _input_maximum = ChanCount(_default_type, input_max);
123         }
124         if (output_min > 0) {
125                 _output_minimum = ChanCount(_default_type, output_min);
126         }
127         if (output_max >= 0) {
128                 _output_maximum = ChanCount(_default_type, output_max);
129         }
130
131         _gain = 1.0;
132         _desired_gain = 1.0;
133         pending_state_node = 0;
134         no_panner_reset = false;
135         _phase_invert = false;
136         deferred_state = 0;
137
138         boost::shared_ptr<AutomationList> gl(
139                         new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
140
141         _gain_control = boost::shared_ptr<GainControl>(
142                         new GainControl(X_("gaincontrol"), *this, gl));
143
144         add_control(_gain_control);
145
146         apply_gain_automation = false;
147         
148         {
149                 // IO::Meter is emitted from another thread so the
150                 // Meter signal must be protected.
151                 Glib::Mutex::Lock guard (m_meter_signal_lock);
152                 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
153         }
154         
155         // Connect to our own PortCountChanged signal to connect output buffers
156         IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
157
158         _session.add_controllable (_gain_control);
159
160         create_bundles_for_inputs_and_outputs ();
161 }
162
163 IO::IO (Session& s, const XMLNode& node, DataType dt)
164         : Automatable (s, "unnamed io"),
165       _output_buffers (new BufferSet()),
166           _active(true),
167           _default_type (dt)
168 {
169         _meter = new PeakMeter (_session);
170         _public_ports = true; // XXX get this from node
171         _panner = 0;
172         deferred_state = 0;
173         no_panner_reset = false;
174         _desired_gain = 1.0;
175         _gain = 1.0;
176
177         apply_gain_automation = false;
178         
179         boost::shared_ptr<AutomationList> gl(
180                         new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
181
182         _gain_control = boost::shared_ptr<GainControl>(
183                         new GainControl(X_("gaincontrol"), *this, gl));
184
185         add_control(_gain_control);
186
187         set_state (node);
188
189         {
190                 // IO::Meter is emitted from another thread so the
191                 // Meter signal must be protected.
192                 Glib::Mutex::Lock guard (m_meter_signal_lock);
193                 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
194         }
195         
196         // Connect to our own PortCountChanged signal to connect output buffers
197         IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
198
199         _session.add_controllable (_gain_control);
200
201         create_bundles_for_inputs_and_outputs ();
202 }
203
204 IO::~IO ()
205 {
206         Glib::Mutex::Lock guard (m_meter_signal_lock);
207         Glib::Mutex::Lock lm (io_lock);
208
209         BLOCK_PROCESS_CALLBACK ();
210
211         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
212                 _session.engine().unregister_port (*i);
213         }
214
215         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
216                 _session.engine().unregister_port (*i);
217         }
218
219         m_meter_connection.disconnect();
220
221         delete _meter;
222         delete _panner;
223         delete _output_buffers;
224 }
225
226 void
227 IO::silence (nframes_t nframes, nframes_t offset)
228 {
229         /* io_lock, not taken: function must be called from Session::process() calltree */
230
231         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
232                 i->get_buffer().silence (nframes, offset);
233         }
234 }
235
236 /** Deliver bufs to the IO's output ports
237  *
238  * This function should automatically do whatever it necessary to correctly deliver bufs
239  * to the outputs, eg applying gain or pan or whatever else needs to be done.
240  */
241 void
242 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
243 {
244         // FIXME: type specific code doesn't actually need to be here, it will go away in time
245
246         /* ********** AUDIO ********** */
247
248         // Apply gain if gain automation isn't playing
249         if ( ! apply_gain_automation) {
250                 
251                 gain_t dg = _gain; // desired gain
252
253                 {
254                         Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
255
256                         if (dm.locked()) {
257                                 dg = _desired_gain;
258                         }
259
260                 }
261
262                 if (dg != _gain || dg != 1.0)
263                         Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
264         }
265         
266         // Use the panner to distribute audio to output port buffers
267         if (_panner && !_panner->empty() && !_panner->bypassed()) {
268                 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
269         } else {
270                 const DataType type = DataType::AUDIO;
271                 
272                 // Copy any audio 1:1 to outputs
273                 
274                 BufferSet::iterator o = output_buffers().begin(type);
275                 BufferSet::iterator i = bufs.begin(type);
276                 BufferSet::iterator prev = i;
277                 
278                 while (i != bufs.end(type) && o != output_buffers().end (type)) {
279                         o->read_from(*i, nframes, offset);
280                         prev = i;
281                         ++i;
282                         ++o;
283                 }
284
285                 /* extra outputs get a copy of the last buffer */
286
287                 while (o != output_buffers().end(type)) {
288                         o->read_from(*prev, nframes, offset);
289                         ++o;
290                 }
291         }
292
293         /* ********** MIDI ********** */
294
295         // No MIDI, we're done here
296         if (bufs.count().n_midi() == 0) {
297                 return;
298         }
299
300         const DataType type = DataType::MIDI;
301
302         // Copy any MIDI 1:1 to outputs
303         assert(bufs.count().n_midi() == output_buffers().count().n_midi());
304         BufferSet::iterator o = output_buffers().begin(type);
305         for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
306                 o->read_from(*i, nframes, offset);
307         }
308 }
309
310 void
311 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
312 {
313         assert(outs.available() >= n_inputs());
314         
315         if (n_inputs() == ChanCount::ZERO)
316                 return;
317
318         outs.set_count(n_inputs());
319         
320         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
321                 
322                 BufferSet::iterator o = outs.begin(*t);
323                 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
324                         o->read_from(i->get_buffer(), nframes, offset);
325                 }
326
327         }
328 }
329
330 void
331 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame, 
332                       nframes_t nframes, nframes_t offset)
333 {
334         BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
335
336         collect_input (bufs, nframes, offset);
337
338         _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
339 }
340
341
342 void
343 IO::check_bundles_connected_to_inputs ()
344 {
345         check_bundles (_bundles_connected_to_inputs, inputs());
346 }
347
348 void
349 IO::check_bundles_connected_to_outputs ()
350 {
351         check_bundles (_bundles_connected_to_outputs, outputs());
352 }
353
354 void
355 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
356 {
357         std::vector<UserBundleInfo> new_list;
358         
359         for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
360
361                 uint32_t const N = i->bundle->nchannels ();
362
363                 if (ports.num_ports() < N) {
364                         continue;
365                 }
366
367                 bool ok = true;
368                 for (uint32_t j = 0; j < N; ++j) {
369                         /* Every port on bundle channel j must be connected to our input j */
370                         PortList const pl = i->bundle->channel_ports (j);
371                         for (uint32_t k = 0; k < pl.size(); ++k) {
372                                 if (ports.port(j)->connected_to (pl[k]) == false) {
373                                         ok = false;
374                                         break;
375                                 }
376                         }
377
378                         if (ok == false) {
379                                 break;
380                         }
381                 }
382
383                 if (ok) {
384                         new_list.push_back (*i);
385                 } else {
386                         i->configuration_will_change.disconnect ();
387                         i->configuration_has_changed.disconnect ();
388                         i->ports_will_change.disconnect ();
389                         i->ports_have_changed.disconnect ();
390                 }
391         }
392
393         list = new_list;
394 }
395
396
397 int
398 IO::disconnect_input (Port* our_port, string other_port, void* src)
399 {
400         if (other_port.length() == 0 || our_port == 0) {
401                 return 0;
402         }
403
404         { 
405                 BLOCK_PROCESS_CALLBACK ();
406                 
407                 {
408                         Glib::Mutex::Lock lm (io_lock);
409                         
410                         /* check that our_port is really one of ours */
411                         
412                         if ( ! _inputs.contains(our_port)) {
413                                 return -1;
414                         }
415                         
416                         /* disconnect it from the source */
417                         
418                         if (_session.engine().disconnect (other_port, our_port->name())) {
419                                 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
420                                 return -1;
421                         }
422
423                         check_bundles_connected_to_inputs ();
424                 }
425         }
426
427         input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
428         _session.set_dirty ();
429
430         return 0;
431 }
432
433 int
434 IO::connect_input (Port* our_port, string other_port, void* src)
435 {
436         if (other_port.length() == 0 || our_port == 0) {
437                 return 0;
438         }
439
440         {
441                 BLOCK_PROCESS_CALLBACK ();
442                 
443                 {
444                         Glib::Mutex::Lock lm (io_lock);
445                         
446                         /* check that our_port is really one of ours */
447                         
448                         if ( ! _inputs.contains(our_port) ) {
449                                 return -1;
450                         }
451                         
452                         /* connect it to the source */
453
454                         if (_session.engine().connect (other_port, our_port->name())) {
455                                 return -1;
456                         }
457                 }
458         }
459
460         input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
461         _session.set_dirty ();
462         return 0;
463 }
464
465 int
466 IO::disconnect_output (Port* our_port, string other_port, void* src)
467 {
468         if (other_port.length() == 0 || our_port == 0) {
469                 return 0;
470         }
471
472         {
473                 BLOCK_PROCESS_CALLBACK ();
474                 
475                 {
476                         Glib::Mutex::Lock lm (io_lock);
477                         
478                         /* check that our_port is really one of ours */
479                         
480                         if ( ! _outputs.contains(our_port) ) {
481                                 return -1;
482                         }
483                         
484                         /* disconnect it from the destination */
485                         
486                         if (_session.engine().disconnect (our_port->name(), other_port)) {
487                                 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
488                                 return -1;
489                         }
490
491                         check_bundles_connected_to_outputs ();
492                 }
493         }
494
495         output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
496         _session.set_dirty ();
497         return 0;
498 }
499
500 int
501 IO::connect_output (Port* our_port, string other_port, void* src)
502 {
503         if (other_port.length() == 0 || our_port == 0) {
504                 return 0;
505         }
506
507         {
508                 BLOCK_PROCESS_CALLBACK ();
509
510                 
511                 {
512                         Glib::Mutex::Lock lm (io_lock);
513                         
514                         /* check that our_port is really one of ours */
515                         
516                         if ( ! _outputs.contains(our_port) ) {
517                                 return -1;
518                         }
519                         
520                         /* connect it to the destination */
521                         
522                         if (_session.engine().connect (our_port->name(), other_port)) {
523                                 return -1;
524                         }
525                 }
526         }
527
528         output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
529         _session.set_dirty ();
530         return 0;
531 }
532
533 int
534 IO::set_input (Port* other_port, void* src)
535 {
536         /* this removes all but one ports, and connects that one port
537            to the specified source.
538         */
539
540         if (_input_minimum.n_total() > 1) {
541                 /* sorry, you can't do this */
542                 return -1;
543         }
544
545         if (other_port == 0) {
546                 if (_input_minimum == ChanCount::ZERO) {
547                         return ensure_inputs (ChanCount::ZERO, false, true, src);
548                 } else {
549                         return -1;
550                 }
551         }
552
553         if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
554                 return -1;
555         }
556
557         return connect_input (_inputs.port(0), other_port->name(), src);
558 }
559
560 int
561 IO::remove_output_port (Port* port, void* src)
562 {
563         IOChange change (NoChange);
564
565         {
566                 BLOCK_PROCESS_CALLBACK ();
567
568                 
569                 {
570                         Glib::Mutex::Lock lm (io_lock);
571
572                         if (n_outputs() <= _output_minimum) {
573                                 /* sorry, you can't do this */
574                                 return -1;
575                         }
576
577                         if (_outputs.remove(port)) {
578                                 change = IOChange (change|ConfigurationChanged);
579
580                                 if (port->connected()) {
581                                         change = IOChange (change|ConnectionsChanged);
582                                 } 
583
584                                 _session.engine().unregister_port (*port);
585                                 check_bundles_connected_to_outputs ();
586                                 
587                                 setup_peak_meters ();
588                                 reset_panner ();
589                         }
590                 }
591
592                 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
593         }
594
595         if (change == ConnectionsChanged) {
596                 setup_bundles_for_inputs_and_outputs ();
597         }
598
599         if (change != NoChange) {
600                 output_changed (change, src);
601                 _session.set_dirty ();
602                 return 0;
603         }
604
605         return -1;
606 }
607
608 /** Add an output port.
609  *
610  * @param destination Name of input port to connect new port to.
611  * @param src Source for emitted ConfigurationChanged signal.
612  * @param type Data type of port.  Default value (NIL) will use this IO's default type.
613  */
614 int
615 IO::add_output_port (string destination, void* src, DataType type)
616 {
617         Port* our_port;
618
619         if (type == DataType::NIL)
620                 type = _default_type;
621
622         {
623                 BLOCK_PROCESS_CALLBACK ();
624
625                 
626                 { 
627                         Glib::Mutex::Lock lm (io_lock);
628                         
629                         if (n_outputs() >= _output_maximum) {
630                                 return -1;
631                         }
632                 
633                         /* Create a new output port */
634                         
635                         string portname = build_legal_port_name (type, false);
636                         
637                         if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
638                                 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
639                                 return -1;
640                         }
641                         
642                         _outputs.add (our_port);
643                         setup_peak_meters ();
644                         reset_panner ();
645                 }
646
647                 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
648         }
649
650         if (destination.length()) {
651                 if (_session.engine().connect (our_port->name(), destination)) {
652                         return -1;
653                 }
654         }
655         
656         // pan_changed (src); /* EMIT SIGNAL */
657         output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
658         setup_bundles_for_inputs_and_outputs ();
659         _session.set_dirty ();
660
661         return 0;
662 }
663
664 int
665 IO::remove_input_port (Port* port, void* src)
666 {
667         IOChange change (NoChange);
668
669         {
670                 BLOCK_PROCESS_CALLBACK ();
671
672                 
673                 {
674                         Glib::Mutex::Lock lm (io_lock);
675
676                         if (n_inputs() <= _input_minimum) {
677                                 /* sorry, you can't do this */
678                                 return -1;
679                         }
680
681                         if (_inputs.remove(port)) {
682                                 change = IOChange (change|ConfigurationChanged);
683
684                                 if (port->connected()) {
685                                         change = IOChange (change|ConnectionsChanged);
686                                 } 
687
688                                 _session.engine().unregister_port (*port);
689                                 check_bundles_connected_to_inputs ();
690                                 
691                                 setup_peak_meters ();
692                                 reset_panner ();
693                         }
694                 }
695                 
696                 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
697         }
698
699         if (change == ConfigurationChanged) {
700                 setup_bundles_for_inputs_and_outputs ();
701         }
702
703         if (change != NoChange) {
704                 input_changed (change, src);
705                 _session.set_dirty ();
706                 return 0;
707         } 
708         
709         return -1;
710 }
711
712
713 /** Add an input port.
714  *
715  * @param type Data type of port.  The appropriate port type, and @ref Port will be created.
716  * @param destination Name of input port to connect new port to.
717  * @param src Source for emitted ConfigurationChanged signal.
718  */
719 int
720 IO::add_input_port (string source, void* src, DataType type)
721 {
722         Port* our_port;
723         
724         if (type == DataType::NIL)
725                 type = _default_type;
726
727         {
728                 BLOCK_PROCESS_CALLBACK ();
729                 
730                 { 
731                         Glib::Mutex::Lock lm (io_lock);
732
733                         if (n_inputs() >= _input_maximum) {
734                                 return -1;
735                         }
736
737                         /* Create a new input port */
738                         
739                         string portname = build_legal_port_name (type, true);
740
741                         if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
742                                 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
743                                 return -1;
744                         }
745
746                         _inputs.add (our_port);
747                         setup_peak_meters ();
748                         reset_panner ();
749                 }
750
751                 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
752         }
753
754         if (source.length()) {
755
756                 if (_session.engine().connect (source, our_port->name())) {
757                         return -1;
758                 }
759         } 
760
761         // pan_changed (src); /* EMIT SIGNAL */
762         input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
763         setup_bundles_for_inputs_and_outputs ();
764         _session.set_dirty ();
765         
766         return 0;
767 }
768
769 int
770 IO::disconnect_inputs (void* src)
771 {
772         { 
773                 BLOCK_PROCESS_CALLBACK ();
774                 
775                 {
776                         Glib::Mutex::Lock lm (io_lock);
777                         
778                         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
779                                 _session.engine().disconnect (*i);
780                         }
781
782                         check_bundles_connected_to_inputs ();
783                 }
784         }
785         
786         input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
787         
788         return 0;
789 }
790
791 int
792 IO::disconnect_outputs (void* src)
793 {
794         {
795                 BLOCK_PROCESS_CALLBACK ();
796                 
797                 {
798                         Glib::Mutex::Lock lm (io_lock);
799                         
800                         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
801                                 _session.engine().disconnect (*i);
802                         }
803
804                         check_bundles_connected_to_outputs ();
805                 }
806         }
807
808         output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
809         _session.set_dirty ();
810         
811         return 0;
812 }
813
814 bool
815 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
816 {
817         Port* input_port = 0;
818         bool  changed    = false;
819
820
821         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
822                 
823                 const size_t n = count.get(*t);
824         
825                 /* remove unused ports */
826                 for (size_t i = n_inputs().get(*t); i > n; --i) {
827                         input_port = _inputs.port(*t, i-1);
828
829                         assert(input_port);
830                         _inputs.remove(input_port);
831                         _session.engine().unregister_port (*input_port);
832
833                         changed = true;
834                 }
835
836                 /* create any necessary new ports */
837                 while (n_inputs().get(*t) < n) {
838
839                         string portname = build_legal_port_name (*t, true);
840
841                         try {
842
843                                 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
844                                         error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
845                                         return -1;
846                                 }
847                         }
848
849                         catch (AudioEngine::PortRegistrationFailure& err) {
850                                 setup_peak_meters ();
851                                 reset_panner ();
852                                 /* pass it on */
853                                 throw AudioEngine::PortRegistrationFailure();
854                         }
855
856                         _inputs.add (input_port);
857                         changed = true;
858                 }
859         }
860         
861         if (changed) {
862                 check_bundles_connected_to_inputs ();
863                 setup_peak_meters ();
864                 reset_panner ();
865                 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
866                 _session.set_dirty ();
867         }
868         
869         if (clear) {
870                 /* disconnect all existing ports so that we get a fresh start */
871                 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
872                         _session.engine().disconnect (*i);
873                 }
874         }
875
876         return changed;
877 }
878
879 /** Attach output_buffers to port buffers.
880  * 
881  * Connected to IO's own PortCountChanged signal.
882  */
883 void
884 IO::attach_buffers(ChanCount ignored)
885 {
886         _output_buffers->attach_buffers(_outputs);
887 }
888
889 int
890 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
891 {
892         bool in_changed     = false;
893         bool out_changed    = false;
894         bool need_pan_reset = false;
895
896         in = min (_input_maximum, in);
897
898         out = min (_output_maximum, out);
899
900         if (in == n_inputs() && out == n_outputs() && !clear) {
901                 return 0;
902         }
903
904         {
905                 BLOCK_PROCESS_CALLBACK ();
906                 Glib::Mutex::Lock lm (io_lock);
907
908                 Port* port;
909                 
910                 if (n_outputs() != out) {
911                         need_pan_reset = true;
912                 }
913                 
914                 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
915
916                         const size_t nin = in.get(*t);
917                         const size_t nout = out.get(*t);
918
919                         Port* output_port = 0;
920                         Port* input_port = 0;
921
922                         /* remove unused output ports */
923                         for (size_t i = n_outputs().get(*t); i > nout; --i) {
924                                 output_port = _outputs.port(*t, i-1);
925
926                                 assert(output_port);
927                                 _outputs.remove(output_port);
928                                 _session.engine().unregister_port (*output_port);
929
930                                 out_changed = true;
931                         }
932
933                         /* remove unused input ports */
934                         for (size_t i = n_inputs().get(*t); i > nin; --i) {
935                                 input_port = _inputs.port(*t, i-1);
936
937                                 assert(input_port);
938                                 _inputs.remove(input_port);
939                                 _session.engine().unregister_port (*input_port);
940
941                                 in_changed = true;
942                         }
943
944                         /* create any necessary new input ports */
945
946                         while (n_inputs().get(*t) < nin) {
947
948                                 string portname = build_legal_port_name (*t, true);
949
950                                 try {
951                                         if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
952                                                 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
953                                                 return -1;
954                                         }
955                                 }
956                                 
957                                 catch (AudioEngine::PortRegistrationFailure& err) {
958                                         setup_peak_meters ();
959                                         reset_panner ();
960                                         /* pass it on */
961                                         throw AudioEngine::PortRegistrationFailure();
962                                 }
963
964                                 _inputs.add (port);
965                                 in_changed = true;
966                         }
967
968                         /* create any necessary new output ports */
969
970                         while (n_outputs().get(*t) < nout) {
971
972                                 string portname = build_legal_port_name (*t, false);
973                                 
974                                 try { 
975                                         if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
976                                                 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
977                                                 return -1;
978                                         }
979                                 }
980
981                                 catch (AudioEngine::PortRegistrationFailure& err) {
982                                         setup_peak_meters ();
983                                         reset_panner ();
984                                         /* pass it on */
985                                         throw AudioEngine::PortRegistrationFailure ();
986                                 }
987
988                                 _outputs.add (port);
989                                 out_changed = true;
990                         }
991                 }
992                 
993                 if (clear) {
994                         
995                         /* disconnect all existing ports so that we get a fresh start */
996                         
997                         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
998                                 _session.engine().disconnect (*i);
999                         }
1000                         
1001                         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1002                                 _session.engine().disconnect (*i);
1003                         }
1004                 }
1005                 
1006                 if (in_changed || out_changed) {
1007                         setup_peak_meters ();
1008                         reset_panner ();
1009                 }
1010         }
1011
1012         if (out_changed) {
1013                 check_bundles_connected_to_outputs ();
1014                 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1015         }
1016         
1017         if (in_changed) {
1018                 check_bundles_connected_to_inputs ();
1019                 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1020         }
1021
1022         if (in_changed || out_changed) {
1023                 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1024                 setup_bundles_for_inputs_and_outputs ();
1025                 _session.set_dirty ();
1026         }
1027
1028         return 0;
1029 }
1030
1031 int
1032 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1033 {
1034         bool changed = false;
1035
1036         count = min (_input_maximum, count);
1037
1038         if (count == n_inputs() && !clear) {
1039                 return 0;
1040         }
1041
1042         if (lockit) {
1043                 BLOCK_PROCESS_CALLBACK ();
1044                 Glib::Mutex::Lock im (io_lock);
1045                 changed = ensure_inputs_locked (count, clear, src);
1046         } else {
1047                 changed = ensure_inputs_locked (count, clear, src);
1048         }
1049
1050         if (changed) {
1051                 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1052                 setup_bundles_for_inputs_and_outputs ();
1053                 _session.set_dirty ();
1054         }
1055         return 0;
1056 }
1057
1058 bool
1059 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1060 {
1061         Port* output_port    = 0;
1062         bool  changed        = false;
1063         bool  need_pan_reset = false;
1064
1065         if (n_outputs() != count) {
1066                 need_pan_reset = true;
1067         }
1068         
1069         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1070
1071                 const size_t n = count.get(*t);
1072
1073                 /* remove unused ports */
1074                 for (size_t i = n_outputs().get(*t); i > n; --i) {
1075                         output_port = _outputs.port(*t, i-1);
1076
1077                         assert(output_port);
1078                         _outputs.remove(output_port);
1079                         _session.engine().unregister_port (*output_port);
1080
1081                         changed = true;
1082                 }
1083
1084                 /* create any necessary new ports */
1085                 while (n_outputs().get(*t) < n) {
1086
1087                         string portname = build_legal_port_name (*t, false);
1088
1089                         if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1090                                 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1091                                 return -1;
1092                         }
1093
1094                         _outputs.add (output_port);
1095                         changed = true;
1096                         setup_peak_meters ();
1097
1098                         if (need_pan_reset) {
1099                                 reset_panner ();
1100                         }
1101                 }
1102         }
1103         
1104         if (changed) {
1105                 check_bundles_connected_to_outputs ();
1106                 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1107                 _session.set_dirty ();
1108         }
1109         
1110         if (clear) {
1111                 /* disconnect all existing ports so that we get a fresh start */
1112                 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1113                         _session.engine().disconnect (*i);
1114                 }
1115         }
1116
1117         return changed;
1118 }
1119
1120 int
1121 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1122 {
1123         bool changed = false;
1124
1125         if (_output_maximum < ChanCount::INFINITE) {
1126                 count = min (_output_maximum, count);
1127                 if (count == n_outputs() && !clear) {
1128                         return 0;
1129                 }
1130         }
1131
1132         /* XXX caller should hold io_lock, but generally doesn't */
1133
1134         if (lockit) {
1135                 BLOCK_PROCESS_CALLBACK ();
1136                 Glib::Mutex::Lock im (io_lock);
1137                 changed = ensure_outputs_locked (count, clear, src);
1138         } else {
1139                 changed = ensure_outputs_locked (count, clear, src);
1140         }
1141
1142         if (changed) {
1143                  output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1144                  setup_bundles_for_inputs_and_outputs ();
1145         }
1146
1147         return 0;
1148 }
1149
1150 gain_t
1151 IO::effective_gain () const
1152 {
1153         if (_gain_control->list()->automation_playback()) {
1154                 return _gain_control->get_value();
1155         } else {
1156                 return _desired_gain;
1157         }
1158 }
1159
1160 void
1161 IO::reset_panner ()
1162 {
1163         if (panners_legal) {
1164                 if (!no_panner_reset) {
1165                         _panner->reset (n_outputs().n_audio(), pans_required());
1166                 }
1167         } else {
1168                 panner_legal_c.disconnect ();
1169                 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1170         }
1171 }
1172
1173 int
1174 IO::panners_became_legal ()
1175 {
1176         _panner->reset (n_outputs().n_audio(), pans_required());
1177         _panner->load (); // automation
1178         panner_legal_c.disconnect ();
1179         return 0;
1180 }
1181
1182 void
1183 IO::defer_pan_reset ()
1184 {
1185         no_panner_reset = true;
1186 }
1187
1188 void
1189 IO::allow_pan_reset ()
1190 {
1191         no_panner_reset = false;
1192         reset_panner ();
1193 }
1194
1195
1196 XMLNode&
1197 IO::get_state (void)
1198 {
1199         return state (true);
1200 }
1201
1202 XMLNode&
1203 IO::state (bool full_state)
1204 {
1205         XMLNode* node = new XMLNode (state_node_name);
1206         char buf[64];
1207         string str;
1208         vector<string>::iterator ci;
1209         int n;
1210         LocaleGuard lg (X_("POSIX"));
1211         Glib::Mutex::Lock lm (io_lock);
1212
1213         node->add_property("name", _name);
1214         id().print (buf, sizeof (buf));
1215         node->add_property("id", buf);
1216
1217         for (
1218           std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1219           i != _bundles_connected_to_inputs.end();
1220           ++i
1221           )
1222         {
1223                 XMLNode* n = new XMLNode ("InputBundle");
1224                 n->add_property ("name", i->bundle->name ());
1225                 node->add_child_nocopy (*n);
1226         }
1227
1228         for (
1229           std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1230           i != _bundles_connected_to_outputs.end();
1231           ++i
1232           )
1233         {
1234                 XMLNode* n = new XMLNode ("OutputBundle");
1235                 n->add_property ("name", i->bundle->name ());
1236                 node->add_child_nocopy (*n);
1237         }
1238         
1239         str = "";
1240
1241         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1242                         
1243                 vector<string> connections;
1244
1245                 if (i->get_connections (connections)) {
1246
1247                         str += '{';
1248                         
1249                         for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1250                                 if (n) {
1251                                         str += ',';
1252                                 }
1253                                 
1254                                 /* if its a connection to our own port,
1255                                    return only the port name, not the
1256                                    whole thing. this allows connections
1257                                    to be re-established even when our
1258                                    client name is different.
1259                                 */
1260                                 
1261                                 str += _session.engine().make_port_name_relative (*ci);
1262                         }       
1263                         
1264                         str += '}';
1265
1266                 } else {
1267                         str += "{}";
1268                 }
1269         }
1270         
1271         node->add_property ("inputs", str);
1272
1273         str = "";
1274         
1275         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1276                 
1277                 vector<string> connections;
1278
1279                 if (i->get_connections (connections)) {
1280                         
1281                         str += '{';
1282                         
1283                         for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1284                                 if (n) {
1285                                         str += ',';
1286                                 }
1287                                 
1288                                 str += _session.engine().make_port_name_relative (*ci);
1289                         }
1290                         
1291                         str += '}';
1292
1293                 } else {
1294                         str += "{}";
1295                 }
1296         }
1297         
1298         node->add_property ("outputs", str);
1299
1300         node->add_child_nocopy (_panner->state (full_state));
1301         node->add_child_nocopy (_gain_control->get_state ());
1302
1303         snprintf (buf, sizeof(buf), "%2.12f", gain());
1304         node->add_property ("gain", buf);
1305
1306         /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1307            as -1.
1308         */
1309
1310         int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1311         int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1312
1313         snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1314
1315         node->add_property ("iolimits", buf);
1316
1317         /* automation */
1318         
1319         if (full_state)
1320                 node->add_child_nocopy (get_automation_state());
1321
1322         return *node;
1323 }
1324
1325 int
1326 IO::set_state (const XMLNode& node)
1327 {
1328         const XMLProperty* prop;
1329         XMLNodeConstIterator iter;
1330         LocaleGuard lg (X_("POSIX"));
1331
1332         /* force use of non-localized representation of decimal point,
1333            since we use it a lot in XML files and so forth.
1334         */
1335
1336         if (node.name() != state_node_name) {
1337                 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1338                 return -1;
1339         }
1340
1341         if ((prop = node.property ("name")) != 0) {
1342                 _name = prop->value();
1343                 /* used to set panner name with this, but no more */
1344         } 
1345
1346         if ((prop = node.property ("id")) != 0) {
1347                 _id = prop->value ();
1348         }
1349
1350         int in_min = -1;
1351         int in_max = -1;
1352         int out_min = -1;
1353         int out_max = -1;
1354
1355         if ((prop = node.property ("iolimits")) != 0) {
1356                 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1357                         &in_min, &in_max, &out_min, &out_max);
1358
1359                 /* Correct for the difference between the way we write things to session files and the
1360                    way things are described by ChanCount; see comments in io.h about what the different
1361                    ChanCount values mean. */
1362
1363                 if (in_min < 0) {
1364                         _input_minimum = ChanCount::ZERO;
1365                 } else {
1366                         _input_minimum = ChanCount (_default_type, in_min);
1367                 }
1368
1369                 if (in_max < 0) {
1370                         _input_maximum = ChanCount::INFINITE;
1371                 } else {
1372                         _input_maximum = ChanCount (_default_type, in_max);
1373                 }
1374
1375                 if (out_min < 0) {
1376                         _output_minimum = ChanCount::ZERO;
1377                 } else {
1378                         _output_minimum = ChanCount (_default_type, out_min);
1379                 }
1380                 
1381                 if (out_max < 0) {
1382                         _output_maximum = ChanCount::INFINITE;
1383                 } else {
1384                         _output_maximum = ChanCount (_default_type, out_max);
1385                 }
1386         }
1387         
1388         if ((prop = node.property ("gain")) != 0) {
1389                 set_gain (atof (prop->value().c_str()), this);
1390                 _gain = _desired_gain;
1391         }
1392
1393         if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1394                 /* old school automation handling */
1395         }
1396
1397         for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1398
1399                 if ((*iter)->name() == "Panner") {
1400                         if (_panner == 0) {
1401                                 _panner = new Panner (_name, _session);
1402                         }
1403                         _panner->set_state (**iter);
1404                 }
1405
1406                 if ((*iter)->name() == X_("Automation")) {
1407
1408                         set_automation_state (*(*iter), Parameter(GainAutomation));
1409                 }
1410
1411                 if ((*iter)->name() == X_("controllable")) {
1412                         if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1413                                 _gain_control->set_state (**iter);
1414                         }
1415                 }
1416         }
1417
1418         if (ports_legal) {
1419
1420                 if (create_ports (node)) {
1421                         return -1;
1422                 }
1423
1424         } else {
1425
1426                 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1427         }
1428
1429         if (panners_legal) {
1430                 reset_panner ();
1431         } else {
1432                 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1433         }
1434
1435         if (connecting_legal) {
1436
1437                 if (make_connections (node)) {
1438                         return -1;
1439                 }
1440
1441         } else {
1442                 
1443                 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1444         }
1445
1446         if (!ports_legal || !connecting_legal) {
1447                 pending_state_node = new XMLNode (node);
1448         }
1449
1450         return 0;
1451 }
1452
1453 int
1454 IO::load_automation (string path)
1455 {
1456         string fullpath;
1457         ifstream in;
1458         char line[128];
1459         uint32_t linecnt = 0;
1460         float version;
1461         LocaleGuard lg (X_("POSIX"));
1462
1463         fullpath = _session.automation_dir();
1464         fullpath += path;
1465
1466         in.open (fullpath.c_str());
1467
1468         if (!in) {
1469                 fullpath = _session.automation_dir();
1470                 fullpath += _session.snap_name();
1471                 fullpath += '-';
1472                 fullpath += path;
1473
1474                 in.open (fullpath.c_str());
1475
1476                 if (!in) {
1477                         error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1478                         return -1;
1479                 }
1480         }
1481
1482         clear_automation ();
1483
1484         while (in.getline (line, sizeof(line), '\n')) {
1485                 char type;
1486                 nframes_t when;
1487                 double value;
1488
1489                 if (++linecnt == 1) {
1490                         if (memcmp (line, "version", 7) == 0) {
1491                                 if (sscanf (line, "version %f", &version) != 1) {
1492                                         error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1493                                         return -1;
1494                                 }
1495                         } else {
1496                                 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1497                                 return -1;
1498                         }
1499
1500                         continue;
1501                 }
1502
1503                 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1504                         warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1505                         continue;
1506                 }
1507
1508                 switch (type) {
1509                 case 'g':
1510                         _gain_control->list()->fast_simple_add (when, value);
1511                         break;
1512
1513                 case 's':
1514                         break;
1515
1516                 case 'm':
1517                         break;
1518
1519                 case 'p':
1520                         /* older (pre-1.0) versions of ardour used this */
1521                         break;
1522
1523                 default:
1524                         warning << _("dubious automation event found (and ignored)") << endmsg;
1525                 }
1526         }
1527
1528         return 0;
1529 }
1530
1531 int
1532 IO::connecting_became_legal ()
1533 {
1534         int ret;
1535
1536         if (pending_state_node == 0) {
1537                 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1538                 /*NOTREACHED*/
1539                 return -1;
1540         }
1541
1542         connection_legal_c.disconnect ();
1543
1544         ret = make_connections (*pending_state_node);
1545
1546         if (ports_legal) {
1547                 delete pending_state_node;
1548                 pending_state_node = 0;
1549         }
1550
1551         return ret;
1552 }
1553 int
1554 IO::ports_became_legal ()
1555 {
1556         int ret;
1557
1558         if (pending_state_node == 0) {
1559                 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1560                 /*NOTREACHED*/
1561                 return -1;
1562         }
1563
1564         port_legal_c.disconnect ();
1565
1566         ret = create_ports (*pending_state_node);
1567
1568         if (connecting_legal) {
1569                 delete pending_state_node;
1570                 pending_state_node = 0;
1571         }
1572
1573         return ret;
1574 }
1575
1576 int
1577 IO::create_ports (const XMLNode& node)
1578 {
1579         XMLProperty const * prop;
1580         int num_inputs = 0;
1581         int num_outputs = 0;
1582
1583         if ((prop = node.property ("inputs")) != 0) {
1584                 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1585         } else if ((prop = node.property ("outputs")) != 0) {
1586                 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1587         }
1588
1589         no_panner_reset = true;
1590
1591         // FIXME: audio-only
1592         if (ensure_io (ChanCount(DataType::AUDIO, num_inputs), ChanCount(DataType::AUDIO, num_outputs), true, this)) {
1593                 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1594                 return -1;
1595         }
1596
1597         no_panner_reset = false;
1598
1599         set_deferred_state ();
1600
1601         PortsCreated();
1602         return 0;
1603 }
1604
1605
1606 int
1607 IO::make_connections (const XMLNode& node)
1608 {
1609         XMLProperty const * prop;
1610         
1611         if ((prop = node.property ("inputs")) != 0) {
1612                 if (set_inputs (prop->value())) {
1613                         error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1614                         return -1;
1615                 }
1616         }
1617
1618                                 
1619         if ((prop = node.property ("outputs")) != 0) {
1620                 if (set_outputs (prop->value())) {
1621                         error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1622                         return -1;
1623                 }
1624         }
1625
1626         for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1627
1628                 if ((*i)->name() == "InputBundle") {
1629                         XMLProperty const * prop = (*i)->property ("name");
1630                         if (prop) {
1631                                 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1632                                 if (b) {
1633                                         connect_input_ports_to_bundle (b, this);
1634                                 } else {
1635                                         error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
1636                                 }
1637                         }
1638                         
1639                 } else if ((*i)->name() == "OutputBundle") {
1640                         XMLProperty const * prop = (*i)->property ("name");
1641                         if (prop) {
1642                                 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1643                                 if (b) {
1644                                         connect_output_ports_to_bundle (b, this);
1645                                 } else {
1646                                         error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
1647                                 }
1648                         }
1649                 }
1650         }
1651         
1652         return 0;
1653 }
1654
1655 int
1656 IO::set_inputs (const string& str)
1657 {
1658         vector<string> ports;
1659         int i;
1660         int n;
1661         uint32_t nports;
1662         
1663         if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1664                 return 0;
1665         }
1666
1667         // FIXME: audio-only
1668         if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1669                 return -1;
1670         }
1671
1672         string::size_type start, end, ostart;
1673
1674         ostart = 0;
1675         start = 0;
1676         end = 0;
1677         i = 0;
1678
1679         while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1680                 start += 1;
1681
1682                 if ((end = str.find_first_of ('}', start)) == string::npos) {
1683                         error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1684                         return -1;
1685                 }
1686
1687                 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1688                         error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1689
1690                         return -1;
1691                         
1692                 } else if (n > 0) {
1693
1694                         for (int x = 0; x < n; ++x) {
1695                                 connect_input (input (i), ports[x], this);
1696                         }
1697                 }
1698
1699                 ostart = end+1;
1700                 i++;
1701         }
1702
1703         return 0;
1704 }
1705
1706 int
1707 IO::set_outputs (const string& str)
1708 {
1709         vector<string> ports;
1710         int i;
1711         int n;
1712         uint32_t nports;
1713         
1714         if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1715                 return 0;
1716         }
1717
1718         // FIXME: audio-only
1719         if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1720                 return -1;
1721         }
1722
1723         string::size_type start, end, ostart;
1724
1725         ostart = 0;
1726         start = 0;
1727         end = 0;
1728         i = 0;
1729
1730         while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1731                 start += 1;
1732
1733                 if ((end = str.find_first_of ('}', start)) == string::npos) {
1734                         error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1735                         return -1;
1736                 }
1737
1738                 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1739                         error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1740
1741                         return -1;
1742                         
1743                 } else if (n > 0) {
1744
1745                         for (int x = 0; x < n; ++x) {
1746                                 connect_output (output (i), ports[x], this);
1747                         }
1748                 }
1749
1750                 ostart = end+1;
1751                 i++;
1752         }
1753
1754         return 0;
1755 }
1756
1757 int
1758 IO::parse_io_string (const string& str, vector<string>& ports)
1759 {
1760         string::size_type pos, opos;
1761
1762         if (str.length() == 0) {
1763                 return 0;
1764         }
1765
1766         pos = 0;
1767         opos = 0;
1768
1769         ports.clear ();
1770
1771         while ((pos = str.find_first_of (',', opos)) != string::npos) {
1772                 ports.push_back (str.substr (opos, pos - opos));
1773                 opos = pos + 1;
1774         }
1775         
1776         if (opos < str.length()) {
1777                 ports.push_back (str.substr(opos));
1778         }
1779
1780         return ports.size();
1781 }
1782
1783 int
1784 IO::parse_gain_string (const string& str, vector<string>& ports)
1785 {
1786         string::size_type pos, opos;
1787
1788         pos = 0;
1789         opos = 0;
1790         ports.clear ();
1791
1792         while ((pos = str.find_first_of (',', opos)) != string::npos) {
1793                 ports.push_back (str.substr (opos, pos - opos));
1794                 opos = pos + 1;
1795         }
1796         
1797         if (opos < str.length()) {
1798                 ports.push_back (str.substr(opos));
1799         }
1800
1801         return ports.size();
1802 }
1803
1804 bool
1805 IO::set_name (const string& requested_name)
1806 {
1807         if (requested_name == _name) {
1808                 return true;
1809         }
1810         
1811         string name;
1812         Route *rt;
1813         if ( (rt = dynamic_cast<Route *>(this))) {
1814                 name = Route::ensure_track_or_route_name(requested_name, _session);
1815         } else {
1816                 name = requested_name;
1817         }
1818
1819
1820         /* replace all colons in the name. i wish we didn't have to do this */
1821
1822         if (replace_all (name, ":", "-")) {
1823                 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1824         }
1825
1826         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1827                 string current_name = i->short_name();
1828                 current_name.replace (current_name.find (_name), _name.length(), name);
1829                 i->set_name (current_name);
1830         }
1831
1832         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1833                 string current_name = i->short_name();
1834                 current_name.replace (current_name.find (_name), _name.length(), name);
1835                 i->set_name (current_name);
1836         }
1837
1838         bool const r = SessionObject::set_name(name);
1839
1840         setup_bundles_for_inputs_and_outputs ();
1841
1842         return r;
1843 }
1844
1845 void
1846 IO::set_input_minimum (ChanCount n)
1847 {
1848         _input_minimum = n;
1849 }
1850
1851 void
1852 IO::set_input_maximum (ChanCount n)
1853 {
1854         _input_maximum = n;
1855 }
1856
1857 void
1858 IO::set_output_minimum (ChanCount n)
1859 {
1860         _output_minimum = n;
1861 }
1862
1863 void
1864 IO::set_output_maximum (ChanCount n)
1865 {
1866         _output_maximum = n;
1867 }
1868
1869 void
1870 IO::set_port_latency (nframes_t nframes)
1871 {
1872         Glib::Mutex::Lock lm (io_lock);
1873
1874         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1875                 i->set_latency (nframes);
1876         }
1877 }
1878
1879 nframes_t
1880 IO::output_latency () const
1881 {
1882         nframes_t max_latency;
1883         nframes_t latency;
1884
1885         max_latency = 0;
1886
1887         /* io lock not taken - must be protected by other means */
1888
1889         for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1890                 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1891                         max_latency = latency;
1892                 }
1893         }
1894
1895         return max_latency;
1896 }
1897
1898 nframes_t
1899 IO::input_latency () const
1900 {
1901         nframes_t max_latency;
1902         nframes_t latency;
1903
1904         max_latency = 0;
1905
1906         /* io lock not taken - must be protected by other means */
1907
1908         for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1909                 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1910                         max_latency = latency;
1911                 } 
1912         }
1913
1914         return max_latency;
1915 }
1916
1917 int
1918 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1919 {
1920         {
1921                 BLOCK_PROCESS_CALLBACK ();
1922                 Glib::Mutex::Lock lm2 (io_lock);
1923
1924                 /* Connect to the bundle, not worrying about any connections
1925                    that are already made. */
1926
1927                 uint32_t const channels = c->nchannels ();
1928                 
1929                 for (uint32_t n = 0; n < channels; ++n) {
1930                         const PortList& pl = c->channel_ports (n);
1931
1932                         for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
1933
1934                           if (!_inputs.port(n)->connected_to (*i)) {
1935                                         
1936                                         if (_session.engine().connect (*i, _inputs.port(n)->name())) {
1937                                                 return -1;
1938                                         }
1939                                 }
1940                                 
1941                         }
1942                 }
1943
1944                 /* If this is a UserBundle, make a note of what we've done */
1945
1946                 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1947                 if (ub) {
1948
1949                         /* See if we already know about this one */
1950                         std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1951                         while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
1952                                 ++i;
1953                         }
1954
1955                         if (i == _bundles_connected_to_inputs.end()) {
1956                                 /* We don't, so make a note */
1957                                 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
1958                         }
1959                 }
1960         }
1961
1962         input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
1963         return 0;
1964 }
1965
1966 int
1967 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1968 {
1969         {
1970                 BLOCK_PROCESS_CALLBACK ();
1971                 Glib::Mutex::Lock lm2 (io_lock);
1972
1973                 /* Connect to the bundle, not worrying about any connections
1974                    that are already made. */
1975
1976                 uint32_t const channels = c->nchannels ();
1977
1978                 for (uint32_t n = 0; n < channels; ++n) {
1979
1980                         const PortList& pl = c->channel_ports (n);
1981
1982                         for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
1983
1984                                 if (!_outputs.port(n)->connected_to (*i)) {
1985                                                 
1986                                         if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
1987                                                 return -1;
1988                                         }
1989                                 }
1990                         }
1991                 }
1992
1993                 /* If this is a UserBundle, make a note of what we've done */
1994
1995                 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1996                 if (ub) {
1997
1998                         /* See if we already know about this one */
1999                         std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2000                         while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2001                                 ++i;
2002                         }
2003
2004                         if (i == _bundles_connected_to_outputs.end()) {
2005                                 /* We don't, so make a note */
2006                                 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2007                         }
2008                 }
2009         }
2010
2011         output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2012
2013         return 0;
2014 }
2015
2016 int
2017 IO::disable_connecting ()
2018 {
2019         connecting_legal = false;
2020         return 0;
2021 }
2022
2023 int
2024 IO::enable_connecting ()
2025 {
2026         connecting_legal = true;
2027         return ConnectingLegal ();
2028 }
2029
2030 int
2031 IO::disable_ports ()
2032 {
2033         ports_legal = false;
2034         return 0;
2035 }
2036
2037 int
2038 IO::enable_ports ()
2039 {
2040         ports_legal = true;
2041         return PortsLegal ();
2042 }
2043
2044 int
2045 IO::disable_panners (void)
2046 {
2047         panners_legal = false;
2048         return 0;
2049 }
2050
2051 int
2052 IO::reset_panners ()
2053 {
2054         panners_legal = true;
2055         return PannersLegal ();
2056 }
2057
2058 void
2059 IO::bundle_configuration_will_change ()
2060 {
2061         //XXX
2062 //      connect_input_ports_to_bundle (_input_bundle, this);
2063 }
2064
2065 void
2066 IO::bundle_configuration_has_changed ()
2067 {
2068         //XXX
2069 //      connect_input_ports_to_bundle (_input_bundle, this);
2070 }
2071
2072 void
2073 IO::bundle_ports_will_change (int ignored)
2074 {
2075 //XXX
2076 //      connect_output_ports_to_bundle (_output_bundle, this);
2077 }
2078
2079 void
2080 IO::bundle_ports_have_changed (int ignored)
2081 {
2082         //XXX
2083 //      connect_output_ports_to_bundle (_output_bundle, this);
2084 }
2085
2086 void
2087 IO::GainControl::set_value (float val)
2088 {
2089         // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2090         if (val > 1.99526231f)
2091                 val = 1.99526231f;
2092
2093         _user_value = val;
2094         _io.set_gain (val, this);
2095         
2096         Changed(); /* EMIT SIGNAL */
2097 }
2098
2099 float
2100 IO::GainControl::get_value (void) const
2101 {
2102         return AutomationControl::get_value();
2103 }
2104
2105 void
2106 IO::setup_peak_meters()
2107 {
2108         ChanCount max_streams = std::max(_inputs.count(), _outputs.count());
2109         _meter->configure_io(max_streams, max_streams);
2110 }
2111
2112 /**
2113     Update the peak meters.
2114
2115     The meter signal lock is taken to prevent modification of the 
2116     Meter signal while updating the meters, taking the meter signal
2117     lock prior to taking the io_lock ensures that all IO will remain 
2118     valid while metering.
2119 */   
2120 void
2121 IO::update_meters()
2122 {
2123         Glib::Mutex::Lock guard (m_meter_signal_lock);
2124         Meter(); /* EMIT SIGNAL */
2125 }
2126
2127 void
2128 IO::meter ()
2129 {
2130         // FIXME: Ugly.  Meter should manage the lock, if it's necessary
2131         
2132         Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2133         _meter->meter();
2134 }
2135
2136 void
2137 IO::clear_automation ()
2138 {
2139         Automatable::clear_automation (); // clears gain automation
2140         _panner->clear_automation ();
2141 }
2142
2143 void
2144 IO::set_parameter_automation_state (Parameter param, AutoState state)
2145 {
2146         // XXX: would be nice to get rid of this special hack
2147
2148         if (param.type() == GainAutomation) {
2149
2150                 bool changed = false;
2151
2152                 { 
2153                         Glib::Mutex::Lock lm (_automation_lock);
2154
2155                         boost::shared_ptr<AutomationList> gain_auto = _gain_control->list();
2156
2157                         if (state != gain_auto->automation_state()) {
2158                                 changed = true;
2159                                 _last_automation_snapshot = 0;
2160                                 gain_auto->set_automation_state (state);
2161
2162                                 if (state != Off) {
2163                                         // FIXME: shouldn't this use Curve?
2164                                         set_gain (gain_auto->eval (_session.transport_frame()), this);
2165                                 }
2166                         }
2167                 }
2168
2169                 if (changed) {
2170                         _session.set_dirty ();
2171                 }
2172
2173         } else {
2174                 Automatable::set_parameter_automation_state(param, state);
2175         }
2176 }
2177
2178 void
2179 IO::inc_gain (gain_t factor, void *src)
2180 {
2181         if (_desired_gain == 0.0f)
2182                 set_gain (0.000001f + (0.000001f * factor), src);
2183         else
2184                 set_gain (_desired_gain + (_desired_gain * factor), src);
2185 }
2186
2187 void
2188 IO::set_gain (gain_t val, void *src)
2189 {
2190         // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2191         if (val > 1.99526231f)
2192                 val = 1.99526231f;
2193
2194         if (src != _gain_control.get()) {
2195                 _gain_control->set_value(val);
2196                 // bit twisty, this will come back and call us again
2197                 // (this keeps control in sync with reality)
2198                 return;
2199         }
2200
2201         {
2202                 Glib::Mutex::Lock dm (declick_lock);
2203                 _desired_gain = val;
2204         }
2205
2206         if (_session.transport_stopped()) {
2207                 _gain = val;
2208         }
2209         
2210         if (_session.transport_stopped() && src != 0 && src != this && _gain_control->list()->automation_write()) {
2211                 _gain_control->list()->add (_session.transport_frame(), val);
2212                 
2213         }
2214
2215         _session.set_dirty();
2216 }
2217
2218 void
2219 IO::start_pan_touch (uint32_t which)
2220 {
2221         if (which < _panner->size()) {
2222                 (*_panner)[which]->pan_control()->list()->start_touch();
2223         }
2224 }
2225
2226 void
2227 IO::end_pan_touch (uint32_t which)
2228 {
2229         if (which < _panner->size()) {
2230                 (*_panner)[which]->pan_control()->list()->stop_touch();
2231         }
2232
2233 }
2234
2235 void
2236 IO::automation_snapshot (nframes_t now, bool force)
2237 {
2238         Automatable::automation_snapshot (now, force);
2239
2240         if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2241                 _panner->snapshot (now);
2242         }
2243         
2244         _panner->snapshot (now);
2245         _last_automation_snapshot = now;
2246 }
2247
2248 void
2249 IO::transport_stopped (nframes_t frame)
2250 {
2251         _gain_control->list()->reposition_for_rt_add (frame);
2252
2253         if (_gain_control->list()->automation_state() != Off) {
2254                 
2255                 /* the src=0 condition is a special signal to not propagate 
2256                    automation gain changes into the mix group when locating.
2257                 */
2258
2259                 // FIXME: shouldn't this use Curve?
2260                 set_gain (_gain_control->list()->eval (frame), 0);
2261         }
2262
2263         _panner->transport_stopped (frame);
2264 }
2265
2266 string
2267 IO::build_legal_port_name (DataType type, bool in)
2268 {
2269         const int name_size = jack_port_name_size();
2270         int limit;
2271         string suffix;
2272         int maxports;
2273
2274         if (type == DataType::AUDIO) {
2275                 suffix = _("audio");
2276         } else if (type == DataType::MIDI) {
2277                 suffix = _("midi");
2278         } else {
2279                 throw unknown_type();
2280         }
2281         
2282         if (in) {
2283                 suffix += _("_in");
2284                 maxports = _input_maximum.get(type);
2285         } else {
2286                 suffix += _("_out");
2287                 maxports = _output_maximum.get(type);
2288         }
2289         
2290         if (maxports == 1) {
2291                 // allow space for the slash + the suffix
2292                 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2293                 char buf[name_size+1];
2294                 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2295                 return string (buf);
2296         } 
2297         
2298         // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2299
2300         limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2301
2302         char buf1[name_size+1];
2303         char buf2[name_size+1];
2304         
2305         snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2306         
2307         int port_number;
2308         
2309         if (in) {
2310                 port_number = find_input_port_hole (buf1);
2311         } else {
2312                 port_number = find_output_port_hole (buf1);
2313         }
2314         
2315         snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2316         
2317         return string (buf2);
2318 }
2319
2320 int32_t
2321 IO::find_input_port_hole (const char* base)
2322 {
2323         /* CALLER MUST HOLD IO LOCK */
2324
2325         uint32_t n;
2326
2327         if (_inputs.empty()) {
2328                 return 1;
2329         }
2330
2331         /* we only allow up to 4 characters for the port number
2332          */
2333
2334         for (n = 1; n < 9999; ++n) {
2335                 char buf[jack_port_name_size()];
2336                 PortSet::iterator i = _inputs.begin();
2337
2338                 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2339
2340                 for ( ; i != _inputs.end(); ++i) {
2341                         if (i->short_name() == buf) {
2342                                 break;
2343                         }
2344                 }
2345
2346                 if (i == _inputs.end()) {
2347                         break;
2348                 }
2349         }
2350         return n;
2351 }
2352
2353 int32_t
2354 IO::find_output_port_hole (const char* base)
2355 {
2356         /* CALLER MUST HOLD IO LOCK */
2357
2358         uint32_t n;
2359
2360         if (_outputs.empty()) {
2361                 return 1;
2362         }
2363
2364         /* we only allow up to 4 characters for the port number
2365          */
2366
2367         for (n = 1; n < 9999; ++n) {
2368                 char buf[jack_port_name_size()];
2369                 PortSet::iterator i = _outputs.begin();
2370
2371                 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2372
2373                 for ( ; i != _outputs.end(); ++i) {
2374                         if (i->short_name() == buf) {
2375                                 break;
2376                         }
2377                 }
2378
2379                 if (i == _outputs.end()) {
2380                         break;
2381                 }
2382         }
2383         
2384         return n;
2385 }
2386
2387 void
2388 IO::set_active (bool yn)
2389 {
2390         _active = yn; 
2391          active_changed(); /* EMIT SIGNAL */
2392 }
2393
2394
2395 AudioPort*
2396 IO::audio_input(uint32_t n) const
2397 {
2398         return dynamic_cast<AudioPort*>(input(n));
2399 }
2400
2401 AudioPort*
2402 IO::audio_output(uint32_t n) const
2403 {
2404         return dynamic_cast<AudioPort*>(output(n));
2405 }
2406
2407 MidiPort*
2408 IO::midi_input(uint32_t n) const
2409 {
2410         return dynamic_cast<MidiPort*>(input(n));
2411 }
2412
2413 MidiPort*
2414 IO::midi_output(uint32_t n) const
2415 {
2416         return dynamic_cast<MidiPort*>(output(n));
2417 }
2418
2419 void
2420 IO::set_phase_invert (bool yn, void *src)
2421 {
2422         if (_phase_invert != yn) {
2423                 _phase_invert = yn;
2424                 //  phase_invert_changed (src); /* EMIT SIGNAL */
2425         }
2426 }
2427
2428 void
2429 IO::set_denormal_protection (bool yn, void *src)
2430 {
2431         if (_denormal_protection != yn) {
2432                 _denormal_protection = yn;
2433                 //  denormal_protection_changed (src); /* EMIT SIGNAL */
2434         }
2435 }
2436
2437 void
2438 IO::update_port_total_latencies ()
2439 {
2440         /* io_lock, not taken: function must be called from Session::process() calltree */
2441
2442         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2443                 _session.engine().update_total_latency (*i);
2444         }
2445
2446         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2447                 _session.engine().update_total_latency (*i);
2448         }
2449 }
2450
2451
2452 /**
2453  *  Setup bundles that describe our inputs and outputs.
2454  */
2455
2456 void
2457 IO::setup_bundles_for_inputs_and_outputs ()
2458 {
2459         char buf[32];
2460
2461         snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2462         _bundle_for_inputs->set_name (buf);
2463         uint32_t const ni = inputs().num_ports();
2464         _bundle_for_inputs->set_channels (ni);
2465         for (uint32_t i = 0; i < ni; ++i) {
2466                 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2467         }
2468
2469         snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2470         _bundle_for_outputs->set_name (buf);
2471         uint32_t const no = outputs().num_ports();
2472         _bundle_for_outputs->set_channels (no);
2473         for (uint32_t i = 0; i < no; ++i) {
2474                 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2475         }
2476 }
2477
2478
2479 /**
2480  *  Create and setup bundles that describe our inputs and outputs.
2481  */
2482
2483 void
2484 IO::create_bundles_for_inputs_and_outputs ()
2485 {
2486         _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2487         _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2488         setup_bundles_for_inputs_and_outputs ();
2489 }
2490
2491 /** Add a bundle to a list if is connected to our inputs.
2492  *  @param b Bundle to check.
2493  *  @param bundles List to add to.
2494  */
2495 void
2496 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2497 {
2498         boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2499         if (ab == 0 || ab->ports_are_outputs() == false) {
2500                 return;
2501         }
2502
2503         if (ab->nchannels () != n_inputs().n_total ()) {
2504                 return;
2505         }
2506
2507         for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2508
2509                 PortList const & pl = b->channel_ports (i);
2510
2511                 if (pl.empty()) {
2512                         return;
2513                 }
2514
2515                 if (!input(i)->connected_to (pl[0])) {
2516                         return;
2517                 }
2518         }
2519
2520         bundles->push_back (b);
2521 }
2522
2523 /** @return Bundles connected to our inputs */
2524 std::vector<boost::shared_ptr<Bundle> >
2525 IO::bundles_connected_to_inputs ()
2526 {
2527         std::vector<boost::shared_ptr<Bundle> > bundles;
2528         
2529         /* User bundles */
2530         for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2531                 bundles.push_back (i->bundle);
2532         }
2533
2534         /* Auto bundles */
2535         _session.foreach_bundle (
2536                 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2537                 );
2538
2539         return bundles;
2540 }
2541
2542
2543 /** Add a bundle to a list if is connected to our outputs.
2544  *  @param b Bundle to check.
2545  *  @param bundles List to add to.
2546  */
2547 void
2548 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2549 {
2550         boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2551         if (ab == 0 || ab->ports_are_inputs() == false) {
2552                 return;
2553         }
2554
2555         if (ab->nchannels () != n_outputs().n_total ()) {
2556                 return;
2557         }
2558
2559         for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2560
2561                 PortList const & pl = b->channel_ports (i);
2562
2563                 if (pl.empty()) {
2564                         return;
2565                 }
2566
2567                 if (!output(i)->connected_to (pl[0])) {
2568                         return;
2569                 }
2570         }
2571
2572         bundles->push_back (b);
2573 }
2574
2575
2576 /* @return Bundles connected to our outputs */
2577 std::vector<boost::shared_ptr<Bundle> >
2578 IO::bundles_connected_to_outputs ()
2579 {
2580         std::vector<boost::shared_ptr<Bundle> > bundles;
2581
2582         /* User bundles */
2583         for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2584                 bundles.push_back (i->bundle);
2585         }
2586
2587         /* Auto bundles */
2588         _session.foreach_bundle (
2589                 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2590                 );
2591
2592         return bundles; 
2593 }
2594
2595
2596 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2597 {
2598         bundle = b;
2599         configuration_will_change = b->ConfigurationWillChange.connect (
2600                 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2601                 );
2602         configuration_has_changed = b->ConfigurationHasChanged.connect (
2603                 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2604                 );
2605         ports_will_change = b->PortsWillChange.connect (
2606                 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2607                 );
2608         ports_have_changed = b->PortsHaveChanged.connect (
2609                 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)
2610                 );
2611 }
2612