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