more cleanups, redesigns and subtle bug fixes for automation editing
[ardour2.git] / libs / ardour / io.cc
blob21f51e68fe53ec13fcf78f46d26c7a1b28828ba5
1 /*
2 Copyright (C) 2000 Paul Davis
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.
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.
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.
20 #include <fstream>
21 #include <algorithm>
22 #include <unistd.h>
23 #include <locale.h>
24 #include <errno.h>
26 #include <sigc++/bind.h>
28 #include <glibmm.h>
29 #include <glibmm/thread.h>
31 #include <pbd/xml++.h>
32 #include <pbd/replace_all.h>
33 #include <pbd/localeguard.h>
35 #include <ardour/audioengine.h>
36 #include <ardour/io.h>
37 #include <ardour/route.h>
38 #include <ardour/port.h>
39 #include <ardour/connection.h>
40 #include <ardour/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/dB.h>
45 #include "i18n.h"
47 #include <cmath>
49 #include <cstdlib>
52 A bug in OS X's cmath that causes isnan() and isinf() to be
53 "undeclared". the following works around that
56 #if defined(__APPLE__) && defined(__MACH__)
57 extern "C" int isnan (double);
58 extern "C" int isinf (double);
59 #endif
61 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
63 using namespace std;
64 using namespace ARDOUR;
65 using namespace PBD;
67 nframes_t IO::_automation_interval = 0;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,uint32_t> IO::MoreOutputs;
77 sigc::signal<int> IO::PortsCreated;
78 sigc::signal<void,nframes_t> IO::CycleStart;
80 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
82 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
83 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
99 static bool sort_ports_by_name (Port* a, Port* b) {
101 std::string const a_name = a->name();
102 unsigned int last_digit_position_a = a_name.size();
103 std::string::const_reverse_iterator r_iterator = a_name.rbegin();
105 while (r_iterator != a_name.rend() and Glib::Unicode::isdigit(*r_iterator)) {
106 r_iterator++; last_digit_position_a--;
109 std::string const b_name = b->name();
110 unsigned int last_digit_position_b = b_name.size();
111 r_iterator = b_name.rbegin();
113 while (r_iterator != b_name.rend() and Glib::Unicode::isdigit(*r_iterator)) {
114 r_iterator++; last_digit_position_b--;
117 // if some of the names don't have a number as posfix, compare as strings
118 if (last_digit_position_a == a_name.size() or last_digit_position_b == b_name.size()) {
119 return a_name < b_name;
122 const std::string prefix_a = a_name.substr(0, last_digit_position_a - 1);
123 const unsigned int posfix_a = std::atoi(a_name.substr(last_digit_position_a, a_name.size() - last_digit_position_a).c_str());
124 const std::string prefix_b = b_name.substr(0, last_digit_position_b - 1);
125 const unsigned int posfix_b = std::atoi(b_name.substr(last_digit_position_b, b_name.size() - last_digit_position_b).c_str());
127 if (prefix_a != prefix_b) {
128 return a_name < b_name;
129 } else {
130 return posfix_a < posfix_b;
135 /** @param default_type The type of port that will be created by ensure_io
136 * and friends if no type is explicitly requested (to avoid breakage).
138 IO::IO (Session& s, string name,
139 int input_min, int input_max, int output_min, int output_max,
140 DataType default_type)
141 : _session (s),
142 _name (name),
143 _default_type(default_type),
144 _gain_control (X_("gaincontrol"), *this),
145 _gain_automation_curve (0.0, 2.0, 1.0),
146 _input_minimum (input_min),
147 _input_maximum (input_max),
148 _output_minimum (output_min),
149 _output_maximum (output_max)
151 _panner = new Panner (name, _session);
152 _active = true;
153 _gain = 1.0;
154 _desired_gain = 1.0;
155 _input_connection = 0;
156 _output_connection = 0;
157 pending_state_node = 0;
158 _ninputs = 0;
159 _noutputs = 0;
160 no_panner_reset = false;
161 deferred_state = 0;
163 apply_gain_automation = false;
164 _ignore_gain_on_deliver = false;
166 last_automation_snapshot = 0;
168 _gain_automation_state = Auto_Off;
169 _gain_automation_style = Auto_Absolute;
172 // IO::Meter is emitted from another thread so the
173 // Meter signal must be protected.
174 Glib::Mutex::Lock guard (m_meter_signal_lock);
175 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
178 _output_offset = 0;
179 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
181 _session.add_controllable (&_gain_control);
184 IO::IO (Session& s, const XMLNode& node, DataType dt)
185 : _session (s),
186 _default_type (dt),
187 _gain_control (X_("gaincontrol"), *this),
188 _gain_automation_curve (0, 0, 0) // all reset in set_state()
190 _panner = 0;
191 _active = true;
192 deferred_state = 0;
193 no_panner_reset = false;
194 _desired_gain = 1.0;
195 _gain = 1.0;
196 _input_connection = 0;
197 _output_connection = 0;
198 _ninputs = 0;
199 _noutputs = 0;
201 apply_gain_automation = false;
202 _ignore_gain_on_deliver = false;
204 set_state (node);
207 // IO::Meter is emitted from another thread so the
208 // Meter signal must be protected.
209 Glib::Mutex::Lock guard (m_meter_signal_lock);
210 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
213 _output_offset = 0;
214 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
216 _session.add_controllable (&_gain_control);
219 IO::~IO ()
221 Glib::Mutex::Lock guard (m_meter_signal_lock);
223 Glib::Mutex::Lock lm (io_lock);
224 vector<Port *>::iterator i;
227 BLOCK_PROCESS_CALLBACK ();
229 for (i = _inputs.begin(); i != _inputs.end(); ++i) {
230 _session.engine().unregister_port (*i);
233 for (i = _outputs.begin(); i != _outputs.end(); ++i) {
234 _session.engine().unregister_port (*i);
238 m_meter_connection.disconnect();
241 void
242 IO::silence (nframes_t nframes)
244 /* io_lock, not taken: function must be called from Session::process() calltree */
246 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
247 (*i)->silence (nframes);
251 void
252 IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
254 nframes_t declick = min ((nframes_t)128, nframes);
255 gain_t delta;
256 Sample *buffer;
257 double fractional_shift;
258 double fractional_pos;
259 gain_t polscale = invert_polarity ? -1.0f : 1.0f;
261 if (nframes == 0) return;
263 fractional_shift = -1.0/declick;
265 if (target < initial) {
266 /* fade out: remove more and more of delta from initial */
267 delta = -(initial - target);
268 } else {
269 /* fade in: add more and more of delta from initial */
270 delta = target - initial;
273 for (uint32_t n = 0; n < nbufs; ++n) {
275 buffer = bufs[n];
276 fractional_pos = 1.0;
278 for (nframes_t nx = 0; nx < declick; ++nx) {
279 buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
280 fractional_pos += fractional_shift;
283 /* now ensure the rest of the buffer has the target value
284 applied, if necessary.
287 if (declick != nframes) {
288 float this_target;
290 if (invert_polarity) {
291 this_target = -target;
292 } else {
293 this_target = target;
296 if (this_target == 0.0) {
297 memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
298 } else if (this_target != 1.0) {
299 for (nframes_t nx = declick; nx < nframes; ++nx) {
300 buffer[nx] *= this_target;
307 void
308 IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, nframes_t start, nframes_t end, nframes_t nframes)
310 Sample* dst;
312 /* io_lock, not taken: function must be called from Session::process() calltree */
314 if (_noutputs == 0) {
315 return;
318 if (_noutputs == 1) {
320 dst = get_output_buffer (0, nframes);
322 for (uint32_t n = 0; n < nbufs; ++n) {
323 if (bufs[n] != dst) {
324 memcpy (dst, bufs[n], sizeof (Sample) * nframes);
328 output(0)->mark_silence (false);
330 return;
333 uint32_t o;
334 vector<Port *>::iterator out;
335 vector<Sample *>::iterator in;
336 Panner::iterator pan;
337 Sample* obufs[_noutputs];
339 /* the terrible silence ... */
341 for (out = _outputs.begin(), o = 0; out != _outputs.end(); ++out, ++o) {
342 obufs[o] = get_output_buffer (o, nframes);
343 memset (obufs[o], 0, sizeof (Sample) * nframes);
344 (*out)->mark_silence (false);
347 uint32_t n;
349 for (pan = _panner->begin(), n = 0; n < nbufs; ++n, ++pan) {
350 (*pan)->distribute_automated (bufs[n], obufs, start, end, nframes, _session.pan_automation_buffer());
354 void
355 IO::pan (vector<Sample*>& bufs, uint32_t nbufs, nframes_t nframes, gain_t gain_coeff)
357 Sample* dst;
358 Sample* src;
360 /* io_lock, not taken: function must be called from Session::process() calltree */
362 if (_noutputs == 0) {
363 return;
366 /* the panner can be empty if there are no inputs to the
367 route, but still outputs
370 if (_panner->bypassed() || _panner->empty()) {
371 deliver_output_no_pan (bufs, nbufs, nframes);
372 return;
375 if (_noutputs == 1) {
377 dst = get_output_buffer (0, nframes);
379 if (gain_coeff == 0.0f) {
381 /* only one output, and gain was zero, so make it silent */
383 memset (dst, 0, sizeof (Sample) * nframes);
385 } else if (gain_coeff == 1.0f){
387 /* mix all buffers into the output */
389 uint32_t n;
391 memcpy (dst, bufs[0], sizeof (Sample) * nframes);
393 for (n = 1; n < nbufs; ++n) {
394 Session::mix_buffers_no_gain(dst,bufs[n],nframes);
397 output(0)->mark_silence (false);
399 } else {
401 /* mix all buffers into the output, scaling them all by the gain */
403 uint32_t n;
405 src = bufs[0];
407 for (nframes_t n = 0; n < nframes; ++n) {
408 dst[n] = src[n] * gain_coeff;
411 for (n = 1; n < nbufs; ++n) {
412 Session::mix_buffers_with_gain(dst,bufs[n],nframes,gain_coeff);
415 output(0)->mark_silence (false);
418 return;
421 uint32_t o;
422 vector<Port *>::iterator out;
423 vector<Sample *>::iterator in;
424 Panner::iterator pan;
425 Sample* obufs[_noutputs];
427 /* the terrible silence ... */
429 /* XXX this is wasteful but i see no way to avoid it */
431 for (out = _outputs.begin(), o = 0; out != _outputs.end(); ++out, ++o) {
432 obufs[o] = get_output_buffer (o, nframes);
433 memset (obufs[o], 0, sizeof (Sample) * nframes);
434 (*out)->mark_silence (false);
437 uint32_t n;
439 for (pan = _panner->begin(), n = 0; n < nbufs; ++n) {
440 Panner::iterator tmp;
442 tmp = pan;
443 ++tmp;
445 (*pan)->distribute (bufs[n], obufs, gain_coeff, nframes);
447 if (tmp != _panner->end()) {
448 pan = tmp;
453 void
454 IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
456 /* io_lock, not taken: function must be called from Session::process() calltree */
458 if (_noutputs == 0) {
459 return;
462 if (_panner->bypassed() || _panner->empty()) {
463 deliver_output_no_pan (bufs, nbufs, nframes);
464 return;
468 gain_t dg;
469 gain_t pangain = _gain;
472 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
474 if (dm.locked()) {
475 dg = _desired_gain;
476 } else {
477 dg = _gain;
481 if (dg != _gain) {
482 apply_declick (bufs, nbufs, nframes, _gain, dg, false);
483 _gain = dg;
484 pangain = 1.0f;
487 /* simple, non-automation panning to outputs */
489 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
490 pan (bufs, nbufs, nframes, pangain * speed_quietning);
491 } else {
492 pan (bufs, nbufs, nframes, pangain);
496 void
497 IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
499 /* io_lock, not taken: function must be called from Session::process() calltree */
501 if (_noutputs == 0) {
502 return;
505 gain_t dg;
506 gain_t old_gain = _gain;
508 if (apply_gain_automation || _ignore_gain_on_deliver) {
510 /* gain has already been applied by automation code. do nothing here except
511 speed quietning.
514 _gain = 1.0f;
515 dg = _gain;
517 } else {
519 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
521 if (dm.locked()) {
522 dg = _desired_gain;
523 } else {
524 dg = _gain;
528 Sample* src;
529 Sample* dst;
530 uint32_t i;
531 vector<Port*>::iterator o;
532 vector<Sample*> outs;
533 gain_t actual_gain;
535 /* reduce nbufs to the index of the last input buffer */
537 nbufs--;
539 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
540 actual_gain = _gain * speed_quietning;
541 } else {
542 actual_gain = _gain;
545 for (o = _outputs.begin(), i = 0; o != _outputs.end(); ++o, ++i) {
547 dst = get_output_buffer (i, nframes);
548 src = bufs[min(nbufs,i)];
550 if (dg != _gain) {
551 /* unlikely condition */
552 outs.push_back (dst);
555 if (dg != _gain || actual_gain == 1.0f) {
556 memcpy (dst, src, sizeof (Sample) * nframes);
557 } else if (actual_gain == 0.0f) {
558 memset (dst, 0, sizeof (Sample) * nframes);
559 } else {
560 for (nframes_t x = 0; x < nframes; ++x) {
561 dst[x] = src[x] * actual_gain;
565 (*o)->mark_silence (false);
568 if (dg != _gain) {
569 apply_declick (outs, i, nframes, _gain, dg, false);
570 _gain = dg;
573 if (apply_gain_automation || _ignore_gain_on_deliver) {
574 _gain = old_gain;
578 void
579 IO::collect_input (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
581 /* io_lock, not taken: function must be called from Session::process() calltree */
583 vector<Port *>::iterator i;
584 uint32_t n;
585 Sample *last = 0;
587 /* we require that bufs.size() >= 1 */
589 for (n = 0, i = _inputs.begin(); n < nbufs; ++i, ++n) {
590 if (i == _inputs.end()) {
591 break;
594 last = get_input_buffer (n, nframes);
595 memcpy (bufs[n], last, sizeof (Sample) * nframes);
598 /* fill any excess outputs with the last input */
600 if (last) {
601 while (n < nbufs) {
602 memcpy (bufs[n], last, sizeof (Sample) * nframes);
603 ++n;
605 } else {
606 while (n < nbufs) {
607 memset (bufs[n], 0, sizeof (Sample) * nframes);
608 ++n;
613 void
614 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
616 vector<Sample*>& bufs = _session.get_passthru_buffers ();
617 uint32_t nbufs = n_process_buffers ();
619 collect_input (bufs, nbufs, nframes);
621 for (uint32_t n = 0; n < nbufs; ++n) {
622 _peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
626 void
627 IO::drop_input_connection ()
629 _input_connection = 0;
630 input_connection_configuration_connection.disconnect();
631 input_connection_connection_connection.disconnect();
632 _session.set_dirty ();
635 void
636 IO::drop_output_connection ()
638 _output_connection = 0;
639 output_connection_configuration_connection.disconnect();
640 output_connection_connection_connection.disconnect();
641 _session.set_dirty ();
645 IO::disconnect_input (Port* our_port, string other_port, void* src)
647 if (other_port.length() == 0 || our_port == 0) {
648 return 0;
652 BLOCK_PROCESS_CALLBACK ();
655 Glib::Mutex::Lock lm (io_lock);
657 /* check that our_port is really one of ours */
659 if (find (_inputs.begin(), _inputs.end(), our_port) == _inputs.end()) {
660 return -1;
663 /* disconnect it from the source */
665 if (_session.engine().disconnect (other_port, our_port->name())) {
666 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
667 return -1;
670 drop_input_connection();
674 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
675 _session.set_dirty ();
677 return 0;
681 IO::connect_input (Port* our_port, string other_port, void* src)
683 if (other_port.length() == 0 || our_port == 0) {
684 return 0;
688 BLOCK_PROCESS_CALLBACK ();
691 Glib::Mutex::Lock lm (io_lock);
693 /* check that our_port is really one of ours */
695 if (find (_inputs.begin(), _inputs.end(), our_port) == _inputs.end()) {
696 return -1;
699 /* connect it to the source */
701 if (_session.engine().connect (other_port, our_port->name())) {
702 return -1;
705 drop_input_connection ();
709 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
710 _session.set_dirty ();
711 return 0;
715 IO::disconnect_output (Port* our_port, string other_port, void* src)
717 if (other_port.length() == 0 || our_port == 0) {
718 return 0;
722 BLOCK_PROCESS_CALLBACK ();
725 Glib::Mutex::Lock lm (io_lock);
727 if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
728 return -1;
731 /* disconnect it from the destination */
733 if (_session.engine().disconnect (our_port->name(), other_port)) {
734 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
735 return -1;
738 drop_output_connection ();
742 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
743 _session.set_dirty ();
744 return 0;
748 IO::connect_output (Port* our_port, string other_port, void* src)
750 if (other_port.length() == 0 || our_port == 0) {
751 return 0;
755 BLOCK_PROCESS_CALLBACK ();
759 Glib::Mutex::Lock lm (io_lock);
761 /* check that our_port is really one of ours */
763 if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
764 return -1;
767 /* connect it to the destination */
769 if (_session.engine().connect (our_port->name(), other_port)) {
770 return -1;
773 drop_output_connection ();
777 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
778 _session.set_dirty ();
779 return 0;
783 IO::set_input (Port* other_port, void* src)
785 /* this removes all but one ports, and connects that one port
786 to the specified source.
789 if (_input_minimum > 1 || _input_minimum == 0) {
790 /* sorry, you can't do this */
791 return -1;
794 if (other_port == 0) {
795 if (_input_minimum < 0) {
796 return ensure_inputs (0, false, true, src);
797 } else {
798 return -1;
802 if (ensure_inputs (1, true, true, src)) {
803 return -1;
806 return connect_input (_inputs.front(), other_port->name(), src);
810 IO::remove_output_port (Port* port, void* src)
812 IOChange change (NoChange);
815 BLOCK_PROCESS_CALLBACK ();
819 Glib::Mutex::Lock lm (io_lock);
821 if (_noutputs - 1 == (uint32_t) _output_minimum) {
822 /* sorry, you can't do this */
823 return -1;
826 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
827 if (*i == port) {
828 change = IOChange (change|ConfigurationChanged);
829 if (port->connected()) {
830 change = IOChange (change|ConnectionsChanged);
833 _session.engine().unregister_port (*i);
834 _outputs.erase (i);
835 _noutputs--;
836 drop_output_connection ();
838 break;
842 if (change != NoChange) {
843 setup_peak_meters ();
844 reset_panner ();
849 if (change != NoChange) {
850 output_changed (change, src); /* EMIT SIGNAL */
851 _session.set_dirty ();
852 return 0;
855 return -1;
858 /** Add an output port.
860 * @param destination Name of input port to connect new port to.
861 * @param src Source for emitted ConfigurationChanged signal.
862 * @param type Data type of port. Default value (NIL) will use this IO's default type.
865 IO::add_output_port (string destination, void* src, DataType type)
867 Port* our_port;
869 if (type == DataType::NIL)
870 type = _default_type;
873 BLOCK_PROCESS_CALLBACK ();
877 Glib::Mutex::Lock lm (io_lock);
879 if (_output_maximum >= 0 && (int) _noutputs == _output_maximum) {
880 return -1;
883 /* Create a new output port */
885 string portname = build_legal_port_name (false);
887 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
888 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
889 return -1;
892 _outputs.push_back (our_port);
893 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
894 ++_noutputs;
895 drop_output_connection ();
896 setup_peak_meters ();
897 reset_panner ();
900 MoreOutputs (_noutputs); /* EMIT SIGNAL */
903 if (destination.length()) {
904 if (_session.engine().connect (our_port->name(), destination)) {
905 return -1;
909 // pan_changed (src); /* EMIT SIGNAL */
910 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
911 _session.set_dirty ();
912 return 0;
916 IO::remove_input_port (Port* port, void* src)
918 IOChange change (NoChange);
921 BLOCK_PROCESS_CALLBACK ();
925 Glib::Mutex::Lock lm (io_lock);
927 if (((int)_ninputs - 1) < _input_minimum) {
928 /* sorry, you can't do this */
929 return -1;
931 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
933 if (*i == port) {
934 change = IOChange (change|ConfigurationChanged);
936 if (port->connected()) {
937 change = IOChange (change|ConnectionsChanged);
940 _session.engine().unregister_port (*i);
941 _inputs.erase (i);
942 _ninputs--;
943 drop_input_connection ();
945 break;
949 if (change != NoChange) {
950 setup_peak_meters ();
951 reset_panner ();
956 if (change != NoChange) {
957 input_changed (change, src);
958 _session.set_dirty ();
959 return 0;
962 return -1;
966 /** Add an input port.
968 * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
969 * @param destination Name of input port to connect new port to.
970 * @param src Source for emitted ConfigurationChanged signal.
973 IO::add_input_port (string source, void* src, DataType type)
975 Port* our_port;
977 if (type == DataType::NIL)
978 type = _default_type;
981 BLOCK_PROCESS_CALLBACK ();
984 Glib::Mutex::Lock lm (io_lock);
986 if (_input_maximum >= 0 && (int) _ninputs == _input_maximum) {
987 return -1;
990 /* Create a new input port */
992 string portname = build_legal_port_name (true);
994 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
995 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
996 return -1;
999 _inputs.push_back (our_port);
1000 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1001 ++_ninputs;
1002 drop_input_connection ();
1003 setup_peak_meters ();
1004 reset_panner ();
1007 MoreOutputs (_ninputs); /* EMIT SIGNAL */
1010 if (source.length()) {
1012 if (_session.engine().connect (source, our_port->name())) {
1013 return -1;
1017 // pan_changed (src); /* EMIT SIGNAL */
1018 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1019 _session.set_dirty ();
1021 return 0;
1025 IO::disconnect_inputs (void* src)
1028 BLOCK_PROCESS_CALLBACK ();
1031 Glib::Mutex::Lock lm (io_lock);
1033 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1034 _session.engine().disconnect (*i);
1037 drop_input_connection ();
1040 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1041 return 0;
1045 IO::disconnect_outputs (void* src)
1048 BLOCK_PROCESS_CALLBACK ();
1051 Glib::Mutex::Lock lm (io_lock);
1053 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1054 _session.engine().disconnect (*i);
1057 drop_output_connection ();
1061 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1062 _session.set_dirty ();
1063 return 0;
1066 bool
1067 IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
1069 Port* input_port;
1070 bool changed = false;
1071 bool reduced = false;
1073 /* remove unused ports */
1075 while (_ninputs > n) {
1076 _session.engine().unregister_port (_inputs.back());
1077 _inputs.pop_back();
1078 _ninputs--;
1079 reduced = true;
1080 changed = true;
1083 /* create any necessary new ports */
1085 while (_ninputs < n) {
1087 /* Create a new input port (of the default type) */
1089 string portname = build_legal_port_name (true);
1091 try {
1093 if ((input_port = _session.engine().register_input_port (_default_type, portname)) == 0) {
1094 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
1095 return -1;
1099 catch (AudioEngine::PortRegistrationFailure& err) {
1100 setup_peak_meters ();
1101 reset_panner ();
1102 /* pass it on */
1103 throw;
1106 _inputs.push_back (input_port);
1107 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1108 ++_ninputs;
1109 changed = true;
1112 if (changed) {
1113 drop_input_connection ();
1114 setup_peak_meters ();
1115 reset_panner ();
1116 MoreOutputs (_ninputs); /* EMIT SIGNAL */
1117 _session.set_dirty ();
1120 if (clear) {
1121 /* disconnect all existing ports so that we get a fresh start */
1123 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1124 _session.engine().disconnect (*i);
1128 return changed;
1132 IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
1134 bool in_changed = false;
1135 bool out_changed = false;
1136 bool in_reduced = false;
1137 bool out_reduced = false;
1138 bool need_pan_reset;
1140 if (_input_maximum >= 0) {
1141 nin = min (_input_maximum, (int) nin);
1144 if (_output_maximum >= 0) {
1145 nout = min (_output_maximum, (int) nout);
1148 if (nin == _ninputs && nout == _noutputs && !clear) {
1149 return 0;
1153 BLOCK_PROCESS_CALLBACK ();
1154 Glib::Mutex::Lock lm (io_lock);
1156 Port* port;
1158 if (_noutputs == nout) {
1159 need_pan_reset = false;
1160 } else {
1161 need_pan_reset = true;
1164 /* remove unused ports */
1166 while (_ninputs > nin) {
1167 _session.engine().unregister_port (_inputs.back());
1168 _inputs.pop_back();
1169 _ninputs--;
1170 in_reduced = true;
1171 in_changed = true;
1174 while (_noutputs > nout) {
1175 _session.engine().unregister_port (_outputs.back());
1176 _outputs.pop_back();
1177 _noutputs--;
1178 out_reduced = true;
1179 out_changed = true;
1182 /* create any necessary new ports (of the default type) */
1184 while (_ninputs < nin) {
1186 /* Create a new input port */
1188 string portname = build_legal_port_name (true);
1190 try {
1191 if ((port = _session.engine().register_input_port (_default_type, portname)) == 0) {
1192 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
1193 return -1;
1197 catch (AudioEngine::PortRegistrationFailure& err) {
1198 setup_peak_meters ();
1199 reset_panner ();
1200 /* pass it on */
1201 throw;
1204 _inputs.push_back (port);
1205 ++_ninputs;
1206 in_changed = true;
1209 /* create any necessary new ports */
1211 while (_noutputs < nout) {
1213 string portname = build_legal_port_name (false);
1215 try {
1216 if ((port = _session.engine().register_output_port (_default_type, portname)) == 0) {
1217 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1218 return -1;
1222 catch (AudioEngine::PortRegistrationFailure& err) {
1223 setup_peak_meters ();
1224 reset_panner ();
1225 /* pass it on */
1226 throw;
1229 _outputs.push_back (port);
1230 ++_noutputs;
1231 out_changed = true;
1234 if (clear) {
1236 /* disconnect all existing ports so that we get a fresh start */
1238 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1239 _session.engine().disconnect (*i);
1242 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1243 _session.engine().disconnect (*i);
1247 if (in_changed || out_changed) {
1248 setup_peak_meters ();
1249 reset_panner ();
1253 if (out_changed) {
1254 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
1255 drop_output_connection ();
1256 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1259 if (in_changed) {
1260 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1261 drop_input_connection ();
1262 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1265 if (in_changed || out_changed) {
1266 MoreOutputs (max (_noutputs, _ninputs)); /* EMIT SIGNAL */
1267 _session.set_dirty ();
1270 return 0;
1274 IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
1276 bool changed = false;
1278 if (_input_maximum >= 0) {
1279 n = min (_input_maximum, (int) n);
1281 if (n == _ninputs && !clear) {
1282 return 0;
1286 if (lockit) {
1287 BLOCK_PROCESS_CALLBACK ();
1288 Glib::Mutex::Lock im (io_lock);
1289 changed = ensure_inputs_locked (n, clear, src);
1290 } else {
1291 changed = ensure_inputs_locked (n, clear, src);
1294 if (changed) {
1295 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1296 _session.set_dirty ();
1299 return 0;
1302 bool
1303 IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
1305 Port* output_port;
1306 bool changed = false;
1307 bool reduced = false;
1308 bool need_pan_reset;
1310 if (_noutputs == n) {
1311 need_pan_reset = false;
1312 } else {
1313 need_pan_reset = true;
1316 /* remove unused ports */
1318 while (_noutputs > n) {
1320 _session.engine().unregister_port (_outputs.back());
1321 _outputs.pop_back();
1322 _noutputs--;
1323 reduced = true;
1324 changed = true;
1327 /* create any necessary new ports */
1329 while (_noutputs < n) {
1331 /* Create a new output port */
1333 string portname = build_legal_port_name (false);
1335 if ((output_port = _session.engine().register_output_port (_default_type, portname)) == 0) {
1336 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1337 return -1;
1340 _outputs.push_back (output_port);
1341 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
1342 ++_noutputs;
1343 changed = true;
1344 setup_peak_meters ();
1346 if (need_pan_reset) {
1347 reset_panner ();
1351 if (changed) {
1352 drop_output_connection ();
1353 MoreOutputs (_noutputs); /* EMIT SIGNAL */
1354 _session.set_dirty ();
1357 if (clear) {
1358 /* disconnect all existing ports so that we get a fresh start */
1360 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1361 _session.engine().disconnect (*i);
1365 return changed;
1369 IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src)
1371 bool changed = false;
1373 if (_output_maximum >= 0) {
1374 n = min (_output_maximum, (int) n);
1375 if (n == _noutputs && !clear) {
1376 return 0;
1380 /* XXX caller should hold io_lock, but generally doesn't */
1382 if (lockit) {
1383 BLOCK_PROCESS_CALLBACK ();
1384 Glib::Mutex::Lock im (io_lock);
1385 changed = ensure_outputs_locked (n, clear, src);
1386 } else {
1387 changed = ensure_outputs_locked (n, clear, src);
1390 if (changed) {
1391 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1394 return 0;
1397 gain_t
1398 IO::effective_gain () const
1400 if (gain_automation_playback()) {
1401 return _effective_gain;
1402 } else {
1403 return _desired_gain;
1407 void
1408 IO::reset_panner ()
1410 if (panners_legal) {
1411 if (!no_panner_reset) {
1412 _panner->reset (_noutputs, pans_required());
1414 } else {
1415 panner_legal_c.disconnect ();
1416 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1421 IO::panners_became_legal ()
1423 _panner->reset (_noutputs, pans_required());
1424 _panner->load (); // automation
1425 panner_legal_c.disconnect ();
1426 return 0;
1429 void
1430 IO::defer_pan_reset ()
1432 no_panner_reset = true;
1435 void
1436 IO::allow_pan_reset ()
1438 no_panner_reset = false;
1439 reset_panner ();
1443 XMLNode&
1444 IO::get_state (void)
1446 return state (true);
1449 XMLNode&
1450 IO::state (bool full_state)
1452 XMLNode* node = new XMLNode (state_node_name);
1453 char buf[64];
1454 string str;
1455 bool need_ins = true;
1456 bool need_outs = true;
1457 LocaleGuard lg (X_("POSIX"));
1458 Glib::Mutex::Lock lm (io_lock);
1460 node->add_property("name", _name);
1461 id().print (buf, sizeof (buf));
1462 node->add_property("id", buf);
1463 node->add_property("active", _active? "yes" : "no");
1465 str = "";
1467 if (_input_connection) {
1468 node->add_property ("input-connection", _input_connection->name());
1469 need_ins = false;
1472 if (_output_connection) {
1473 node->add_property ("output-connection", _output_connection->name());
1474 need_outs = false;
1477 if (need_ins) {
1478 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1480 const char **connections = (*i)->get_connections();
1482 if (connections && connections[0]) {
1483 str += '{';
1485 for (int n = 0; connections && connections[n]; ++n) {
1486 if (n) {
1487 str += ',';
1490 /* if its a connection to our own port,
1491 return only the port name, not the
1492 whole thing. this allows connections
1493 to be re-established even when our
1494 client name is different.
1497 str += _session.engine().make_port_name_relative (connections[n]);
1500 str += '}';
1502 free (connections);
1504 else {
1505 str += "{}";
1509 node->add_property ("inputs", str);
1512 if (need_outs) {
1513 str = "";
1515 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1517 const char **connections = (*i)->get_connections();
1519 if (connections && connections[0]) {
1521 str += '{';
1523 for (int n = 0; connections[n]; ++n) {
1524 if (n) {
1525 str += ',';
1528 str += _session.engine().make_port_name_relative (connections[n]);
1531 str += '}';
1533 free (connections);
1535 else {
1536 str += "{}";
1540 node->add_property ("outputs", str);
1543 node->add_child_nocopy (_panner->state (full_state));
1544 node->add_child_nocopy (_gain_control.get_state ());
1546 snprintf (buf, sizeof(buf), "%2.12f", gain());
1547 node->add_property ("gain", buf);
1549 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d",
1550 _input_minimum,
1551 _input_maximum,
1552 _output_minimum,
1553 _output_maximum);
1555 node->add_property ("iolimits", buf);
1557 /* automation */
1559 if (full_state) {
1561 XMLNode* autonode = new XMLNode (X_("Automation"));
1562 autonode->add_child_nocopy (get_automation_state());
1563 node->add_child_nocopy (*autonode);
1565 snprintf (buf, sizeof (buf), "0x%x", (int) _gain_automation_curve.automation_state());
1566 } else {
1567 /* never store anything except Off for automation state in a template */
1568 snprintf (buf, sizeof (buf), "0x%x", ARDOUR::Auto_Off);
1571 return *node;
1575 IO::set_state (const XMLNode& node)
1577 const XMLProperty* prop;
1578 XMLNodeConstIterator iter;
1579 LocaleGuard lg (X_("POSIX"));
1581 /* force use of non-localized representation of decimal point,
1582 since we use it a lot in XML files and so forth.
1585 if (node.name() != state_node_name) {
1586 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1587 return -1;
1590 if ((prop = node.property ("name")) != 0) {
1591 _name = prop->value();
1592 /* used to set panner name with this, but no more */
1595 if ((prop = node.property ("id")) != 0) {
1596 _id = prop->value ();
1599 if ((prop = node.property ("iolimits")) != 0) {
1600 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1601 &_input_minimum,
1602 &_input_maximum,
1603 &_output_minimum,
1604 &_output_maximum);
1607 if ((prop = node.property ("gain")) != 0) {
1608 set_gain (atof (prop->value().c_str()), this);
1609 _gain = _desired_gain;
1612 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1613 /* old school automation handling */
1616 if ((prop = node.property (X_("active"))) != 0) {
1617 set_active (string_is_affirmative (prop->value()));
1620 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1622 if ((*iter)->name() == "Panner") {
1623 if (_panner == 0) {
1624 _panner = new Panner (_name, _session);
1626 _panner->set_state (**iter);
1629 if ((*iter)->name() == X_("Automation")) {
1631 set_automation_state (*(*iter)->children().front());
1634 if ((*iter)->name() == X_("controllable")) {
1635 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1636 _gain_control.set_state (**iter);
1641 if (ports_legal) {
1643 if (create_ports (node)) {
1644 return -1;
1647 } else {
1649 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1652 if (panners_legal) {
1653 reset_panner ();
1654 } else {
1655 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1658 if (connecting_legal) {
1660 if (make_connections (node)) {
1661 return -1;
1664 } else {
1666 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1669 if (!ports_legal || !connecting_legal) {
1670 pending_state_node = new XMLNode (node);
1673 last_automation_snapshot = 0;
1675 return 0;
1679 IO::set_automation_state (const XMLNode& node)
1681 return _gain_automation_curve.set_state (node);
1684 XMLNode&
1685 IO::get_automation_state ()
1687 return (_gain_automation_curve.get_state ());
1691 IO::load_automation (string path)
1693 string fullpath;
1694 ifstream in;
1695 char line[128];
1696 uint32_t linecnt = 0;
1697 float version;
1698 LocaleGuard lg (X_("POSIX"));
1700 fullpath = Glib::build_filename(_session.automation_dir(), path);
1702 in.open (fullpath.c_str());
1704 if (!in) {
1705 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1707 in.open (fullpath.c_str());
1709 if (!in) {
1710 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1711 return -1;
1715 clear_automation ();
1717 while (in.getline (line, sizeof(line), '\n')) {
1718 char type;
1719 jack_nframes_t when;
1720 double value;
1722 if (++linecnt == 1) {
1723 if (memcmp (line, "version", 7) == 0) {
1724 if (sscanf (line, "version %f", &version) != 1) {
1725 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1726 return -1;
1728 } else {
1729 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1730 return -1;
1733 continue;
1736 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1737 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1738 continue;
1741 switch (type) {
1742 case 'g':
1743 _gain_automation_curve.fast_simple_add (when, value);
1744 break;
1746 case 's':
1747 break;
1749 case 'm':
1750 break;
1752 case 'p':
1753 /* older (pre-1.0) versions of ardour used this */
1754 break;
1756 default:
1757 warning << _("dubious automation event found (and ignored)") << endmsg;
1761 return 0;
1765 IO::connecting_became_legal ()
1767 int ret;
1769 if (pending_state_node == 0) {
1770 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1771 /*NOTREACHED*/
1772 return -1;
1775 connection_legal_c.disconnect ();
1777 ret = make_connections (*pending_state_node);
1779 if (ports_legal) {
1780 delete pending_state_node;
1781 pending_state_node = 0;
1784 return ret;
1787 IO::ports_became_legal ()
1789 int ret;
1791 if (pending_state_node == 0) {
1792 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1793 /*NOTREACHED*/
1794 return -1;
1797 port_legal_c.disconnect ();
1799 ret = create_ports (*pending_state_node);
1801 if (connecting_legal) {
1802 delete pending_state_node;
1803 pending_state_node = 0;
1806 return ret;
1809 Connection *
1810 IO::find_possible_connection(const string &desired_name, const string &default_name, const string &connection_type_name)
1812 static const string digits = "0123456789";
1814 Connection* c = _session.connection_by_name (desired_name);
1816 if (!c) {
1817 int connection_number, mask;
1818 string possible_name;
1819 bool stereo = false;
1820 string::size_type last_non_digit_pos;
1822 error << string_compose(_("Unknown connection \"%1\" listed for %2 of %3"), desired_name, connection_type_name, _name)
1823 << endmsg;
1825 // find numeric suffix of desired name
1826 connection_number = 0;
1828 last_non_digit_pos = desired_name.find_last_not_of(digits);
1830 if (last_non_digit_pos != string::npos) {
1831 stringstream s;
1832 s << desired_name.substr(last_non_digit_pos);
1833 s >> connection_number;
1836 // see if it's a stereo connection e.g. "in 3+4"
1838 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1839 int left_connection_number = 0;
1840 string::size_type left_last_non_digit_pos;
1842 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1844 if (left_last_non_digit_pos != string::npos) {
1845 stringstream s;
1846 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1847 s >> left_connection_number;
1849 if (left_connection_number > 0 && left_connection_number + 1 == connection_number) {
1850 connection_number--;
1851 stereo = true;
1856 // make 0-based
1857 if (connection_number)
1858 connection_number--;
1860 // find highest set bit
1861 mask = 1;
1862 while ((mask <= connection_number) && (mask <<= 1));
1864 // "wrap" connection number into largest possible power of 2
1865 // that works...
1867 while (mask) {
1869 if (connection_number & mask) {
1870 connection_number &= ~mask;
1872 stringstream s;
1873 s << default_name << " " << connection_number + 1;
1875 if (stereo) {
1876 s << "+" << connection_number + 2;
1879 possible_name = s.str();
1881 if ((c = _session.connection_by_name (possible_name)) != 0) {
1882 break;
1885 mask >>= 1;
1887 if (c) {
1888 info << string_compose (_("Connection %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1889 << endmsg;
1890 } else {
1891 error << string_compose(_("No %1 connections available as a replacement"), connection_type_name)
1892 << endmsg;
1897 return c;
1902 IO::create_ports (const XMLNode& node)
1904 const XMLProperty* prop;
1905 int num_inputs = 0;
1906 int num_outputs = 0;
1908 if ((prop = node.property ("input-connection")) != 0) {
1910 Connection* c = find_possible_connection(prop->value(), _("in"), _("input"));
1912 if (c == 0) {
1913 return -1;
1916 num_inputs = c->nports();
1918 } else if ((prop = node.property ("inputs")) != 0) {
1920 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1923 if ((prop = node.property ("output-connection")) != 0) {
1924 Connection* c = find_possible_connection(prop->value(), _("out"), _("output"));
1926 if (c == 0) {
1927 return -1;
1930 num_outputs = c->nports ();
1932 } else if ((prop = node.property ("outputs")) != 0) {
1933 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1936 no_panner_reset = true;
1938 if (ensure_io (num_inputs, num_outputs, true, this)) {
1939 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1940 return -1;
1943 no_panner_reset = false;
1945 set_deferred_state ();
1947 PortsCreated();
1948 return 0;
1953 IO::make_connections (const XMLNode& node)
1955 const XMLProperty* prop;
1957 if ((prop = node.property ("input-connection")) != 0) {
1958 Connection* c = find_possible_connection (prop->value(), _("in"), _("input"));
1960 if (c == 0) {
1961 return -1;
1964 use_input_connection (*c, this);
1966 } else if ((prop = node.property ("inputs")) != 0) {
1967 if (set_inputs (prop->value())) {
1968 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1969 return -1;
1973 if ((prop = node.property ("output-connection")) != 0) {
1974 Connection* c = find_possible_connection (prop->value(), _("out"), _("output"));
1976 if (c == 0) {
1977 return -1;
1980 use_output_connection (*c, this);
1982 } else if ((prop = node.property ("outputs")) != 0) {
1983 if (set_outputs (prop->value())) {
1984 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1985 return -1;
1989 return 0;
1993 IO::set_inputs (const string& str)
1995 vector<string> ports;
1996 int i;
1997 int n;
1998 uint32_t nports;
2000 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
2001 return 0;
2004 if (ensure_inputs (nports, true, true, this)) {
2005 return -1;
2008 string::size_type start, end, ostart;
2010 ostart = 0;
2011 start = 0;
2012 end = 0;
2013 i = 0;
2015 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
2016 start += 1;
2018 if ((end = str.find_first_of ('}', start)) == string::npos) {
2019 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
2020 return -1;
2023 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
2024 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
2026 return -1;
2028 } else if (n > 0) {
2030 for (int x = 0; x < n; ++x) {
2031 connect_input (input (i), ports[x], this);
2035 ostart = end+1;
2036 i++;
2039 return 0;
2043 IO::set_outputs (const string& str)
2045 vector<string> ports;
2046 int i;
2047 int n;
2048 uint32_t nports;
2050 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
2051 return 0;
2054 if (ensure_outputs (nports, true, true, this)) {
2055 return -1;
2058 string::size_type start, end, ostart;
2060 ostart = 0;
2061 start = 0;
2062 end = 0;
2063 i = 0;
2065 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
2066 start += 1;
2068 if ((end = str.find_first_of ('}', start)) == string::npos) {
2069 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
2070 return -1;
2073 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
2074 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
2076 return -1;
2078 } else if (n > 0) {
2080 for (int x = 0; x < n; ++x) {
2081 connect_output (output (i), ports[x], this);
2085 ostart = end+1;
2086 i++;
2089 return 0;
2093 IO::parse_io_string (const string& str, vector<string>& ports)
2095 string::size_type pos, opos;
2097 if (str.length() == 0) {
2098 return 0;
2101 pos = 0;
2102 opos = 0;
2104 ports.clear ();
2106 while ((pos = str.find_first_of (',', opos)) != string::npos) {
2107 ports.push_back (str.substr (opos, pos - opos));
2108 opos = pos + 1;
2111 if (opos < str.length()) {
2112 ports.push_back (str.substr(opos));
2115 return ports.size();
2119 IO::parse_gain_string (const string& str, vector<string>& ports)
2121 string::size_type pos, opos;
2123 pos = 0;
2124 opos = 0;
2125 ports.clear ();
2127 while ((pos = str.find_first_of (',', opos)) != string::npos) {
2128 ports.push_back (str.substr (opos, pos - opos));
2129 opos = pos + 1;
2132 if (opos < str.length()) {
2133 ports.push_back (str.substr(opos));
2136 return ports.size();
2140 IO::set_name (string requested_name, void* src)
2142 if (requested_name == _name) {
2143 return 0;
2146 string name;
2147 Route *rt;
2148 if ( (rt = dynamic_cast<Route *>(this))) {
2149 name = Route::ensure_track_or_route_name(requested_name, _session);
2150 } else {
2151 name = requested_name;
2155 /* replace all colons in the name. i wish we didn't have to do this */
2157 if (replace_all (name, ":", "-")) {
2158 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
2161 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2162 string current_name = (*i)->short_name();
2163 current_name.replace (current_name.find (_name), _name.length(), name);
2164 (*i)->set_name (current_name);
2167 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2168 string current_name = (*i)->short_name();
2169 current_name.replace (current_name.find (_name), _name.length(), name);
2170 (*i)->set_name (current_name);
2173 _name = name;
2174 name_changed (src); /* EMIT SIGNAL */
2176 return 0;
2179 void
2180 IO::set_input_minimum (int n)
2182 _input_minimum = n;
2185 void
2186 IO::set_input_maximum (int n)
2188 _input_maximum = n;
2191 void
2192 IO::set_output_minimum (int n)
2194 _output_minimum = n;
2197 void
2198 IO::set_output_maximum (int n)
2200 _output_maximum = n;
2203 void
2204 IO::set_port_latency (nframes_t nframes)
2206 Glib::Mutex::Lock lm (io_lock);
2208 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2209 (*i)->set_latency (nframes);
2213 nframes_t
2214 IO::output_latency () const
2216 nframes_t max_latency;
2217 nframes_t latency;
2219 max_latency = 0;
2221 /* io lock not taken - must be protected by other means */
2223 for (vector<Port *>::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2224 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2225 max_latency = latency;
2229 return max_latency;
2232 nframes_t
2233 IO::input_latency () const
2235 nframes_t max_latency;
2236 nframes_t latency;
2238 max_latency = 0;
2240 /* io lock not taken - must be protected by other means */
2242 for (vector<Port *>::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2243 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2244 max_latency = latency;
2248 return max_latency;
2252 IO::use_input_connection (Connection& c, void* src)
2254 uint32_t limit;
2257 BLOCK_PROCESS_CALLBACK ();
2258 Glib::Mutex::Lock lm2 (io_lock);
2260 limit = c.nports();
2262 drop_input_connection ();
2264 if (ensure_inputs (limit, false, false, src)) {
2265 return -1;
2268 /* first pass: check the current state to see what's correctly
2269 connected, and drop anything that we don't want.
2272 for (uint32_t n = 0; n < limit; ++n) {
2273 const Connection::PortList& pl = c.port_connections (n);
2275 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2277 if (!_inputs[n]->connected_to ((*i))) {
2279 /* clear any existing connections */
2281 _session.engine().disconnect (_inputs[n]);
2283 } else if (_inputs[n]->connected() > 1) {
2285 /* OK, it is connected to the port we want,
2286 but its also connected to other ports.
2287 Change that situation.
2290 /* XXX could be optimized to not drop
2291 the one we want.
2294 _session.engine().disconnect (_inputs[n]);
2300 /* second pass: connect all requested ports where necessary */
2302 for (uint32_t n = 0; n < limit; ++n) {
2303 const Connection::PortList& pl = c.port_connections (n);
2305 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2307 if (!_inputs[n]->connected_to ((*i))) {
2309 if (_session.engine().connect (*i, _inputs[n]->name())) {
2310 return -1;
2317 _input_connection = &c;
2319 input_connection_configuration_connection = c.ConfigurationChanged.connect
2320 (mem_fun (*this, &IO::input_connection_configuration_changed));
2321 input_connection_connection_connection = c.ConnectionsChanged.connect
2322 (mem_fun (*this, &IO::input_connection_connection_changed));
2325 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2326 return 0;
2330 IO::use_output_connection (Connection& c, void* src)
2332 uint32_t limit;
2335 BLOCK_PROCESS_CALLBACK ();
2336 Glib::Mutex::Lock lm2 (io_lock);
2338 limit = c.nports();
2340 drop_output_connection ();
2342 if (ensure_outputs (limit, false, false, src)) {
2343 return -1;
2346 /* first pass: check the current state to see what's correctly
2347 connected, and drop anything that we don't want.
2350 for (uint32_t n = 0; n < limit; ++n) {
2352 const Connection::PortList& pl = c.port_connections (n);
2354 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2356 if (!_outputs[n]->connected_to ((*i))) {
2358 /* clear any existing connections */
2360 _session.engine().disconnect (_outputs[n]);
2362 } else if (_outputs[n]->connected() > 1) {
2364 /* OK, it is connected to the port we want,
2365 but its also connected to other ports.
2366 Change that situation.
2369 /* XXX could be optimized to not drop
2370 the one we want.
2373 _session.engine().disconnect (_outputs[n]);
2378 /* second pass: connect all requested ports where necessary */
2380 for (uint32_t n = 0; n < limit; ++n) {
2382 const Connection::PortList& pl = c.port_connections (n);
2384 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2386 if (!_outputs[n]->connected_to ((*i))) {
2388 if (_session.engine().connect (_outputs[n]->name(), *i)) {
2389 return -1;
2395 _output_connection = &c;
2397 output_connection_configuration_connection = c.ConfigurationChanged.connect
2398 (mem_fun (*this, &IO::output_connection_configuration_changed));
2399 output_connection_connection_connection = c.ConnectionsChanged.connect
2400 (mem_fun (*this, &IO::output_connection_connection_changed));
2403 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2405 return 0;
2409 IO::disable_connecting ()
2411 connecting_legal = false;
2412 return 0;
2416 IO::enable_connecting ()
2418 connecting_legal = true;
2419 return ConnectingLegal ();
2423 IO::disable_ports ()
2425 ports_legal = false;
2426 return 0;
2430 IO::enable_ports ()
2432 ports_legal = true;
2433 return PortsLegal ();
2437 IO::disable_panners (void)
2439 panners_legal = false;
2440 return 0;
2444 IO::reset_panners ()
2446 panners_legal = true;
2447 return PannersLegal ();
2450 void
2451 IO::input_connection_connection_changed (int ignored)
2453 use_input_connection (*_input_connection, this);
2456 void
2457 IO::input_connection_configuration_changed ()
2459 use_input_connection (*_input_connection, this);
2462 void
2463 IO::output_connection_connection_changed (int ignored)
2465 use_output_connection (*_output_connection, this);
2468 void
2469 IO::output_connection_configuration_changed ()
2471 use_output_connection (*_output_connection, this);
2474 void
2475 IO::GainControllable::set_value (float val)
2477 io.set_gain (direct_control_to_gain (val), this);
2480 float
2481 IO::GainControllable::get_value (void) const
2483 return direct_gain_to_control (io.effective_gain());
2486 void
2487 IO::reset_peak_meters ()
2489 uint32_t limit = max (_ninputs, _noutputs);
2491 for (uint32_t i = 0; i < limit; ++i) {
2492 _peak_power[i] = 0;
2496 void
2497 IO::reset_max_peak_meters ()
2499 uint32_t limit = max (_ninputs, _noutputs);
2501 for (uint32_t i = 0; i < limit; ++i) {
2502 _max_peak_power[i] = -INFINITY;
2506 void
2507 IO::setup_peak_meters ()
2509 uint32_t limit = max (_ninputs, _noutputs);
2511 while (_peak_power.size() < limit) {
2512 _peak_power.push_back (0);
2513 _visible_peak_power.push_back (-INFINITY);
2514 _max_peak_power.push_back (-INFINITY);
2519 Update the peak meters.
2521 The meter signal lock is taken to prevent modification of the
2522 Meter signal while updating the meters, taking the meter signal
2523 lock prior to taking the io_lock ensures that all IO will remain
2524 valid while metering.
2526 void
2527 IO::update_meters()
2529 Glib::Mutex::Lock guard (m_meter_signal_lock);
2530 Meter();
2533 void
2534 IO::meter ()
2536 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2537 uint32_t limit = max (_ninputs, _noutputs);
2539 for (uint32_t n = 0; n < limit; ++n) {
2541 /* XXX we should use atomic exchange here */
2543 /* grab peak since last read */
2545 float new_peak = _peak_power[n];
2546 _peak_power[n] = 0;
2548 /* compute new visible value using falloff */
2550 if (new_peak > 0.0f) {
2551 new_peak = fast_coefficient_to_dB (new_peak);
2552 } else {
2553 new_peak = -INFINITY;
2556 /* update max peak */
2558 _max_peak_power[n] = max (new_peak, _max_peak_power[n]);
2560 if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
2561 _visible_peak_power[n] = new_peak;
2562 } else {
2563 // do falloff, the config value is in dB/sec, we get updated at 100/sec currently (should be a var somewhere)
2564 new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f);
2565 _visible_peak_power[n] = max (new_peak, -INFINITY);
2570 bool
2571 IO::gain_automation_recording ()
2573 return (_session.transport_rolling() && _gain_automation_curve.automation_write() );
2577 void
2578 IO::clear_automation ()
2580 Glib::Mutex::Lock lm (automation_lock);
2581 _gain_automation_curve.clear ();
2582 _panner->clear_automation ();
2585 void
2586 IO::set_gain_automation_state (AutoState state)
2588 bool changed = false;
2591 Glib::Mutex::Lock lm (automation_lock);
2593 if (state != _gain_automation_curve.automation_state()) {
2594 changed = true;
2595 last_automation_snapshot = 0;
2596 _gain_automation_curve.set_automation_state (state);
2598 /* don't reset gain if we're moving to Off or Write mode;
2599 if we're moving to Write, the user may have manually set up gains
2600 that they don't want to lose */
2601 if (state != Auto_Off && state != Auto_Write) {
2602 set_gain (_gain_automation_curve.eval (_session.transport_frame()), this);
2607 if (changed) {
2608 _session.set_dirty ();
2609 gain_automation_state_changed (); /* EMIT SIGNAL */
2613 void
2614 IO::set_gain_automation_style (AutoStyle style)
2616 bool changed = false;
2619 Glib::Mutex::Lock lm (automation_lock);
2621 if (style != _gain_automation_curve.automation_style()) {
2622 changed = true;
2623 _gain_automation_curve.set_automation_style (style);
2627 if (changed) {
2628 gain_automation_style_changed (); /* EMIT SIGNAL */
2631 void
2632 IO::inc_gain (gain_t factor, void *src)
2634 if (_desired_gain == 0.0f)
2635 set_gain (0.000001f + (0.000001f * factor), src);
2636 else
2637 set_gain (_desired_gain + (_desired_gain * factor), src);
2640 void
2641 IO::set_gain (gain_t val, void *src)
2643 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2645 if (val > 1.99526231f) {
2646 val = 1.99526231f;
2650 Glib::Mutex::Lock dm (declick_lock);
2651 _desired_gain = val;
2654 if (_session.transport_stopped()) {
2655 _effective_gain = val;
2656 // _gain = val;
2659 gain_changed (src);
2660 _gain_control.Changed (); /* EMIT SIGNAL */
2662 if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
2663 _gain_automation_curve.add (_session.transport_frame(), val);
2666 _session.set_dirty();
2669 void
2670 IO::start_gain_touch ()
2672 _gain_automation_curve.start_touch (_session.transport_frame());
2675 void
2676 IO::end_gain_touch ()
2678 bool mark = false;
2679 double when = 0;
2681 if (_session.transport_rolling() && _gain_automation_curve.automation_state() == Auto_Touch) {
2682 mark = true;
2683 when = _session.transport_frame();
2686 _gain_automation_curve.stop_touch (mark, when);
2689 void
2690 IO::start_pan_touch (uint32_t which)
2692 if (which < _panner->size()) {
2693 (*_panner)[which]->automation().start_touch (_session.transport_frame());
2697 void
2698 IO::end_pan_touch (uint32_t which)
2700 if (which < _panner->size()) {
2701 bool mark = false;
2702 double when = 0;
2704 if (_session.transport_rolling() && (*_panner)[which]->automation().automation_state() == Auto_Touch) {
2705 mark = true;
2706 when = _session.transport_frame();
2709 (*_panner)[which]->automation().stop_touch(mark, when);
2713 void
2714 IO::automation_snapshot (nframes_t now, bool force)
2716 if (gain_automation_recording()) {
2717 _gain_automation_curve.rt_add (now, gain());
2720 _panner->snapshot (now);
2721 last_automation_snapshot = now;
2724 void
2725 IO::transport_stopped (nframes_t frame)
2727 _gain_automation_curve.write_pass_finished (frame);
2729 if (_gain_automation_curve.automation_state() == Auto_Touch || _gain_automation_curve.automation_state() == Auto_Play) {
2731 /* the src=0 condition is a special signal to not propagate
2732 automation gain changes into the mix group when locating.
2735 set_gain (_gain_automation_curve.eval (frame), 0);
2738 _panner->transport_stopped (frame);
2741 string
2742 IO::build_legal_port_name (bool in)
2744 const int name_size = jack_port_name_size();
2745 int limit;
2746 const char* suffix;
2747 int maxports;
2749 /* note that if "in" or "out" are translated it will break a session
2750 across locale switches because a port's connection list will
2751 show (old) translated names, but the current port name will
2752 use the (new) translated name.
2755 if (in) {
2756 if (getenv ("ARDOUR_RETAIN_PORT_NAME_SUFFIX_TRANSLATION") != 0) {
2757 suffix = _("in");
2758 } else {
2759 suffix = X_("in");
2761 maxports = _input_maximum;
2762 } else {
2763 if (getenv ("ARDOUR_RETAIN_PORT_NAME_SUFFIX_TRANSLATION") != 0) {
2764 suffix = _("out");
2765 } else {
2766 suffix = X_("out");
2768 maxports = _output_maximum;
2771 if (maxports == 1) {
2772 // allow space for the slash + the suffix
2773 limit = name_size - _session.engine().client_name().length() - (strlen (suffix) + 1);
2774 char buf[name_size+1];
2775 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix);
2776 return string (buf);
2779 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2781 limit = name_size - _session.engine().client_name().length() - (strlen (suffix) + 5);
2783 char buf1[name_size+1];
2784 char buf2[name_size+1];
2786 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix);
2788 int port_number;
2790 if (in) {
2791 port_number = find_input_port_hole (buf1);
2792 } else {
2793 port_number = find_output_port_hole (buf1);
2796 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2798 return string (buf2);
2801 int32_t
2802 IO::find_input_port_hole (const char* base)
2804 /* CALLER MUST HOLD IO LOCK */
2806 uint32_t n;
2808 if (_inputs.empty()) {
2809 return 1;
2812 /* we only allow up to 4 characters for the port number
2815 for (n = 1; n < 9999; ++n) {
2816 char buf[jack_port_name_size()];
2817 vector<Port*>::iterator i;
2819 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2821 for (i = _inputs.begin(); i != _inputs.end(); ++i) {
2822 if ((*i)->short_name() == buf) {
2823 break;
2827 if (i == _inputs.end()) {
2828 break;
2831 return n;
2834 int32_t
2835 IO::find_output_port_hole (const char* base)
2837 /* CALLER MUST HOLD IO LOCK */
2839 uint32_t n;
2841 if (_outputs.empty()) {
2842 return 1;
2845 /* we only allow up to 4 characters for the port number
2848 for (n = 1; n < 9999; ++n) {
2849 char buf[jack_port_name_size()];
2850 vector<Port*>::iterator i;
2852 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2854 for (i = _outputs.begin(); i != _outputs.end(); ++i) {
2855 if ((*i)->short_name() == buf) {
2856 break;
2860 if (i == _outputs.end()) {
2861 break;
2865 return n;
2868 void
2869 IO::set_active (bool yn)
2871 _active = yn;
2872 active_changed(); /* EMIT SIGNAL */
2875 string
2876 IO::name_from_state (const XMLNode& node)
2878 const XMLProperty* prop;
2880 if ((prop = node.property ("name")) != 0) {
2881 return prop->value();
2884 return string();
2887 void
2888 IO::set_name_in_state (XMLNode& node, const string& new_name)
2890 const XMLProperty* prop;
2892 if ((prop = node.property ("name")) != 0) {
2893 node.add_property ("name", new_name);
2897 void
2898 IO::cycle_start (nframes_t nframes)
2900 _output_offset = 0;
2903 void
2904 IO::increment_output_offset (nframes_t n)
2906 _output_offset += n;
2909 Sample*
2910 IO::get_input_buffer (int n, nframes_t nframes)
2912 Port* port;
2914 if (!(port = input (n))) {
2915 return 0;
2918 return port->get_buffer (nframes);
2921 Sample*
2922 IO::get_output_buffer (int n, nframes_t nframes)
2924 Port* port;
2926 if (!(port = output (n))) {
2927 return 0;
2930 return port->get_buffer (nframes) + _output_offset;