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