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