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