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