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