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