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