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