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