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.
26 #include <sigc++/bind.h>
29 #include <glibmm/thread.h>
31 #include <pbd/xml++.h>
32 #include <pbd/replace_all.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/io.h>
36 #include <ardour/route.h>
37 #include <ardour/port.h>
38 #include <ardour/connection.h>
39 #include <ardour/session.h>
40 #include <ardour/cycle_timer.h>
41 #include <ardour/panner.h>
42 #include <ardour/dB.h>
51 A bug in OS X's cmath that causes isnan() and isinf() to be
52 "undeclared". the following works around that
55 #if defined(__APPLE__) && defined(__MACH__)
56 extern "C" int isnan (double);
57 extern "C" int isinf (double);
60 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
63 using namespace ARDOUR;
66 nframes_t IO::_automation_interval = 0;
67 const string IO::state_node_name = "IO";
68 bool IO::connecting_legal = false;
69 bool IO::ports_legal = false;
70 bool IO::panners_legal = false;
71 sigc::signal<void> IO::Meter;
72 sigc::signal<int> IO::ConnectingLegal;
73 sigc::signal<int> IO::PortsLegal;
74 sigc::signal<int> IO::PannersLegal;
75 sigc::signal<void,uint32_t> IO::MoreOutputs;
76 sigc::signal<int> IO::PortsCreated;
77 sigc::signal<void,nframes_t> IO::CycleStart;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
85 static gain_t direct_control_to_gain (double fract) {
86 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
87 /* this maxes at +6dB */
88 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
91 static double direct_gain_to_control (gain_t gain) {
92 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
93 if (gain == 0) return 0.0;
95 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
98 static bool sort_ports_by_name (Port* a, Port* b) {
100 unsigned int last_digit_position_a = a->name().size();
101 std::string::const_reverse_iterator r_iterator = a->name().rbegin();
103 while (r_iterator!=a->name().rend() and Glib::Unicode::isdigit(*r_iterator)) {
104 r_iterator++; last_digit_position_a--;
107 unsigned int last_digit_position_b = b->name().size();
108 r_iterator = b->name().rbegin();
110 while (r_iterator!=b->name().rend() and Glib::Unicode::isdigit(*r_iterator)) {
111 r_iterator++; last_digit_position_b--;
114 // if some of the names don't have a number as posfix, compare as strings
115 if (last_digit_position_a == a->name().size() or last_digit_position_b == b->name().size()) {
116 return a->name() < b->name();
119 const std::string prefix_a = a->name().substr(0, last_digit_position_a - 1);
120 const unsigned int posfix_a = std::atoi(a->name().substr(last_digit_position_a, a->name().size() - last_digit_position_a).c_str());
121 const std::string prefix_b = b->name().substr(0, last_digit_position_b - 1);
122 const unsigned int posfix_b = std::atoi(b->name().substr(last_digit_position_b, b->name().size() - last_digit_position_b).c_str());
124 if (prefix_a != prefix_b) {
125 return a->name() < b->name();
127 return posfix_a < posfix_b;
132 /** @param default_type The type of port that will be created by ensure_io
133 * and friends if no type is explicitly requested (to avoid breakage).
135 IO::IO (Session& s, string name,
136 int input_min, int input_max, int output_min, int output_max,
137 DataType default_type)
140 _default_type(default_type),
141 _gain_control (X_("gaincontrol"), *this),
142 _gain_automation_curve (0.0, 2.0, 1.0),
143 _input_minimum (input_min),
144 _input_maximum (input_max),
145 _output_minimum (output_min),
146 _output_maximum (output_max)
148 _panner = new Panner (name, _session);
152 _input_connection = 0;
153 _output_connection = 0;
154 pending_state_node = 0;
157 no_panner_reset = false;
160 apply_gain_automation = false;
161 _ignore_gain_on_deliver = false;
163 last_automation_snapshot = 0;
165 _gain_automation_state = Off;
166 _gain_automation_style = Absolute;
169 // IO::Meter is emitted from another thread so the
170 // Meter signal must be protected.
171 Glib::Mutex::Lock guard (m_meter_signal_lock);
172 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
176 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
178 _session.add_controllable (&_gain_control);
181 IO::IO (Session& s, const XMLNode& node, DataType dt)
184 _gain_control (X_("gaincontrol"), *this),
185 _gain_automation_curve (0, 0, 0) // all reset in set_state()
190 no_panner_reset = false;
193 _input_connection = 0;
194 _output_connection = 0;
198 apply_gain_automation = false;
199 _ignore_gain_on_deliver = false;
204 // IO::Meter is emitted from another thread so the
205 // Meter signal must be protected.
206 Glib::Mutex::Lock guard (m_meter_signal_lock);
207 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
211 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
213 _session.add_controllable (&_gain_control);
218 Glib::Mutex::Lock guard (m_meter_signal_lock);
220 Glib::Mutex::Lock lm (io_lock);
221 vector<Port *>::iterator i;
224 BLOCK_PROCESS_CALLBACK ();
226 for (i = _inputs.begin(); i != _inputs.end(); ++i) {
227 _session.engine().unregister_port (*i);
230 for (i = _outputs.begin(); i != _outputs.end(); ++i) {
231 _session.engine().unregister_port (*i);
235 m_meter_connection.disconnect();
239 IO::silence (nframes_t nframes)
241 /* io_lock, not taken: function must be called from Session::process() calltree */
243 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
244 (*i)->silence (nframes);
249 IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
251 nframes_t declick = min ((nframes_t)128, nframes);
254 double fractional_shift;
255 double fractional_pos;
256 gain_t polscale = invert_polarity ? -1.0f : 1.0f;
258 if (nframes == 0) return;
260 fractional_shift = -1.0/declick;
262 if (target < initial) {
263 /* fade out: remove more and more of delta from initial */
264 delta = -(initial - target);
266 /* fade in: add more and more of delta from initial */
267 delta = target - initial;
270 for (uint32_t n = 0; n < nbufs; ++n) {
273 fractional_pos = 1.0;
275 for (nframes_t nx = 0; nx < declick; ++nx) {
276 buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
277 fractional_pos += fractional_shift;
280 /* now ensure the rest of the buffer has the target value
281 applied, if necessary.
284 if (declick != nframes) {
287 if (invert_polarity) {
288 this_target = -target;
290 this_target = target;
293 if (this_target == 0.0) {
294 memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
295 } else if (this_target != 1.0) {
296 for (nframes_t nx = declick; nx < nframes; ++nx) {
297 buffer[nx] *= this_target;
305 IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, nframes_t start, nframes_t end, nframes_t nframes)
309 /* io_lock, not taken: function must be called from Session::process() calltree */
311 if (_noutputs == 0) {
315 if (_noutputs == 1) {
317 dst = get_output_buffer (0, nframes);
319 for (uint32_t n = 0; n < nbufs; ++n) {
320 if (bufs[n] != dst) {
321 memcpy (dst, bufs[n], sizeof (Sample) * nframes);
325 output(0)->mark_silence (false);
331 vector<Port *>::iterator out;
332 vector<Sample *>::iterator in;
333 Panner::iterator pan;
334 Sample* obufs[_noutputs];
336 /* the terrible silence ... */
338 for (out = _outputs.begin(), o = 0; out != _outputs.end(); ++out, ++o) {
339 obufs[o] = get_output_buffer (o, nframes);
340 memset (obufs[o], 0, sizeof (Sample) * nframes);
341 (*out)->mark_silence (false);
346 for (pan = _panner->begin(), n = 0; n < nbufs; ++n, ++pan) {
347 (*pan)->distribute_automated (bufs[n], obufs, start, end, nframes, _session.pan_automation_buffer());
352 IO::pan (vector<Sample*>& bufs, uint32_t nbufs, nframes_t nframes, gain_t gain_coeff)
357 /* io_lock, not taken: function must be called from Session::process() calltree */
359 if (_noutputs == 0) {
363 /* the panner can be empty if there are no inputs to the
364 route, but still outputs
367 if (_panner->bypassed() || _panner->empty()) {
368 deliver_output_no_pan (bufs, nbufs, nframes);
372 if (_noutputs == 1) {
374 dst = get_output_buffer (0, nframes);
376 if (gain_coeff == 0.0f) {
378 /* only one output, and gain was zero, so make it silent */
380 memset (dst, 0, sizeof (Sample) * nframes);
382 } else if (gain_coeff == 1.0f){
384 /* mix all buffers into the output */
388 memcpy (dst, bufs[0], sizeof (Sample) * nframes);
390 for (n = 1; n < nbufs; ++n) {
391 Session::mix_buffers_no_gain(dst,bufs[n],nframes);
394 output(0)->mark_silence (false);
398 /* mix all buffers into the output, scaling them all by the gain */
404 for (nframes_t n = 0; n < nframes; ++n) {
405 dst[n] = src[n] * gain_coeff;
408 for (n = 1; n < nbufs; ++n) {
409 Session::mix_buffers_with_gain(dst,bufs[n],nframes,gain_coeff);
412 output(0)->mark_silence (false);
419 vector<Port *>::iterator out;
420 vector<Sample *>::iterator in;
421 Panner::iterator pan;
422 Sample* obufs[_noutputs];
424 /* the terrible silence ... */
426 /* XXX this is wasteful but i see no way to avoid it */
428 for (out = _outputs.begin(), o = 0; out != _outputs.end(); ++out, ++o) {
429 obufs[o] = get_output_buffer (o, nframes);
430 memset (obufs[o], 0, sizeof (Sample) * nframes);
431 (*out)->mark_silence (false);
436 for (pan = _panner->begin(), n = 0; n < nbufs; ++n) {
437 Panner::iterator tmp;
442 (*pan)->distribute (bufs[n], obufs, gain_coeff, nframes);
444 if (tmp != _panner->end()) {
451 IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
453 /* io_lock, not taken: function must be called from Session::process() calltree */
455 if (_noutputs == 0) {
459 if (_panner->bypassed() || _panner->empty()) {
460 deliver_output_no_pan (bufs, nbufs, nframes);
466 gain_t pangain = _gain;
469 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
479 apply_declick (bufs, nbufs, nframes, _gain, dg, false);
484 /* simple, non-automation panning to outputs */
486 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
487 pan (bufs, nbufs, nframes, pangain * speed_quietning);
489 pan (bufs, nbufs, nframes, pangain);
494 IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
496 /* io_lock, not taken: function must be called from Session::process() calltree */
498 if (_noutputs == 0) {
503 gain_t old_gain = _gain;
505 if (apply_gain_automation || _ignore_gain_on_deliver) {
507 /* gain has already been applied by automation code. do nothing here except
516 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
528 vector<Port*>::iterator o;
529 vector<Sample*> outs;
532 /* reduce nbufs to the index of the last input buffer */
536 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
537 actual_gain = _gain * speed_quietning;
542 for (o = _outputs.begin(), i = 0; o != _outputs.end(); ++o, ++i) {
544 dst = get_output_buffer (i, nframes);
545 src = bufs[min(nbufs,i)];
548 /* unlikely condition */
549 outs.push_back (dst);
552 if (dg != _gain || actual_gain == 1.0f) {
553 memcpy (dst, src, sizeof (Sample) * nframes);
554 } else if (actual_gain == 0.0f) {
555 memset (dst, 0, sizeof (Sample) * nframes);
557 for (nframes_t x = 0; x < nframes; ++x) {
558 dst[x] = src[x] * actual_gain;
562 (*o)->mark_silence (false);
566 apply_declick (outs, i, nframes, _gain, dg, false);
570 if (apply_gain_automation || _ignore_gain_on_deliver) {
576 IO::collect_input (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes)
578 /* io_lock, not taken: function must be called from Session::process() calltree */
580 vector<Port *>::iterator i;
584 /* we require that bufs.size() >= 1 */
586 for (n = 0, i = _inputs.begin(); n < nbufs; ++i, ++n) {
587 if (i == _inputs.end()) {
591 last = get_input_buffer (n, nframes);
592 memcpy (bufs[n], last, sizeof (Sample) * nframes);
595 /* fill any excess outputs with the last input */
599 memcpy (bufs[n], last, sizeof (Sample) * nframes);
604 memset (bufs[n], 0, sizeof (Sample) * nframes);
611 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
613 vector<Sample*>& bufs = _session.get_passthru_buffers ();
614 uint32_t nbufs = n_process_buffers ();
616 collect_input (bufs, nbufs, nframes);
618 for (uint32_t n = 0; n < nbufs; ++n) {
619 _peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
624 IO::drop_input_connection ()
626 _input_connection = 0;
627 input_connection_configuration_connection.disconnect();
628 input_connection_connection_connection.disconnect();
629 _session.set_dirty ();
633 IO::drop_output_connection ()
635 _output_connection = 0;
636 output_connection_configuration_connection.disconnect();
637 output_connection_connection_connection.disconnect();
638 _session.set_dirty ();
642 IO::disconnect_input (Port* our_port, string other_port, void* src)
644 if (other_port.length() == 0 || our_port == 0) {
649 BLOCK_PROCESS_CALLBACK ();
652 Glib::Mutex::Lock lm (io_lock);
654 /* check that our_port is really one of ours */
656 if (find (_inputs.begin(), _inputs.end(), our_port) == _inputs.end()) {
660 /* disconnect it from the source */
662 if (_session.engine().disconnect (other_port, our_port->name())) {
663 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
667 drop_input_connection();
671 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
672 _session.set_dirty ();
678 IO::connect_input (Port* our_port, string other_port, void* src)
680 if (other_port.length() == 0 || our_port == 0) {
685 BLOCK_PROCESS_CALLBACK ();
688 Glib::Mutex::Lock lm (io_lock);
690 /* check that our_port is really one of ours */
692 if (find (_inputs.begin(), _inputs.end(), our_port) == _inputs.end()) {
696 /* connect it to the source */
698 if (_session.engine().connect (other_port, our_port->name())) {
702 drop_input_connection ();
706 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
707 _session.set_dirty ();
712 IO::disconnect_output (Port* our_port, string other_port, void* src)
714 if (other_port.length() == 0 || our_port == 0) {
719 BLOCK_PROCESS_CALLBACK ();
722 Glib::Mutex::Lock lm (io_lock);
724 if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
728 /* disconnect it from the destination */
730 if (_session.engine().disconnect (our_port->name(), other_port)) {
731 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
735 drop_output_connection ();
739 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
740 _session.set_dirty ();
745 IO::connect_output (Port* our_port, string other_port, void* src)
747 if (other_port.length() == 0 || our_port == 0) {
752 BLOCK_PROCESS_CALLBACK ();
756 Glib::Mutex::Lock lm (io_lock);
758 /* check that our_port is really one of ours */
760 if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
764 /* connect it to the destination */
766 if (_session.engine().connect (our_port->name(), other_port)) {
770 drop_output_connection ();
774 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
775 _session.set_dirty ();
780 IO::set_input (Port* other_port, void* src)
782 /* this removes all but one ports, and connects that one port
783 to the specified source.
786 if (_input_minimum > 1 || _input_minimum == 0) {
787 /* sorry, you can't do this */
791 if (other_port == 0) {
792 if (_input_minimum < 0) {
793 return ensure_inputs (0, false, true, src);
799 if (ensure_inputs (1, true, true, src)) {
803 return connect_input (_inputs.front(), other_port->name(), src);
807 IO::remove_output_port (Port* port, void* src)
809 IOChange change (NoChange);
812 BLOCK_PROCESS_CALLBACK ();
816 Glib::Mutex::Lock lm (io_lock);
818 if (_noutputs - 1 == (uint32_t) _output_minimum) {
819 /* sorry, you can't do this */
823 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
825 change = IOChange (change|ConfigurationChanged);
826 if (port->connected()) {
827 change = IOChange (change|ConnectionsChanged);
830 _session.engine().unregister_port (*i);
833 drop_output_connection ();
839 if (change != NoChange) {
840 setup_peak_meters ();
846 if (change != NoChange) {
847 output_changed (change, src); /* EMIT SIGNAL */
848 _session.set_dirty ();
855 /** Add an output port.
857 * @param destination Name of input port to connect new port to.
858 * @param src Source for emitted ConfigurationChanged signal.
859 * @param type Data type of port. Default value (NIL) will use this IO's default type.
862 IO::add_output_port (string destination, void* src, DataType type)
866 if (type == DataType::NIL)
867 type = _default_type;
870 BLOCK_PROCESS_CALLBACK ();
874 Glib::Mutex::Lock lm (io_lock);
876 if (_output_maximum >= 0 && (int) _noutputs == _output_maximum) {
880 /* Create a new output port */
882 string portname = build_legal_port_name (false);
884 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
885 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
889 _outputs.push_back (our_port);
890 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
892 drop_output_connection ();
893 setup_peak_meters ();
897 MoreOutputs (_noutputs); /* EMIT SIGNAL */
900 if (destination.length()) {
901 if (_session.engine().connect (our_port->name(), destination)) {
906 // pan_changed (src); /* EMIT SIGNAL */
907 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
908 _session.set_dirty ();
913 IO::remove_input_port (Port* port, void* src)
915 IOChange change (NoChange);
918 BLOCK_PROCESS_CALLBACK ();
922 Glib::Mutex::Lock lm (io_lock);
924 if (((int)_ninputs - 1) < _input_minimum) {
925 /* sorry, you can't do this */
928 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
931 change = IOChange (change|ConfigurationChanged);
933 if (port->connected()) {
934 change = IOChange (change|ConnectionsChanged);
937 _session.engine().unregister_port (*i);
940 drop_input_connection ();
946 if (change != NoChange) {
947 setup_peak_meters ();
953 if (change != NoChange) {
954 input_changed (change, src);
955 _session.set_dirty ();
963 /** Add an input port.
965 * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
966 * @param destination Name of input port to connect new port to.
967 * @param src Source for emitted ConfigurationChanged signal.
970 IO::add_input_port (string source, void* src, DataType type)
974 if (type == DataType::NIL)
975 type = _default_type;
978 BLOCK_PROCESS_CALLBACK ();
981 Glib::Mutex::Lock lm (io_lock);
983 if (_input_maximum >= 0 && (int) _ninputs == _input_maximum) {
987 /* Create a new input port */
989 string portname = build_legal_port_name (true);
991 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
992 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
996 _inputs.push_back (our_port);
997 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
999 drop_input_connection ();
1000 setup_peak_meters ();
1004 MoreOutputs (_ninputs); /* EMIT SIGNAL */
1007 if (source.length()) {
1009 if (_session.engine().connect (source, our_port->name())) {
1014 // pan_changed (src); /* EMIT SIGNAL */
1015 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1016 _session.set_dirty ();
1022 IO::disconnect_inputs (void* src)
1025 BLOCK_PROCESS_CALLBACK ();
1028 Glib::Mutex::Lock lm (io_lock);
1030 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1031 _session.engine().disconnect (*i);
1034 drop_input_connection ();
1037 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1042 IO::disconnect_outputs (void* src)
1045 BLOCK_PROCESS_CALLBACK ();
1048 Glib::Mutex::Lock lm (io_lock);
1050 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1051 _session.engine().disconnect (*i);
1054 drop_output_connection ();
1058 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1059 _session.set_dirty ();
1064 IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
1067 bool changed = false;
1068 bool reduced = false;
1070 /* remove unused ports */
1072 while (_ninputs > n) {
1073 _session.engine().unregister_port (_inputs.back());
1080 /* create any necessary new ports */
1082 while (_ninputs < n) {
1084 /* Create a new input port (of the default type) */
1086 string portname = build_legal_port_name (true);
1090 if ((input_port = _session.engine().register_input_port (_default_type, portname)) == 0) {
1091 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
1096 catch (AudioEngine::PortRegistrationFailure& err) {
1097 setup_peak_meters ();
1103 _inputs.push_back (input_port);
1104 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1110 drop_input_connection ();
1111 setup_peak_meters ();
1113 MoreOutputs (_ninputs); /* EMIT SIGNAL */
1114 _session.set_dirty ();
1118 /* disconnect all existing ports so that we get a fresh start */
1120 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1121 _session.engine().disconnect (*i);
1129 IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
1131 bool in_changed = false;
1132 bool out_changed = false;
1133 bool in_reduced = false;
1134 bool out_reduced = false;
1135 bool need_pan_reset;
1137 if (_input_maximum >= 0) {
1138 nin = min (_input_maximum, (int) nin);
1141 if (_output_maximum >= 0) {
1142 nout = min (_output_maximum, (int) nout);
1145 if (nin == _ninputs && nout == _noutputs && !clear) {
1150 BLOCK_PROCESS_CALLBACK ();
1151 Glib::Mutex::Lock lm (io_lock);
1155 if (_noutputs == nout) {
1156 need_pan_reset = false;
1158 need_pan_reset = true;
1161 /* remove unused ports */
1163 while (_ninputs > nin) {
1164 _session.engine().unregister_port (_inputs.back());
1171 while (_noutputs > nout) {
1172 _session.engine().unregister_port (_outputs.back());
1173 _outputs.pop_back();
1179 /* create any necessary new ports (of the default type) */
1181 while (_ninputs < nin) {
1183 /* Create a new input port */
1185 string portname = build_legal_port_name (true);
1188 if ((port = _session.engine().register_input_port (_default_type, portname)) == 0) {
1189 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
1194 catch (AudioEngine::PortRegistrationFailure& err) {
1195 setup_peak_meters ();
1201 _inputs.push_back (port);
1206 /* create any necessary new ports */
1208 while (_noutputs < nout) {
1210 string portname = build_legal_port_name (false);
1213 if ((port = _session.engine().register_output_port (_default_type, portname)) == 0) {
1214 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1219 catch (AudioEngine::PortRegistrationFailure& err) {
1220 setup_peak_meters ();
1226 _outputs.push_back (port);
1233 /* disconnect all existing ports so that we get a fresh start */
1235 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1236 _session.engine().disconnect (*i);
1239 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1240 _session.engine().disconnect (*i);
1244 if (in_changed || out_changed) {
1245 setup_peak_meters ();
1251 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
1252 drop_output_connection ();
1253 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1257 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1258 drop_input_connection ();
1259 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1262 if (in_changed || out_changed) {
1263 MoreOutputs (max (_noutputs, _ninputs)); /* EMIT SIGNAL */
1264 _session.set_dirty ();
1271 IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
1273 bool changed = false;
1275 if (_input_maximum >= 0) {
1276 n = min (_input_maximum, (int) n);
1278 if (n == _ninputs && !clear) {
1284 BLOCK_PROCESS_CALLBACK ();
1285 Glib::Mutex::Lock im (io_lock);
1286 changed = ensure_inputs_locked (n, clear, src);
1288 changed = ensure_inputs_locked (n, clear, src);
1292 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1293 _session.set_dirty ();
1300 IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
1303 bool changed = false;
1304 bool reduced = false;
1305 bool need_pan_reset;
1307 if (_noutputs == n) {
1308 need_pan_reset = false;
1310 need_pan_reset = true;
1313 /* remove unused ports */
1315 while (_noutputs > n) {
1317 _session.engine().unregister_port (_outputs.back());
1318 _outputs.pop_back();
1324 /* create any necessary new ports */
1326 while (_noutputs < n) {
1328 /* Create a new output port */
1330 string portname = build_legal_port_name (false);
1332 if ((output_port = _session.engine().register_output_port (_default_type, portname)) == 0) {
1333 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1337 _outputs.push_back (output_port);
1338 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
1341 setup_peak_meters ();
1343 if (need_pan_reset) {
1349 drop_output_connection ();
1350 MoreOutputs (_noutputs); /* EMIT SIGNAL */
1351 _session.set_dirty ();
1355 /* disconnect all existing ports so that we get a fresh start */
1357 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1358 _session.engine().disconnect (*i);
1366 IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src)
1368 bool changed = false;
1370 if (_output_maximum >= 0) {
1371 n = min (_output_maximum, (int) n);
1372 if (n == _noutputs && !clear) {
1377 /* XXX caller should hold io_lock, but generally doesn't */
1380 BLOCK_PROCESS_CALLBACK ();
1381 Glib::Mutex::Lock im (io_lock);
1382 changed = ensure_outputs_locked (n, clear, src);
1384 changed = ensure_outputs_locked (n, clear, src);
1388 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1395 IO::effective_gain () const
1397 if (gain_automation_playback()) {
1398 return _effective_gain;
1400 return _desired_gain;
1407 if (panners_legal) {
1408 if (!no_panner_reset) {
1409 _panner->reset (_noutputs, pans_required());
1412 panner_legal_c.disconnect ();
1413 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1418 IO::panners_became_legal ()
1420 _panner->reset (_noutputs, pans_required());
1421 _panner->load (); // automation
1422 panner_legal_c.disconnect ();
1427 IO::defer_pan_reset ()
1429 no_panner_reset = true;
1433 IO::allow_pan_reset ()
1435 no_panner_reset = false;
1441 IO::get_state (void)
1443 return state (true);
1447 IO::state (bool full_state)
1449 XMLNode* node = new XMLNode (state_node_name);
1452 bool need_ins = true;
1453 bool need_outs = true;
1454 LocaleGuard lg (X_("POSIX"));
1455 Glib::Mutex::Lock lm (io_lock);
1457 node->add_property("name", _name);
1458 id().print (buf, sizeof (buf));
1459 node->add_property("id", buf);
1460 node->add_property("active", _active? "yes" : "no");
1464 if (_input_connection) {
1465 node->add_property ("input-connection", _input_connection->name());
1469 if (_output_connection) {
1470 node->add_property ("output-connection", _output_connection->name());
1475 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1477 const char **connections = (*i)->get_connections();
1479 if (connections && connections[0]) {
1482 for (int n = 0; connections && connections[n]; ++n) {
1487 /* if its a connection to our own port,
1488 return only the port name, not the
1489 whole thing. this allows connections
1490 to be re-established even when our
1491 client name is different.
1494 str += _session.engine().make_port_name_relative (connections[n]);
1506 node->add_property ("inputs", str);
1512 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1514 const char **connections = (*i)->get_connections();
1516 if (connections && connections[0]) {
1520 for (int n = 0; connections[n]; ++n) {
1525 str += _session.engine().make_port_name_relative (connections[n]);
1537 node->add_property ("outputs", str);
1540 node->add_child_nocopy (_panner->state (full_state));
1541 node->add_child_nocopy (_gain_control.get_state ());
1543 snprintf (buf, sizeof(buf), "%2.12f", gain());
1544 node->add_property ("gain", buf);
1546 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d",
1552 node->add_property ("iolimits", buf);
1558 XMLNode* autonode = new XMLNode (X_("Automation"));
1559 autonode->add_child_nocopy (get_automation_state());
1560 node->add_child_nocopy (*autonode);
1562 snprintf (buf, sizeof (buf), "0x%x", (int) _gain_automation_curve.automation_state());
1564 /* never store anything except Off for automation state in a template */
1565 snprintf (buf, sizeof (buf), "0x%x", ARDOUR::Off);
1572 IO::set_state (const XMLNode& node)
1574 const XMLProperty* prop;
1575 XMLNodeConstIterator iter;
1576 LocaleGuard lg (X_("POSIX"));
1578 /* force use of non-localized representation of decimal point,
1579 since we use it a lot in XML files and so forth.
1582 if (node.name() != state_node_name) {
1583 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1587 if ((prop = node.property ("name")) != 0) {
1588 _name = prop->value();
1589 /* used to set panner name with this, but no more */
1592 if ((prop = node.property ("id")) != 0) {
1593 _id = prop->value ();
1596 if ((prop = node.property ("iolimits")) != 0) {
1597 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1604 if ((prop = node.property ("gain")) != 0) {
1605 set_gain (atof (prop->value().c_str()), this);
1606 _gain = _desired_gain;
1609 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1610 /* old school automation handling */
1613 if ((prop = node.property (X_("active"))) != 0) {
1614 set_active (prop->value() == "yes");
1617 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1619 if ((*iter)->name() == "Panner") {
1621 _panner = new Panner (_name, _session);
1623 _panner->set_state (**iter);
1626 if ((*iter)->name() == X_("Automation")) {
1628 set_automation_state (*(*iter)->children().front());
1631 if ((*iter)->name() == X_("controllable")) {
1632 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1633 _gain_control.set_state (**iter);
1640 if (create_ports (node)) {
1646 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1649 if (panners_legal) {
1652 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1655 if (connecting_legal) {
1657 if (make_connections (node)) {
1663 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1666 if (!ports_legal || !connecting_legal) {
1667 pending_state_node = new XMLNode (node);
1670 last_automation_snapshot = 0;
1676 IO::set_automation_state (const XMLNode& node)
1678 return _gain_automation_curve.set_state (node);
1682 IO::get_automation_state ()
1684 return (_gain_automation_curve.get_state ());
1688 IO::load_automation (string path)
1693 uint32_t linecnt = 0;
1695 LocaleGuard lg (X_("POSIX"));
1697 fullpath = Glib::build_filename(_session.automation_dir(), path);
1699 in.open (fullpath.c_str());
1702 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1704 in.open (fullpath.c_str());
1707 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1712 clear_automation ();
1714 while (in.getline (line, sizeof(line), '\n')) {
1716 jack_nframes_t when;
1719 if (++linecnt == 1) {
1720 if (memcmp (line, "version", 7) == 0) {
1721 if (sscanf (line, "version %f", &version) != 1) {
1722 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1726 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1733 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1734 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1740 _gain_automation_curve.fast_simple_add (when, value);
1750 /* older (pre-1.0) versions of ardour used this */
1754 warning << _("dubious automation event found (and ignored)") << endmsg;
1762 IO::connecting_became_legal ()
1766 if (pending_state_node == 0) {
1767 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1772 connection_legal_c.disconnect ();
1774 ret = make_connections (*pending_state_node);
1777 delete pending_state_node;
1778 pending_state_node = 0;
1784 IO::ports_became_legal ()
1788 if (pending_state_node == 0) {
1789 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1794 port_legal_c.disconnect ();
1796 ret = create_ports (*pending_state_node);
1798 if (connecting_legal) {
1799 delete pending_state_node;
1800 pending_state_node = 0;
1807 IO::find_possible_connection(const string &desired_name, const string &default_name, const string &connection_type_name)
1809 static const string digits = "0123456789";
1811 Connection* c = _session.connection_by_name (desired_name);
1814 int connection_number, mask;
1815 string possible_name;
1816 bool stereo = false;
1817 string::size_type last_non_digit_pos;
1819 error << string_compose(_("Unknown connection \"%1\" listed for %2 of %3"), desired_name, connection_type_name, _name)
1822 // find numeric suffix of desired name
1823 connection_number = 0;
1825 last_non_digit_pos = desired_name.find_last_not_of(digits);
1827 if (last_non_digit_pos != string::npos) {
1829 s << desired_name.substr(last_non_digit_pos);
1830 s >> connection_number;
1833 // see if it's a stereo connection e.g. "in 3+4"
1835 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1836 int left_connection_number = 0;
1837 string::size_type left_last_non_digit_pos;
1839 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1841 if (left_last_non_digit_pos != string::npos) {
1843 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1844 s >> left_connection_number;
1846 if (left_connection_number > 0 && left_connection_number + 1 == connection_number) {
1847 connection_number--;
1854 if (connection_number)
1855 connection_number--;
1857 // find highest set bit
1859 while ((mask <= connection_number) && (mask <<= 1));
1861 // "wrap" connection number into largest possible power of 2
1866 if (connection_number & mask) {
1867 connection_number &= ~mask;
1870 s << default_name << " " << connection_number + 1;
1873 s << "+" << connection_number + 2;
1876 possible_name = s.str();
1878 if ((c = _session.connection_by_name (possible_name)) != 0) {
1885 info << string_compose (_("Connection %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1888 error << string_compose(_("No %1 connections available as a replacement"), connection_type_name)
1899 IO::create_ports (const XMLNode& node)
1901 const XMLProperty* prop;
1903 int num_outputs = 0;
1905 if ((prop = node.property ("input-connection")) != 0) {
1907 Connection* c = find_possible_connection(prop->value(), _("in"), _("input"));
1913 num_inputs = c->nports();
1915 } else if ((prop = node.property ("inputs")) != 0) {
1917 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1920 if ((prop = node.property ("output-connection")) != 0) {
1921 Connection* c = find_possible_connection(prop->value(), _("out"), _("output"));
1927 num_outputs = c->nports ();
1929 } else if ((prop = node.property ("outputs")) != 0) {
1930 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1933 no_panner_reset = true;
1935 if (ensure_io (num_inputs, num_outputs, true, this)) {
1936 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1940 no_panner_reset = false;
1942 set_deferred_state ();
1950 IO::make_connections (const XMLNode& node)
1952 const XMLProperty* prop;
1954 if ((prop = node.property ("input-connection")) != 0) {
1955 Connection* c = find_possible_connection (prop->value(), _("in"), _("input"));
1961 use_input_connection (*c, this);
1963 } else if ((prop = node.property ("inputs")) != 0) {
1964 if (set_inputs (prop->value())) {
1965 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1970 if ((prop = node.property ("output-connection")) != 0) {
1971 Connection* c = find_possible_connection (prop->value(), _("out"), _("output"));
1977 use_output_connection (*c, this);
1979 } else if ((prop = node.property ("outputs")) != 0) {
1980 if (set_outputs (prop->value())) {
1981 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1990 IO::set_inputs (const string& str)
1992 vector<string> ports;
1997 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
2001 if (ensure_inputs (nports, true, true, this)) {
2005 string::size_type start, end, ostart;
2012 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
2015 if ((end = str.find_first_of ('}', start)) == string::npos) {
2016 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
2020 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
2021 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
2027 for (int x = 0; x < n; ++x) {
2028 connect_input (input (i), ports[x], this);
2040 IO::set_outputs (const string& str)
2042 vector<string> ports;
2047 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
2051 if (ensure_outputs (nports, true, true, this)) {
2055 string::size_type start, end, ostart;
2062 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
2065 if ((end = str.find_first_of ('}', start)) == string::npos) {
2066 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
2070 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
2071 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
2077 for (int x = 0; x < n; ++x) {
2078 connect_output (output (i), ports[x], this);
2090 IO::parse_io_string (const string& str, vector<string>& ports)
2092 string::size_type pos, opos;
2094 if (str.length() == 0) {
2103 while ((pos = str.find_first_of (',', opos)) != string::npos) {
2104 ports.push_back (str.substr (opos, pos - opos));
2108 if (opos < str.length()) {
2109 ports.push_back (str.substr(opos));
2112 return ports.size();
2116 IO::parse_gain_string (const string& str, vector<string>& ports)
2118 string::size_type pos, opos;
2124 while ((pos = str.find_first_of (',', opos)) != string::npos) {
2125 ports.push_back (str.substr (opos, pos - opos));
2129 if (opos < str.length()) {
2130 ports.push_back (str.substr(opos));
2133 return ports.size();
2137 IO::set_name (string requested_name, void* src)
2139 if (requested_name == _name) {
2145 if ( (rt = dynamic_cast<Route *>(this))) {
2146 name = Route::ensure_track_or_route_name(requested_name, _session);
2148 name = requested_name;
2152 /* replace all colons in the name. i wish we didn't have to do this */
2154 if (replace_all (name, ":", "-")) {
2155 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
2158 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2159 string current_name = (*i)->short_name();
2160 current_name.replace (current_name.find (_name), _name.length(), name);
2161 (*i)->set_name (current_name);
2164 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2165 string current_name = (*i)->short_name();
2166 current_name.replace (current_name.find (_name), _name.length(), name);
2167 (*i)->set_name (current_name);
2171 name_changed (src); /* EMIT SIGNAL */
2177 IO::set_input_minimum (int n)
2183 IO::set_input_maximum (int n)
2189 IO::set_output_minimum (int n)
2191 _output_minimum = n;
2195 IO::set_output_maximum (int n)
2197 _output_maximum = n;
2201 IO::set_port_latency (nframes_t nframes)
2203 Glib::Mutex::Lock lm (io_lock);
2205 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2206 (*i)->set_latency (nframes);
2211 IO::output_latency () const
2213 nframes_t max_latency;
2218 /* io lock not taken - must be protected by other means */
2220 for (vector<Port *>::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2221 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2222 max_latency = latency;
2230 IO::input_latency () const
2232 nframes_t max_latency;
2237 /* io lock not taken - must be protected by other means */
2239 for (vector<Port *>::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2240 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2241 max_latency = latency;
2249 IO::use_input_connection (Connection& c, void* src)
2254 BLOCK_PROCESS_CALLBACK ();
2255 Glib::Mutex::Lock lm2 (io_lock);
2259 drop_input_connection ();
2261 if (ensure_inputs (limit, false, false, src)) {
2265 /* first pass: check the current state to see what's correctly
2266 connected, and drop anything that we don't want.
2269 for (uint32_t n = 0; n < limit; ++n) {
2270 const Connection::PortList& pl = c.port_connections (n);
2272 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2274 if (!_inputs[n]->connected_to ((*i))) {
2276 /* clear any existing connections */
2278 _session.engine().disconnect (_inputs[n]);
2280 } else if (_inputs[n]->connected() > 1) {
2282 /* OK, it is connected to the port we want,
2283 but its also connected to other ports.
2284 Change that situation.
2287 /* XXX could be optimized to not drop
2291 _session.engine().disconnect (_inputs[n]);
2297 /* second pass: connect all requested ports where necessary */
2299 for (uint32_t n = 0; n < limit; ++n) {
2300 const Connection::PortList& pl = c.port_connections (n);
2302 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2304 if (!_inputs[n]->connected_to ((*i))) {
2306 if (_session.engine().connect (*i, _inputs[n]->name())) {
2314 _input_connection = &c;
2316 input_connection_configuration_connection = c.ConfigurationChanged.connect
2317 (mem_fun (*this, &IO::input_connection_configuration_changed));
2318 input_connection_connection_connection = c.ConnectionsChanged.connect
2319 (mem_fun (*this, &IO::input_connection_connection_changed));
2322 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2327 IO::use_output_connection (Connection& c, void* src)
2332 BLOCK_PROCESS_CALLBACK ();
2333 Glib::Mutex::Lock lm2 (io_lock);
2337 drop_output_connection ();
2339 if (ensure_outputs (limit, false, false, src)) {
2343 /* first pass: check the current state to see what's correctly
2344 connected, and drop anything that we don't want.
2347 for (uint32_t n = 0; n < limit; ++n) {
2349 const Connection::PortList& pl = c.port_connections (n);
2351 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2353 if (!_outputs[n]->connected_to ((*i))) {
2355 /* clear any existing connections */
2357 _session.engine().disconnect (_outputs[n]);
2359 } else if (_outputs[n]->connected() > 1) {
2361 /* OK, it is connected to the port we want,
2362 but its also connected to other ports.
2363 Change that situation.
2366 /* XXX could be optimized to not drop
2370 _session.engine().disconnect (_outputs[n]);
2375 /* second pass: connect all requested ports where necessary */
2377 for (uint32_t n = 0; n < limit; ++n) {
2379 const Connection::PortList& pl = c.port_connections (n);
2381 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2383 if (!_outputs[n]->connected_to ((*i))) {
2385 if (_session.engine().connect (_outputs[n]->name(), *i)) {
2392 _output_connection = &c;
2394 output_connection_configuration_connection = c.ConfigurationChanged.connect
2395 (mem_fun (*this, &IO::output_connection_configuration_changed));
2396 output_connection_connection_connection = c.ConnectionsChanged.connect
2397 (mem_fun (*this, &IO::output_connection_connection_changed));
2400 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2406 IO::disable_connecting ()
2408 connecting_legal = false;
2413 IO::enable_connecting ()
2415 connecting_legal = true;
2416 return ConnectingLegal ();
2420 IO::disable_ports ()
2422 ports_legal = false;
2430 return PortsLegal ();
2434 IO::disable_panners (void)
2436 panners_legal = false;
2441 IO::reset_panners ()
2443 panners_legal = true;
2444 return PannersLegal ();
2448 IO::input_connection_connection_changed (int ignored)
2450 use_input_connection (*_input_connection, this);
2454 IO::input_connection_configuration_changed ()
2456 use_input_connection (*_input_connection, this);
2460 IO::output_connection_connection_changed (int ignored)
2462 use_output_connection (*_output_connection, this);
2466 IO::output_connection_configuration_changed ()
2468 use_output_connection (*_output_connection, this);
2472 IO::GainControllable::set_value (float val)
2474 io.set_gain (direct_control_to_gain (val), this);
2478 IO::GainControllable::get_value (void) const
2480 return direct_gain_to_control (io.effective_gain());
2484 IO::reset_peak_meters ()
2486 uint32_t limit = max (_ninputs, _noutputs);
2488 for (uint32_t i = 0; i < limit; ++i) {
2494 IO::reset_max_peak_meters ()
2496 uint32_t limit = max (_ninputs, _noutputs);
2498 for (uint32_t i = 0; i < limit; ++i) {
2499 _max_peak_power[i] = -INFINITY;
2504 IO::setup_peak_meters ()
2506 uint32_t limit = max (_ninputs, _noutputs);
2508 while (_peak_power.size() < limit) {
2509 _peak_power.push_back (0);
2510 _visible_peak_power.push_back (-INFINITY);
2511 _max_peak_power.push_back (-INFINITY);
2516 Update the peak meters.
2518 The meter signal lock is taken to prevent modification of the
2519 Meter signal while updating the meters, taking the meter signal
2520 lock prior to taking the io_lock ensures that all IO will remain
2521 valid while metering.
2526 Glib::Mutex::Lock guard (m_meter_signal_lock);
2533 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2534 uint32_t limit = max (_ninputs, _noutputs);
2536 for (uint32_t n = 0; n < limit; ++n) {
2538 /* XXX we should use atomic exchange here */
2540 /* grab peak since last read */
2542 float new_peak = _peak_power[n];
2545 /* compute new visible value using falloff */
2547 if (new_peak > 0.0f) {
2548 new_peak = coefficient_to_dB (new_peak);
2550 new_peak = -INFINITY;
2553 /* update max peak */
2555 _max_peak_power[n] = max (new_peak, _max_peak_power[n]);
2557 if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
2558 _visible_peak_power[n] = new_peak;
2560 // do falloff, the config value is in dB/sec, we get updated at 100/sec currently (should be a var somewhere)
2561 new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f);
2562 _visible_peak_power[n] = max (new_peak, -INFINITY);
2568 IO::clear_automation ()
2570 Glib::Mutex::Lock lm (automation_lock);
2571 _gain_automation_curve.clear ();
2572 _panner->clear_automation ();
2576 IO::set_gain_automation_state (AutoState state)
2578 bool changed = false;
2581 Glib::Mutex::Lock lm (automation_lock);
2583 if (state != _gain_automation_curve.automation_state()) {
2585 last_automation_snapshot = 0;
2586 _gain_automation_curve.set_automation_state (state);
2588 /* don't reset gain if we're moving to Off or Write mode;
2589 if we're moving to Write, the user may have manually set up gains
2590 that they don't want to lose */
2591 if (state != Off && state != Write) {
2592 set_gain (_gain_automation_curve.eval (_session.transport_frame()), this);
2598 _session.set_dirty ();
2599 gain_automation_state_changed (); /* EMIT SIGNAL */
2604 IO::set_gain_automation_style (AutoStyle style)
2606 bool changed = false;
2609 Glib::Mutex::Lock lm (automation_lock);
2611 if (style != _gain_automation_curve.automation_style()) {
2613 _gain_automation_curve.set_automation_style (style);
2618 gain_automation_style_changed (); /* EMIT SIGNAL */
2622 IO::inc_gain (gain_t factor, void *src)
2624 if (_desired_gain == 0.0f)
2625 set_gain (0.000001f + (0.000001f * factor), src);
2627 set_gain (_desired_gain + (_desired_gain * factor), src);
2631 IO::set_gain (gain_t val, void *src)
2633 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2635 if (val > 1.99526231f) {
2640 Glib::Mutex::Lock dm (declick_lock);
2641 _desired_gain = val;
2644 if (_session.transport_stopped()) {
2645 _effective_gain = val;
2650 _gain_control.Changed (); /* EMIT SIGNAL */
2652 if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
2653 _gain_automation_curve.add (_session.transport_frame(), val);
2656 _session.set_dirty();
2660 IO::start_gain_touch ()
2662 _gain_automation_curve.start_touch ();
2666 IO::end_gain_touch ()
2668 _gain_automation_curve.stop_touch ();
2672 IO::start_pan_touch (uint32_t which)
2674 if (which < _panner->size()) {
2675 (*_panner)[which]->automation().start_touch();
2680 IO::end_pan_touch (uint32_t which)
2682 if (which < _panner->size()) {
2683 (*_panner)[which]->automation().stop_touch();
2689 IO::automation_snapshot (nframes_t now, bool force)
2691 if (gain_automation_recording()) {
2692 _gain_automation_curve.rt_add (now, gain());
2695 _panner->snapshot (now);
2696 last_automation_snapshot = now;
2700 IO::transport_stopped (nframes_t frame)
2702 _gain_automation_curve.reposition_for_rt_add (frame);
2704 if (_gain_automation_curve.automation_state() != Off) {
2706 /* the src=0 condition is a special signal to not propagate
2707 automation gain changes into the mix group when locating.
2710 set_gain (_gain_automation_curve.eval (frame), 0);
2713 _panner->transport_stopped (frame);
2717 IO::build_legal_port_name (bool in)
2719 const int name_size = jack_port_name_size();
2726 maxports = _input_maximum;
2729 maxports = _output_maximum;
2732 if (maxports == 1) {
2733 // allow space for the slash + the suffix
2734 limit = name_size - _session.engine().client_name().length() - (strlen (suffix) + 1);
2735 char buf[name_size+1];
2736 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix);
2737 return string (buf);
2740 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2742 limit = name_size - _session.engine().client_name().length() - (strlen (suffix) + 5);
2744 char buf1[name_size+1];
2745 char buf2[name_size+1];
2747 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix);
2752 port_number = find_input_port_hole (buf1);
2754 port_number = find_output_port_hole (buf1);
2757 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2759 return string (buf2);
2763 IO::find_input_port_hole (const char* base)
2765 /* CALLER MUST HOLD IO LOCK */
2769 if (_inputs.empty()) {
2773 /* we only allow up to 4 characters for the port number
2776 for (n = 1; n < 9999; ++n) {
2777 char buf[jack_port_name_size()];
2778 vector<Port*>::iterator i;
2780 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2782 for (i = _inputs.begin(); i != _inputs.end(); ++i) {
2783 if ((*i)->short_name() == buf) {
2788 if (i == _inputs.end()) {
2796 IO::find_output_port_hole (const char* base)
2798 /* CALLER MUST HOLD IO LOCK */
2802 if (_outputs.empty()) {
2806 /* we only allow up to 4 characters for the port number
2809 for (n = 1; n < 9999; ++n) {
2810 char buf[jack_port_name_size()];
2811 vector<Port*>::iterator i;
2813 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2815 for (i = _outputs.begin(); i != _outputs.end(); ++i) {
2816 if ((*i)->short_name() == buf) {
2821 if (i == _outputs.end()) {
2830 IO::set_active (bool yn)
2833 active_changed(); /* EMIT SIGNAL */
2837 IO::name_from_state (const XMLNode& node)
2839 const XMLProperty* prop;
2841 if ((prop = node.property ("name")) != 0) {
2842 return prop->value();
2849 IO::set_name_in_state (XMLNode& node, const string& new_name)
2851 const XMLProperty* prop;
2853 if ((prop = node.property ("name")) != 0) {
2854 node.add_property ("name", new_name);
2859 IO::cycle_start (nframes_t nframes)
2865 IO::increment_output_offset (nframes_t n)
2867 _output_offset += n;
2871 IO::get_input_buffer (int n, nframes_t nframes)
2875 if (!(port = input (n))) {
2879 return port->get_buffer (nframes);
2883 IO::get_output_buffer (int n, nframes_t nframes)
2887 if (!(port = output (n))) {
2891 return port->get_buffer (nframes) + _output_offset;