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