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