d0a233a3567f29e0a8cf41dec71bfd762186630e
[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)
103         : Automatable (s, name),
104       _output_buffers (new BufferSet()),
105           _default_type (default_type),
106           _input_minimum (ChanCount::ZERO),
107           _input_maximum (ChanCount::INFINITE),
108           _output_minimum (ChanCount::ZERO),
109           _output_maximum (ChanCount::INFINITE)
110 {
111         _panner = new Panner (name, _session);
112         _meter = new PeakMeter (_session);
113
114         if (input_min > 0) {
115                 _input_minimum = ChanCount(_default_type, input_min);
116         }
117         if (input_max >= 0) {
118                 _input_maximum = ChanCount(_default_type, input_max);
119         }
120         if (output_min > 0) {
121                 _output_minimum = ChanCount(_default_type, output_min);
122         }
123         if (output_max >= 0) {
124                 _output_maximum = ChanCount(_default_type, output_max);
125         }
126
127         _gain = 1.0;
128         _desired_gain = 1.0;
129         pending_state_node = 0;
130         no_panner_reset = false;
131         _phase_invert = false;
132         deferred_state = 0;
133
134         boost::shared_ptr<AutomationList> gl(
135                         new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
136
137         _gain_control = boost::shared_ptr<GainControl>(
138                         new GainControl(X_("gaincontrol"), *this, gl));
139
140         add_control(_gain_control);
141
142         apply_gain_automation = false;
143         
144         {
145                 // IO::Meter is emitted from another thread so the
146                 // Meter signal must be protected.
147                 Glib::Mutex::Lock guard (m_meter_signal_lock);
148                 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
149         }
150         
151         // Connect to our own PortCountChanged signal to connect output buffers
152         IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
153
154         _session.add_controllable (_gain_control);
155
156         create_bundles_for_inputs_and_outputs ();
157 }
158
159 IO::IO (Session& s, const XMLNode& node, DataType dt)
160         : Automatable (s, "unnamed io"),
161       _output_buffers (new BufferSet()),
162           _default_type (dt)
163 {
164         _meter = new PeakMeter (_session);
165
166         _panner = 0;
167         deferred_state = 0;
168         no_panner_reset = false;
169         _desired_gain = 1.0;
170         _gain = 1.0;
171
172         apply_gain_automation = false;
173         
174         boost::shared_ptr<AutomationList> gl(
175                         new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
176
177         _gain_control = boost::shared_ptr<GainControl>(
178                         new GainControl(X_("gaincontrol"), *this, gl));
179
180         add_control(_gain_control);
181
182         set_state (node);
183
184         {
185                 // IO::Meter is emitted from another thread so the
186                 // Meter signal must be protected.
187                 Glib::Mutex::Lock guard (m_meter_signal_lock);
188                 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
189         }
190         
191         // Connect to our own PortCountChanged signal to connect output buffers
192         IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
193
194         _session.add_controllable (_gain_control);
195
196         create_bundles_for_inputs_and_outputs ();
197 }
198
199 IO::~IO ()
200 {
201         cerr << "Deleting IO called " << _name << endl;
202
203         Glib::Mutex::Lock guard (m_meter_signal_lock);
204         
205         Glib::Mutex::Lock lm (io_lock);
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 Jack outputs.
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 (Jack, type, name)) == 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 Jack 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 (Jack, type, name)) == 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 (Jack, *t, buf)) == 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 (Jack, *t, buf)) == 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 (Jack, *t, buf)) == 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 (Jack, *t, buf)) == 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         LocaleGuard lg (X_("POSIX"));
1245         Glib::Mutex::Lock lm (io_lock);
1246
1247         node->add_property("name", _name);
1248         id().print (buf, sizeof (buf));
1249         node->add_property("id", buf);
1250
1251         for (
1252           std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1253           i != _bundles_connected_to_inputs.end();
1254           ++i
1255           )
1256         {
1257                 XMLNode* n = new XMLNode ("InputBundle");
1258                 n->add_property ("name", i->bundle->name ());
1259                 node->add_child_nocopy (*n);
1260         }
1261
1262         for (
1263           std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1264           i != _bundles_connected_to_outputs.end();
1265           ++i
1266           )
1267         {
1268                 XMLNode* n = new XMLNode ("OutputBundle");
1269                 n->add_property ("name", i->bundle->name ());
1270                 node->add_child_nocopy (*n);
1271         }
1272         
1273         str = "";
1274
1275         for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1276                         
1277                 const char **connections = i->get_connections();
1278                 
1279                 if (connections && connections[0]) {
1280                         str += '{';
1281                         
1282                         for (int n = 0; connections && connections[n]; ++n) {
1283                                 if (n) {
1284                                         str += ',';
1285                                 }
1286                                 
1287                                 /* if its a connection to our own port,
1288                                    return only the port name, not the
1289                                    whole thing. this allows connections
1290                                    to be re-established even when our
1291                                    client name is different.
1292                                 */
1293                                 
1294                                 str += _session.engine().make_port_name_relative (connections[n]);
1295                         }       
1296                         
1297                         str += '}';
1298                         
1299                         free (connections);
1300                 }
1301                 else {
1302                         str += "{}";
1303                 }
1304         }
1305         
1306         node->add_property ("inputs", str);
1307
1308         str = "";
1309         
1310         for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1311                 
1312                 const char **connections = i->get_connections();
1313                 
1314                 if (connections && connections[0]) {
1315                         
1316                         str += '{';
1317                         
1318                         for (int n = 0; connections[n]; ++n) {
1319                                 if (n) {
1320                                         str += ',';
1321                                 }
1322                                 
1323                                 str += _session.engine().make_port_name_relative (connections[n]);
1324                         }
1325                         
1326                         str += '}';
1327                         
1328                         free (connections);
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 }