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