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