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