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