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