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