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