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