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