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