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