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