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