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