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