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