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