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