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