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