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