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