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