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