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>
49 A bug in OS X's cmath that causes isnan() and isinf() to be
50 "undeclared". the following works around that
53 #if defined(__APPLE__) && defined(__MACH__)
54 extern "C" int isnan (double);
55 extern "C" int isinf (double);
58 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
61 using namespace ARDOUR;
64 nframes_t IO::_automation_interval = 0;
65 const string IO::state_node_name = "IO";
66 bool IO::connecting_legal = false;
67 bool IO::ports_legal = false;
68 bool IO::panners_legal = false;
69 sigc::signal<void> IO::Meter;
70 sigc::signal<int> IO::ConnectingLegal;
71 sigc::signal<int> IO::PortsLegal;
72 sigc::signal<int> IO::PannersLegal;
73 sigc::signal<void,uint32_t> IO::MoreOutputs;
74 sigc::signal<int> IO::PortsCreated;
76 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
78 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
79 others can be imagined.
82 static gain_t direct_control_to_gain (double fract) {
83 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
84 /* this maxes at +6dB */
85 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
88 static double direct_gain_to_control (gain_t gain) {
89 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
90 if (gain == 0) return 0.0;
92 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
95 static bool sort_ports_by_name (Port* a, Port* b)
97 return a->name() < b->name();
101 /** @param default_type The type of port that will be created by ensure_io
102 * and friends if no type is explicitly requested (to avoid breakage).
104 IO::IO (Session& s, string name,
105 int input_min, int input_max, int output_min, int output_max,
106 DataType default_type)
109 _default_type(default_type),
110 _gain_control (X_("gaincontrol"), *this),
111 _gain_automation_curve (0.0, 2.0, 1.0),
112 _input_minimum (input_min),
113 _input_maximum (input_max),
114 _output_minimum (output_min),
115 _output_maximum (output_max)
117 _panner = new Panner (name, _session);
121 _input_connection = 0;
122 _output_connection = 0;
123 pending_state_node = 0;
126 no_panner_reset = false;
129 apply_gain_automation = false;
130 _ignore_gain_on_deliver = false;
132 last_automation_snapshot = 0;
134 _gain_automation_state = Off;
135 _gain_automation_style = Absolute;
138 // IO::Meter is emitted from another thread so the
139 // Meter signal must be protected.
140 Glib::Mutex::Lock guard (m_meter_signal_lock);
141 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
144 _session.add_controllable (&_gain_control);
147 IO::IO (Session& s, const XMLNode& node, DataType dt)
150 _gain_control (X_("gaincontrol"), *this),
151 _gain_automation_curve (0, 0, 0) // all reset in set_state()
156 no_panner_reset = false;
159 _input_connection = 0;
160 _output_connection = 0;
164 apply_gain_automation = false;
165 _ignore_gain_on_deliver = false;
170 // IO::Meter is emitted from another thread so the
171 // Meter signal must be protected.
172 Glib::Mutex::Lock guard (m_meter_signal_lock);
173 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
176 _session.add_controllable (&_gain_control);
181 Glib::Mutex::Lock guard (m_meter_signal_lock);
183 Glib::Mutex::Lock lm (io_lock);
184 vector<Port *>::iterator i;
187 BLOCK_PROCESS_CALLBACK ();
189 for (i = _inputs.begin(); i != _inputs.end(); ++i) {
190 _session.engine().unregister_port (*i);
193 for (i = _outputs.begin(); i != _outputs.end(); ++i) {
194 _session.engine().unregister_port (*i);
198 m_meter_connection.disconnect();
202 IO::silence (nframes_t nframes, nframes_t offset)
204 /* io_lock, not taken: function must be called from Session::process() calltree */
206 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
207 (*i)->silence (nframes, offset);
212 IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
214 nframes_t declick = min ((nframes_t)128, nframes);
217 double fractional_shift;
218 double fractional_pos;
219 gain_t polscale = invert_polarity ? -1.0f : 1.0f;
221 if (nframes == 0) return;
223 fractional_shift = -1.0/declick;
225 if (target < initial) {
226 /* fade out: remove more and more of delta from initial */
227 delta = -(initial - target);
229 /* fade in: add more and more of delta from initial */
230 delta = target - initial;
233 for (uint32_t n = 0; n < nbufs; ++n) {
236 fractional_pos = 1.0;
238 for (nframes_t nx = 0; nx < declick; ++nx) {
239 buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
240 fractional_pos += fractional_shift;
243 /* now ensure the rest of the buffer has the target value
244 applied, if necessary.
247 if (declick != nframes) {
250 if (invert_polarity) {
251 this_target = -target;
253 this_target = target;
256 if (this_target == 0.0) {
257 memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
258 } else if (this_target != 1.0) {
259 for (nframes_t nx = declick; nx < nframes; ++nx) {
260 buffer[nx] *= this_target;
268 IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, nframes_t start, nframes_t end, nframes_t nframes, nframes_t offset)
272 /* io_lock, not taken: function must be called from Session::process() calltree */
274 if (_noutputs == 0) {
278 if (_noutputs == 1) {
280 dst = output(0)->get_buffer (nframes) + offset;
282 for (uint32_t n = 0; n < nbufs; ++n) {
283 if (bufs[n] != dst) {
284 memcpy (dst, bufs[n], sizeof (Sample) * nframes);
288 output(0)->mark_silence (false);
294 vector<Port *>::iterator out;
295 vector<Sample *>::iterator in;
296 Panner::iterator pan;
297 Sample* obufs[_noutputs];
299 /* the terrible silence ... */
301 for (out = _outputs.begin(), o = 0; out != _outputs.end(); ++out, ++o) {
302 obufs[o] = (*out)->get_buffer (nframes) + offset;
303 memset (obufs[o], 0, sizeof (Sample) * nframes);
304 (*out)->mark_silence (false);
309 for (pan = _panner->begin(), n = 0; n < nbufs; ++n, ++pan) {
310 (*pan)->distribute_automated (bufs[n], obufs, start, end, nframes, _session.pan_automation_buffer());
315 IO::pan (vector<Sample*>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset, gain_t gain_coeff)
320 /* io_lock, not taken: function must be called from Session::process() calltree */
322 if (_noutputs == 0) {
326 /* the panner can be empty if there are no inputs to the
327 route, but still outputs
330 if (_panner->bypassed() || _panner->empty()) {
331 deliver_output_no_pan (bufs, nbufs, nframes, offset);
335 if (_noutputs == 1) {
337 dst = output(0)->get_buffer (nframes) + offset;
339 if (gain_coeff == 0.0f) {
341 /* only one output, and gain was zero, so make it silent */
343 memset (dst, 0, sizeof (Sample) * nframes);
345 } else if (gain_coeff == 1.0f){
347 /* mix all buffers into the output */
351 memcpy (dst, bufs[0], sizeof (Sample) * nframes);
353 for (n = 1; n < nbufs; ++n) {
354 Session::mix_buffers_no_gain(dst,bufs[n],nframes);
357 output(0)->mark_silence (false);
361 /* mix all buffers into the output, scaling them all by the gain */
367 for (nframes_t n = 0; n < nframes; ++n) {
368 dst[n] = src[n] * gain_coeff;
371 for (n = 1; n < nbufs; ++n) {
372 Session::mix_buffers_with_gain(dst,bufs[n],nframes,gain_coeff);
375 output(0)->mark_silence (false);
382 vector<Port *>::iterator out;
383 vector<Sample *>::iterator in;
384 Panner::iterator pan;
385 Sample* obufs[_noutputs];
387 /* the terrible silence ... */
389 /* XXX this is wasteful but i see no way to avoid it */
391 for (out = _outputs.begin(), o = 0; out != _outputs.end(); ++out, ++o) {
392 obufs[o] = (*out)->get_buffer (nframes) + offset;
393 memset (obufs[o], 0, sizeof (Sample) * nframes);
394 (*out)->mark_silence (false);
399 for (pan = _panner->begin(), n = 0; n < nbufs; ++n) {
400 Panner::iterator tmp;
405 (*pan)->distribute (bufs[n], obufs, gain_coeff, nframes);
407 if (tmp != _panner->end()) {
414 IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset)
416 /* io_lock, not taken: function must be called from Session::process() calltree */
418 if (_noutputs == 0) {
422 if (_panner->bypassed() || _panner->empty()) {
423 deliver_output_no_pan (bufs, nbufs, nframes, offset);
429 gain_t pangain = _gain;
432 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
442 apply_declick (bufs, nbufs, nframes, _gain, dg, false);
447 /* simple, non-automation panning to outputs */
449 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
450 pan (bufs, nbufs, nframes, offset, pangain * speed_quietning);
452 pan (bufs, nbufs, nframes, offset, pangain);
457 IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset)
459 /* io_lock, not taken: function must be called from Session::process() calltree */
461 if (_noutputs == 0) {
466 gain_t old_gain = _gain;
468 if (apply_gain_automation || _ignore_gain_on_deliver) {
470 /* gain has already been applied by automation code. do nothing here except
479 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
491 vector<Port*>::iterator o;
492 vector<Sample*> outs;
495 /* reduce nbufs to the index of the last input buffer */
499 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
500 actual_gain = _gain * speed_quietning;
505 for (o = _outputs.begin(), i = 0; o != _outputs.end(); ++o, ++i) {
507 dst = (*o)->get_buffer (nframes) + offset;
508 src = bufs[min(nbufs,i)];
511 /* unlikely condition */
512 outs.push_back (dst);
515 if (dg != _gain || actual_gain == 1.0f) {
516 memcpy (dst, src, sizeof (Sample) * nframes);
517 } else if (actual_gain == 0.0f) {
518 memset (dst, 0, sizeof (Sample) * nframes);
520 for (nframes_t x = 0; x < nframes; ++x) {
521 dst[x] = src[x] * actual_gain;
525 (*o)->mark_silence (false);
529 apply_declick (outs, i, nframes, _gain, dg, false);
533 if (apply_gain_automation || _ignore_gain_on_deliver) {
539 IO::collect_input (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nframes_t offset)
541 /* io_lock, not taken: function must be called from Session::process() calltree */
543 vector<Port *>::iterator i;
547 /* we require that bufs.size() >= 1 */
549 for (n = 0, i = _inputs.begin(); n < nbufs; ++i, ++n) {
550 if (i == _inputs.end()) {
554 /* XXX always read the full extent of the port buffer that
555 we need. One day, we may use jack_port_get_buffer_at_offset()
556 or something similar. For now, this simple hack will
559 Hack? Why yes .. we only need to read nframes-worth of
560 data, but the data we want is at `offset' within the
564 last = (*i)->get_buffer (nframes+offset) + offset;
565 // the dest buffer's offset has already been applied
566 memcpy (bufs[n], last, sizeof (Sample) * nframes);
569 /* fill any excess outputs with the last input */
573 // the dest buffer's offset has already been applied
574 memcpy (bufs[n], last, sizeof (Sample) * nframes);
579 memset (bufs[n], 0, sizeof (Sample) * nframes);
586 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
587 nframes_t nframes, nframes_t offset)
589 vector<Sample*>& bufs = _session.get_passthru_buffers ();
590 uint32_t nbufs = n_process_buffers ();
592 collect_input (bufs, nbufs, nframes, offset);
594 for (uint32_t n = 0; n < nbufs; ++n) {
595 _peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
600 IO::drop_input_connection ()
602 _input_connection = 0;
603 input_connection_configuration_connection.disconnect();
604 input_connection_connection_connection.disconnect();
605 _session.set_dirty ();
609 IO::drop_output_connection ()
611 _output_connection = 0;
612 output_connection_configuration_connection.disconnect();
613 output_connection_connection_connection.disconnect();
614 _session.set_dirty ();
618 IO::disconnect_input (Port* our_port, string other_port, void* src)
620 if (other_port.length() == 0 || our_port == 0) {
625 BLOCK_PROCESS_CALLBACK ();
628 Glib::Mutex::Lock lm (io_lock);
630 /* check that our_port is really one of ours */
632 if (find (_inputs.begin(), _inputs.end(), our_port) == _inputs.end()) {
636 /* disconnect it from the source */
638 if (_session.engine().disconnect (other_port, our_port->name())) {
639 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
643 drop_input_connection();
647 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
648 _session.set_dirty ();
654 IO::connect_input (Port* our_port, string other_port, void* src)
656 if (other_port.length() == 0 || our_port == 0) {
661 BLOCK_PROCESS_CALLBACK ();
664 Glib::Mutex::Lock lm (io_lock);
666 /* check that our_port is really one of ours */
668 if (find (_inputs.begin(), _inputs.end(), our_port) == _inputs.end()) {
672 /* connect it to the source */
674 if (_session.engine().connect (other_port, our_port->name())) {
678 drop_input_connection ();
682 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
683 _session.set_dirty ();
688 IO::disconnect_output (Port* our_port, string other_port, void* src)
690 if (other_port.length() == 0 || our_port == 0) {
695 BLOCK_PROCESS_CALLBACK ();
698 Glib::Mutex::Lock lm (io_lock);
700 if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
704 /* disconnect it from the destination */
706 if (_session.engine().disconnect (our_port->name(), other_port)) {
707 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
711 drop_output_connection ();
715 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
716 _session.set_dirty ();
721 IO::connect_output (Port* our_port, string other_port, void* src)
723 if (other_port.length() == 0 || our_port == 0) {
728 BLOCK_PROCESS_CALLBACK ();
732 Glib::Mutex::Lock lm (io_lock);
734 /* check that our_port is really one of ours */
736 if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
740 /* connect it to the destination */
742 if (_session.engine().connect (our_port->name(), other_port)) {
746 drop_output_connection ();
750 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
751 _session.set_dirty ();
756 IO::set_input (Port* other_port, void* src)
758 /* this removes all but one ports, and connects that one port
759 to the specified source.
762 if (_input_minimum > 1 || _input_minimum == 0) {
763 /* sorry, you can't do this */
767 if (other_port == 0) {
768 if (_input_minimum < 0) {
769 return ensure_inputs (0, false, true, src);
775 if (ensure_inputs (1, true, true, src)) {
779 return connect_input (_inputs.front(), other_port->name(), src);
783 IO::remove_output_port (Port* port, void* src)
785 IOChange change (NoChange);
788 BLOCK_PROCESS_CALLBACK ();
792 Glib::Mutex::Lock lm (io_lock);
794 if (_noutputs - 1 == (uint32_t) _output_minimum) {
795 /* sorry, you can't do this */
799 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
801 change = IOChange (change|ConfigurationChanged);
802 if (port->connected()) {
803 change = IOChange (change|ConnectionsChanged);
806 _session.engine().unregister_port (*i);
809 drop_output_connection ();
815 if (change != NoChange) {
816 setup_peak_meters ();
822 if (change != NoChange) {
823 output_changed (change, src); /* EMIT SIGNAL */
824 _session.set_dirty ();
831 /** Add an output port.
833 * @param destination Name of input port to connect new port to.
834 * @param src Source for emitted ConfigurationChanged signal.
835 * @param type Data type of port. Default value (NIL) will use this IO's default type.
838 IO::add_output_port (string destination, void* src, DataType type)
842 if (type == DataType::NIL)
843 type = _default_type;
846 BLOCK_PROCESS_CALLBACK ();
850 Glib::Mutex::Lock lm (io_lock);
852 if (_output_maximum >= 0 && (int) _noutputs == _output_maximum) {
856 /* Create a new output port */
858 string portname = build_legal_port_name (false);
860 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
861 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
865 _outputs.push_back (our_port);
866 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
868 drop_output_connection ();
869 setup_peak_meters ();
873 MoreOutputs (_noutputs); /* EMIT SIGNAL */
876 if (destination.length()) {
877 if (_session.engine().connect (our_port->name(), destination)) {
882 // pan_changed (src); /* EMIT SIGNAL */
883 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
884 _session.set_dirty ();
889 IO::remove_input_port (Port* port, void* src)
891 IOChange change (NoChange);
894 BLOCK_PROCESS_CALLBACK ();
898 Glib::Mutex::Lock lm (io_lock);
900 if (((int)_ninputs - 1) < _input_minimum) {
901 /* sorry, you can't do this */
904 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
907 change = IOChange (change|ConfigurationChanged);
909 if (port->connected()) {
910 change = IOChange (change|ConnectionsChanged);
913 _session.engine().unregister_port (*i);
916 drop_input_connection ();
922 if (change != NoChange) {
923 setup_peak_meters ();
929 if (change != NoChange) {
930 input_changed (change, src);
931 _session.set_dirty ();
939 /** Add an input port.
941 * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
942 * @param destination Name of input port to connect new port to.
943 * @param src Source for emitted ConfigurationChanged signal.
946 IO::add_input_port (string source, void* src, DataType type)
950 if (type == DataType::NIL)
951 type = _default_type;
954 BLOCK_PROCESS_CALLBACK ();
957 Glib::Mutex::Lock lm (io_lock);
959 if (_input_maximum >= 0 && (int) _ninputs == _input_maximum) {
963 /* Create a new input port */
965 string portname = build_legal_port_name (true);
967 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
968 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
972 _inputs.push_back (our_port);
973 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
975 drop_input_connection ();
976 setup_peak_meters ();
980 MoreOutputs (_ninputs); /* EMIT SIGNAL */
983 if (source.length()) {
985 if (_session.engine().connect (source, our_port->name())) {
990 // pan_changed (src); /* EMIT SIGNAL */
991 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
992 _session.set_dirty ();
998 IO::disconnect_inputs (void* src)
1001 BLOCK_PROCESS_CALLBACK ();
1004 Glib::Mutex::Lock lm (io_lock);
1006 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1007 _session.engine().disconnect (*i);
1010 drop_input_connection ();
1013 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1018 IO::disconnect_outputs (void* src)
1021 BLOCK_PROCESS_CALLBACK ();
1024 Glib::Mutex::Lock lm (io_lock);
1026 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1027 _session.engine().disconnect (*i);
1030 drop_output_connection ();
1034 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1035 _session.set_dirty ();
1040 IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
1043 bool changed = false;
1044 bool reduced = false;
1046 /* remove unused ports */
1048 while (_ninputs > n) {
1049 _session.engine().unregister_port (_inputs.back());
1056 /* create any necessary new ports */
1058 while (_ninputs < n) {
1060 /* Create a new input port (of the default type) */
1062 string portname = build_legal_port_name (true);
1066 if ((input_port = _session.engine().register_input_port (_default_type, portname)) == 0) {
1067 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
1072 catch (AudioEngine::PortRegistrationFailure& err) {
1073 setup_peak_meters ();
1079 _inputs.push_back (input_port);
1080 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1086 drop_input_connection ();
1087 setup_peak_meters ();
1089 MoreOutputs (_ninputs); /* EMIT SIGNAL */
1090 _session.set_dirty ();
1094 /* disconnect all existing ports so that we get a fresh start */
1096 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1097 _session.engine().disconnect (*i);
1105 IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
1107 bool in_changed = false;
1108 bool out_changed = false;
1109 bool in_reduced = false;
1110 bool out_reduced = false;
1111 bool need_pan_reset;
1113 if (_input_maximum >= 0) {
1114 nin = min (_input_maximum, (int) nin);
1117 if (_output_maximum >= 0) {
1118 nout = min (_output_maximum, (int) nout);
1121 if (nin == _ninputs && nout == _noutputs && !clear) {
1126 BLOCK_PROCESS_CALLBACK ();
1127 Glib::Mutex::Lock lm (io_lock);
1131 if (_noutputs == nout) {
1132 need_pan_reset = false;
1134 need_pan_reset = true;
1137 /* remove unused ports */
1139 while (_ninputs > nin) {
1140 _session.engine().unregister_port (_inputs.back());
1147 while (_noutputs > nout) {
1148 _session.engine().unregister_port (_outputs.back());
1149 _outputs.pop_back();
1155 /* create any necessary new ports (of the default type) */
1157 while (_ninputs < nin) {
1159 /* Create a new input port */
1161 string portname = build_legal_port_name (true);
1164 if ((port = _session.engine().register_input_port (_default_type, portname)) == 0) {
1165 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
1170 catch (AudioEngine::PortRegistrationFailure& err) {
1171 setup_peak_meters ();
1177 _inputs.push_back (port);
1182 /* create any necessary new ports */
1184 while (_noutputs < nout) {
1186 string portname = build_legal_port_name (false);
1189 if ((port = _session.engine().register_output_port (_default_type, portname)) == 0) {
1190 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1195 catch (AudioEngine::PortRegistrationFailure& err) {
1196 setup_peak_meters ();
1202 _outputs.push_back (port);
1209 /* disconnect all existing ports so that we get a fresh start */
1211 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1212 _session.engine().disconnect (*i);
1215 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1216 _session.engine().disconnect (*i);
1220 if (in_changed || out_changed) {
1221 setup_peak_meters ();
1227 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
1228 drop_output_connection ();
1229 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1233 sort (_inputs.begin(), _inputs.end(), sort_ports_by_name);
1234 drop_input_connection ();
1235 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1238 if (in_changed || out_changed) {
1239 MoreOutputs (max (_noutputs, _ninputs)); /* EMIT SIGNAL */
1240 _session.set_dirty ();
1247 IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
1249 bool changed = false;
1251 if (_input_maximum >= 0) {
1252 n = min (_input_maximum, (int) n);
1254 if (n == _ninputs && !clear) {
1260 BLOCK_PROCESS_CALLBACK ();
1261 Glib::Mutex::Lock im (io_lock);
1262 changed = ensure_inputs_locked (n, clear, src);
1264 changed = ensure_inputs_locked (n, clear, src);
1268 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1269 _session.set_dirty ();
1276 IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
1279 bool changed = false;
1280 bool reduced = false;
1281 bool need_pan_reset;
1283 if (_noutputs == n) {
1284 need_pan_reset = false;
1286 need_pan_reset = true;
1289 /* remove unused ports */
1291 while (_noutputs > n) {
1293 _session.engine().unregister_port (_outputs.back());
1294 _outputs.pop_back();
1300 /* create any necessary new ports */
1302 while (_noutputs < n) {
1304 /* Create a new output port */
1306 string portname = build_legal_port_name (false);
1308 if ((output_port = _session.engine().register_output_port (_default_type, portname)) == 0) {
1309 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1313 _outputs.push_back (output_port);
1314 sort (_outputs.begin(), _outputs.end(), sort_ports_by_name);
1317 setup_peak_meters ();
1319 if (need_pan_reset) {
1325 drop_output_connection ();
1326 MoreOutputs (_noutputs); /* EMIT SIGNAL */
1327 _session.set_dirty ();
1331 /* disconnect all existing ports so that we get a fresh start */
1333 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1334 _session.engine().disconnect (*i);
1342 IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src)
1344 bool changed = false;
1346 if (_output_maximum >= 0) {
1347 n = min (_output_maximum, (int) n);
1348 if (n == _noutputs && !clear) {
1353 /* XXX caller should hold io_lock, but generally doesn't */
1356 BLOCK_PROCESS_CALLBACK ();
1357 Glib::Mutex::Lock im (io_lock);
1358 changed = ensure_outputs_locked (n, clear, src);
1360 changed = ensure_outputs_locked (n, clear, src);
1364 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1371 IO::effective_gain () const
1373 if (gain_automation_playback()) {
1374 return _effective_gain;
1376 return _desired_gain;
1383 if (panners_legal) {
1384 if (!no_panner_reset) {
1385 _panner->reset (_noutputs, pans_required());
1388 panner_legal_c.disconnect ();
1389 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1394 IO::panners_became_legal ()
1396 _panner->reset (_noutputs, pans_required());
1397 _panner->load (); // automation
1398 panner_legal_c.disconnect ();
1403 IO::defer_pan_reset ()
1405 no_panner_reset = true;
1409 IO::allow_pan_reset ()
1411 no_panner_reset = false;
1417 IO::get_state (void)
1419 return state (true);
1423 IO::state (bool full_state)
1425 XMLNode* node = new XMLNode (state_node_name);
1428 bool need_ins = true;
1429 bool need_outs = true;
1430 LocaleGuard lg (X_("POSIX"));
1431 Glib::Mutex::Lock lm (io_lock);
1433 node->add_property("name", _name);
1434 id().print (buf, sizeof (buf));
1435 node->add_property("id", buf);
1436 node->add_property("active", _active? "yes" : "no");
1440 if (_input_connection) {
1441 node->add_property ("input-connection", _input_connection->name());
1445 if (_output_connection) {
1446 node->add_property ("output-connection", _output_connection->name());
1451 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1453 const char **connections = (*i)->get_connections();
1455 if (connections && connections[0]) {
1458 for (int n = 0; connections && connections[n]; ++n) {
1463 /* if its a connection to our own port,
1464 return only the port name, not the
1465 whole thing. this allows connections
1466 to be re-established even when our
1467 client name is different.
1470 str += _session.engine().make_port_name_relative (connections[n]);
1482 node->add_property ("inputs", str);
1488 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1490 const char **connections = (*i)->get_connections();
1492 if (connections && connections[0]) {
1496 for (int n = 0; connections[n]; ++n) {
1501 str += _session.engine().make_port_name_relative (connections[n]);
1513 node->add_property ("outputs", str);
1516 node->add_child_nocopy (_panner->state (full_state));
1517 node->add_child_nocopy (_gain_control.get_state ());
1519 snprintf (buf, sizeof(buf), "%2.12f", gain());
1520 node->add_property ("gain", buf);
1522 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d",
1528 node->add_property ("iolimits", buf);
1534 XMLNode* autonode = new XMLNode (X_("Automation"));
1535 autonode->add_child_nocopy (get_automation_state());
1536 node->add_child_nocopy (*autonode);
1538 snprintf (buf, sizeof (buf), "0x%x", (int) _gain_automation_curve.automation_state());
1540 /* never store anything except Off for automation state in a template */
1541 snprintf (buf, sizeof (buf), "0x%x", ARDOUR::Off);
1548 IO::set_state (const XMLNode& node)
1550 const XMLProperty* prop;
1551 XMLNodeConstIterator iter;
1552 LocaleGuard lg (X_("POSIX"));
1554 /* force use of non-localized representation of decimal point,
1555 since we use it a lot in XML files and so forth.
1558 if (node.name() != state_node_name) {
1559 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1563 if ((prop = node.property ("name")) != 0) {
1564 _name = prop->value();
1565 /* used to set panner name with this, but no more */
1568 if ((prop = node.property ("id")) != 0) {
1569 _id = prop->value ();
1572 if ((prop = node.property ("iolimits")) != 0) {
1573 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1580 if ((prop = node.property ("gain")) != 0) {
1581 set_gain (atof (prop->value().c_str()), this);
1582 _gain = _desired_gain;
1585 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1586 /* old school automation handling */
1589 if ((prop = node.property (X_("active"))) != 0) {
1590 set_active (prop->value() == "yes");
1593 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1595 if ((*iter)->name() == "Panner") {
1597 _panner = new Panner (_name, _session);
1599 _panner->set_state (**iter);
1602 if ((*iter)->name() == X_("Automation")) {
1604 set_automation_state (*(*iter)->children().front());
1607 if ((*iter)->name() == X_("controllable")) {
1608 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1609 _gain_control.set_state (**iter);
1616 if (create_ports (node)) {
1622 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1625 if (panners_legal) {
1628 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1631 if (connecting_legal) {
1633 if (make_connections (node)) {
1639 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1642 if (!ports_legal || !connecting_legal) {
1643 pending_state_node = new XMLNode (node);
1646 last_automation_snapshot = 0;
1652 IO::set_automation_state (const XMLNode& node)
1654 return _gain_automation_curve.set_state (node);
1658 IO::get_automation_state ()
1660 return (_gain_automation_curve.get_state ());
1664 IO::load_automation (string path)
1669 uint32_t linecnt = 0;
1671 LocaleGuard lg (X_("POSIX"));
1673 fullpath = Glib::build_filename(_session.automation_dir(), path);
1675 in.open (fullpath.c_str());
1678 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1680 in.open (fullpath.c_str());
1683 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1688 clear_automation ();
1690 while (in.getline (line, sizeof(line), '\n')) {
1692 jack_nframes_t when;
1695 if (++linecnt == 1) {
1696 if (memcmp (line, "version", 7) == 0) {
1697 if (sscanf (line, "version %f", &version) != 1) {
1698 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1702 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1709 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1710 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1716 _gain_automation_curve.fast_simple_add (when, value);
1726 /* older (pre-1.0) versions of ardour used this */
1730 warning << _("dubious automation event found (and ignored)") << endmsg;
1738 IO::connecting_became_legal ()
1742 if (pending_state_node == 0) {
1743 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1748 connection_legal_c.disconnect ();
1750 ret = make_connections (*pending_state_node);
1753 delete pending_state_node;
1754 pending_state_node = 0;
1760 IO::ports_became_legal ()
1764 if (pending_state_node == 0) {
1765 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1770 port_legal_c.disconnect ();
1772 ret = create_ports (*pending_state_node);
1774 if (connecting_legal) {
1775 delete pending_state_node;
1776 pending_state_node = 0;
1783 IO::find_possible_connection(const string &desired_name, const string &default_name, const string &connection_type_name)
1785 static const string digits = "0123456789";
1787 Connection* c = _session.connection_by_name (desired_name);
1790 int connection_number, mask;
1791 string possible_name;
1792 bool stereo = false;
1793 string::size_type last_non_digit_pos;
1795 error << string_compose(_("Unknown connection \"%1\" listed for %2 of %3"), desired_name, connection_type_name, _name)
1798 // find numeric suffix of desired name
1799 connection_number = 0;
1801 last_non_digit_pos = desired_name.find_last_not_of(digits);
1803 if (last_non_digit_pos != string::npos) {
1805 s << desired_name.substr(last_non_digit_pos);
1806 s >> connection_number;
1809 // see if it's a stereo connection e.g. "in 3+4"
1811 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1812 int left_connection_number = 0;
1813 string::size_type left_last_non_digit_pos;
1815 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1817 if (left_last_non_digit_pos != string::npos) {
1819 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1820 s >> left_connection_number;
1822 if (left_connection_number > 0 && left_connection_number + 1 == connection_number) {
1823 connection_number--;
1830 if (connection_number)
1831 connection_number--;
1833 // find highest set bit
1835 while ((mask <= connection_number) && (mask <<= 1));
1837 // "wrap" connection number into largest possible power of 2
1842 if (connection_number & mask) {
1843 connection_number &= ~mask;
1846 s << default_name << " " << connection_number + 1;
1849 s << "+" << connection_number + 2;
1852 possible_name = s.str();
1854 if ((c = _session.connection_by_name (possible_name)) != 0) {
1861 info << string_compose (_("Connection %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1864 error << string_compose(_("No %1 connections available as a replacement"), connection_type_name)
1875 IO::create_ports (const XMLNode& node)
1877 const XMLProperty* prop;
1879 int num_outputs = 0;
1881 if ((prop = node.property ("input-connection")) != 0) {
1883 Connection* c = find_possible_connection(prop->value(), _("in"), _("input"));
1889 num_inputs = c->nports();
1891 } else if ((prop = node.property ("inputs")) != 0) {
1893 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1896 if ((prop = node.property ("output-connection")) != 0) {
1897 Connection* c = find_possible_connection(prop->value(), _("out"), _("output"));
1903 num_outputs = c->nports ();
1905 } else if ((prop = node.property ("outputs")) != 0) {
1906 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1909 no_panner_reset = true;
1911 if (ensure_io (num_inputs, num_outputs, true, this)) {
1912 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1916 no_panner_reset = false;
1918 set_deferred_state ();
1926 IO::make_connections (const XMLNode& node)
1928 const XMLProperty* prop;
1930 if ((prop = node.property ("input-connection")) != 0) {
1931 Connection* c = find_possible_connection (prop->value(), _("in"), _("input"));
1937 use_input_connection (*c, this);
1939 } else if ((prop = node.property ("inputs")) != 0) {
1940 if (set_inputs (prop->value())) {
1941 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1946 if ((prop = node.property ("output-connection")) != 0) {
1947 Connection* c = find_possible_connection (prop->value(), _("out"), _("output"));
1953 use_output_connection (*c, this);
1955 } else if ((prop = node.property ("outputs")) != 0) {
1956 if (set_outputs (prop->value())) {
1957 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1966 IO::set_inputs (const string& str)
1968 vector<string> ports;
1973 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1977 if (ensure_inputs (nports, true, true, this)) {
1981 string::size_type start, end, ostart;
1988 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1991 if ((end = str.find_first_of ('}', start)) == string::npos) {
1992 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1996 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1997 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
2003 for (int x = 0; x < n; ++x) {
2004 connect_input (input (i), ports[x], this);
2016 IO::set_outputs (const string& str)
2018 vector<string> ports;
2023 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
2027 if (ensure_outputs (nports, true, true, this)) {
2031 string::size_type start, end, ostart;
2038 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
2041 if ((end = str.find_first_of ('}', start)) == string::npos) {
2042 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
2046 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
2047 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
2053 for (int x = 0; x < n; ++x) {
2054 connect_output (output (i), ports[x], this);
2066 IO::parse_io_string (const string& str, vector<string>& ports)
2068 string::size_type pos, opos;
2070 if (str.length() == 0) {
2079 while ((pos = str.find_first_of (',', opos)) != string::npos) {
2080 ports.push_back (str.substr (opos, pos - opos));
2084 if (opos < str.length()) {
2085 ports.push_back (str.substr(opos));
2088 return ports.size();
2092 IO::parse_gain_string (const string& str, vector<string>& ports)
2094 string::size_type pos, opos;
2100 while ((pos = str.find_first_of (',', opos)) != string::npos) {
2101 ports.push_back (str.substr (opos, pos - opos));
2105 if (opos < str.length()) {
2106 ports.push_back (str.substr(opos));
2109 return ports.size();
2113 IO::set_name (string requested_name, void* src)
2115 if (requested_name == _name) {
2121 if ( (rt = dynamic_cast<Route *>(this))) {
2122 name = Route::ensure_track_or_route_name(requested_name, _session);
2124 name = requested_name;
2128 /* replace all colons in the name. i wish we didn't have to do this */
2130 if (replace_all (name, ":", "-")) {
2131 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
2134 for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2135 string current_name = (*i)->short_name();
2136 current_name.replace (current_name.find (_name), _name.length(), name);
2137 (*i)->set_name (current_name);
2140 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2141 string current_name = (*i)->short_name();
2142 current_name.replace (current_name.find (_name), _name.length(), name);
2143 (*i)->set_name (current_name);
2147 name_changed (src); /* EMIT SIGNAL */
2153 IO::set_input_minimum (int n)
2159 IO::set_input_maximum (int n)
2165 IO::set_output_minimum (int n)
2167 _output_minimum = n;
2171 IO::set_output_maximum (int n)
2173 _output_maximum = n;
2177 IO::set_port_latency (nframes_t nframes)
2179 Glib::Mutex::Lock lm (io_lock);
2181 for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2182 (*i)->set_latency (nframes);
2187 IO::output_latency () const
2189 nframes_t max_latency;
2194 /* io lock not taken - must be protected by other means */
2196 for (vector<Port *>::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2197 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2198 max_latency = latency;
2206 IO::input_latency () const
2208 nframes_t max_latency;
2213 /* io lock not taken - must be protected by other means */
2215 for (vector<Port *>::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2216 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2217 max_latency = latency;
2225 IO::use_input_connection (Connection& c, void* src)
2230 BLOCK_PROCESS_CALLBACK ();
2231 Glib::Mutex::Lock lm2 (io_lock);
2235 drop_input_connection ();
2237 if (ensure_inputs (limit, false, false, src)) {
2241 /* first pass: check the current state to see what's correctly
2242 connected, and drop anything that we don't want.
2245 for (uint32_t n = 0; n < limit; ++n) {
2246 const Connection::PortList& pl = c.port_connections (n);
2248 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2250 if (!_inputs[n]->connected_to ((*i))) {
2252 /* clear any existing connections */
2254 _session.engine().disconnect (_inputs[n]);
2256 } else if (_inputs[n]->connected() > 1) {
2258 /* OK, it is connected to the port we want,
2259 but its also connected to other ports.
2260 Change that situation.
2263 /* XXX could be optimized to not drop
2267 _session.engine().disconnect (_inputs[n]);
2273 /* second pass: connect all requested ports where necessary */
2275 for (uint32_t n = 0; n < limit; ++n) {
2276 const Connection::PortList& pl = c.port_connections (n);
2278 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2280 if (!_inputs[n]->connected_to ((*i))) {
2282 if (_session.engine().connect (*i, _inputs[n]->name())) {
2290 _input_connection = &c;
2292 input_connection_configuration_connection = c.ConfigurationChanged.connect
2293 (mem_fun (*this, &IO::input_connection_configuration_changed));
2294 input_connection_connection_connection = c.ConnectionsChanged.connect
2295 (mem_fun (*this, &IO::input_connection_connection_changed));
2298 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2303 IO::use_output_connection (Connection& c, void* src)
2308 BLOCK_PROCESS_CALLBACK ();
2309 Glib::Mutex::Lock lm2 (io_lock);
2313 drop_output_connection ();
2315 if (ensure_outputs (limit, false, false, src)) {
2319 /* first pass: check the current state to see what's correctly
2320 connected, and drop anything that we don't want.
2323 for (uint32_t n = 0; n < limit; ++n) {
2325 const Connection::PortList& pl = c.port_connections (n);
2327 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2329 if (!_outputs[n]->connected_to ((*i))) {
2331 /* clear any existing connections */
2333 _session.engine().disconnect (_outputs[n]);
2335 } else if (_outputs[n]->connected() > 1) {
2337 /* OK, it is connected to the port we want,
2338 but its also connected to other ports.
2339 Change that situation.
2342 /* XXX could be optimized to not drop
2346 _session.engine().disconnect (_outputs[n]);
2351 /* second pass: connect all requested ports where necessary */
2353 for (uint32_t n = 0; n < limit; ++n) {
2355 const Connection::PortList& pl = c.port_connections (n);
2357 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2359 if (!_outputs[n]->connected_to ((*i))) {
2361 if (_session.engine().connect (_outputs[n]->name(), *i)) {
2368 _output_connection = &c;
2370 output_connection_configuration_connection = c.ConfigurationChanged.connect
2371 (mem_fun (*this, &IO::output_connection_configuration_changed));
2372 output_connection_connection_connection = c.ConnectionsChanged.connect
2373 (mem_fun (*this, &IO::output_connection_connection_changed));
2376 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2382 IO::disable_connecting ()
2384 connecting_legal = false;
2389 IO::enable_connecting ()
2391 connecting_legal = true;
2392 return ConnectingLegal ();
2396 IO::disable_ports ()
2398 ports_legal = false;
2406 return PortsLegal ();
2410 IO::disable_panners (void)
2412 panners_legal = false;
2417 IO::reset_panners ()
2419 panners_legal = true;
2420 return PannersLegal ();
2424 IO::input_connection_connection_changed (int ignored)
2426 use_input_connection (*_input_connection, this);
2430 IO::input_connection_configuration_changed ()
2432 use_input_connection (*_input_connection, this);
2436 IO::output_connection_connection_changed (int ignored)
2438 use_output_connection (*_output_connection, this);
2442 IO::output_connection_configuration_changed ()
2444 use_output_connection (*_output_connection, this);
2448 IO::GainControllable::set_value (float val)
2450 io.set_gain (direct_control_to_gain (val), this);
2454 IO::GainControllable::get_value (void) const
2456 return direct_gain_to_control (io.effective_gain());
2460 IO::reset_peak_meters ()
2462 uint32_t limit = max (_ninputs, _noutputs);
2464 for (uint32_t i = 0; i < limit; ++i) {
2470 IO::reset_max_peak_meters ()
2472 uint32_t limit = max (_ninputs, _noutputs);
2474 for (uint32_t i = 0; i < limit; ++i) {
2475 _max_peak_power[i] = -INFINITY;
2480 IO::setup_peak_meters ()
2482 uint32_t limit = max (_ninputs, _noutputs);
2484 while (_peak_power.size() < limit) {
2485 _peak_power.push_back (0);
2486 _visible_peak_power.push_back (-INFINITY);
2487 _max_peak_power.push_back (-INFINITY);
2492 Update the peak meters.
2494 The meter signal lock is taken to prevent modification of the
2495 Meter signal while updating the meters, taking the meter signal
2496 lock prior to taking the io_lock ensures that all IO will remain
2497 valid while metering.
2502 Glib::Mutex::Lock guard (m_meter_signal_lock);
2509 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2510 uint32_t limit = max (_ninputs, _noutputs);
2512 for (uint32_t n = 0; n < limit; ++n) {
2514 /* XXX we should use atomic exchange here */
2516 /* grab peak since last read */
2518 float new_peak = _peak_power[n];
2521 /* compute new visible value using falloff */
2523 if (new_peak > 0.0f) {
2524 new_peak = coefficient_to_dB (new_peak);
2526 new_peak = -INFINITY;
2529 /* update max peak */
2531 _max_peak_power[n] = max (new_peak, _max_peak_power[n]);
2533 if (Config->get_meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
2534 _visible_peak_power[n] = new_peak;
2536 // do falloff, the config value is in dB/sec, we get updated at 100/sec currently (should be a var somewhere)
2537 new_peak = _visible_peak_power[n] - (Config->get_meter_falloff() * 0.01f);
2538 _visible_peak_power[n] = max (new_peak, -INFINITY);
2544 IO::clear_automation ()
2546 Glib::Mutex::Lock lm (automation_lock);
2547 _gain_automation_curve.clear ();
2548 _panner->clear_automation ();
2552 IO::set_gain_automation_state (AutoState state)
2554 bool changed = false;
2557 Glib::Mutex::Lock lm (automation_lock);
2559 if (state != _gain_automation_curve.automation_state()) {
2561 last_automation_snapshot = 0;
2562 _gain_automation_curve.set_automation_state (state);
2565 set_gain (_gain_automation_curve.eval (_session.transport_frame()), this);
2571 _session.set_dirty ();
2572 gain_automation_state_changed (); /* EMIT SIGNAL */
2577 IO::set_gain_automation_style (AutoStyle style)
2579 bool changed = false;
2582 Glib::Mutex::Lock lm (automation_lock);
2584 if (style != _gain_automation_curve.automation_style()) {
2586 _gain_automation_curve.set_automation_style (style);
2591 gain_automation_style_changed (); /* EMIT SIGNAL */
2595 IO::inc_gain (gain_t factor, void *src)
2597 if (_desired_gain == 0.0f)
2598 set_gain (0.000001f + (0.000001f * factor), src);
2600 set_gain (_desired_gain + (_desired_gain * factor), src);
2604 IO::set_gain (gain_t val, void *src)
2606 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2608 if (val > 1.99526231f) {
2613 Glib::Mutex::Lock dm (declick_lock);
2614 _desired_gain = val;
2617 if (_session.transport_stopped()) {
2618 _effective_gain = val;
2623 _gain_control.Changed (); /* EMIT SIGNAL */
2625 if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
2626 _gain_automation_curve.add (_session.transport_frame(), val);
2629 _session.set_dirty();
2633 IO::start_gain_touch ()
2635 _gain_automation_curve.start_touch ();
2639 IO::end_gain_touch ()
2641 _gain_automation_curve.stop_touch ();
2645 IO::start_pan_touch (uint32_t which)
2647 if (which < _panner->size()) {
2648 (*_panner)[which]->automation().start_touch();
2653 IO::end_pan_touch (uint32_t which)
2655 if (which < _panner->size()) {
2656 (*_panner)[which]->automation().stop_touch();
2662 IO::automation_snapshot (nframes_t now, bool force)
2664 if (gain_automation_recording()) {
2665 _gain_automation_curve.rt_add (now, gain());
2668 _panner->snapshot (now);
2669 last_automation_snapshot = now;
2673 IO::transport_stopped (nframes_t frame)
2675 _gain_automation_curve.reposition_for_rt_add (frame);
2677 if (_gain_automation_curve.automation_state() != Off) {
2679 /* the src=0 condition is a special signal to not propagate
2680 automation gain changes into the mix group when locating.
2683 set_gain (_gain_automation_curve.eval (frame), 0);
2686 _panner->transport_stopped (frame);
2690 IO::build_legal_port_name (bool in)
2692 const int name_size = jack_port_name_size();
2699 maxports = _input_maximum;
2702 maxports = _output_maximum;
2705 if (maxports == 1) {
2706 // allow space for the slash + the suffix
2707 limit = name_size - _session.engine().client_name().length() - (strlen (suffix) + 1);
2708 char buf[name_size+1];
2709 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix);
2710 return string (buf);
2713 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2715 limit = name_size - _session.engine().client_name().length() - (strlen (suffix) + 5);
2717 char buf1[name_size+1];
2718 char buf2[name_size+1];
2720 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix);
2725 port_number = find_input_port_hole (buf1);
2727 port_number = find_output_port_hole (buf1);
2730 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2732 return string (buf2);
2736 IO::find_input_port_hole (const char* base)
2738 /* CALLER MUST HOLD IO LOCK */
2742 if (_inputs.empty()) {
2746 /* we only allow up to 4 characters for the port number
2749 for (n = 1; n < 9999; ++n) {
2750 char buf[jack_port_name_size()];
2751 vector<Port*>::iterator i;
2753 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2755 for (i = _inputs.begin(); i != _inputs.end(); ++i) {
2756 if ((*i)->short_name() == buf) {
2761 if (i == _inputs.end()) {
2769 IO::find_output_port_hole (const char* base)
2771 /* CALLER MUST HOLD IO LOCK */
2775 if (_outputs.empty()) {
2779 /* we only allow up to 4 characters for the port number
2782 for (n = 1; n < 9999; ++n) {
2783 char buf[jack_port_name_size()];
2784 vector<Port*>::iterator i;
2786 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2788 for (i = _outputs.begin(); i != _outputs.end(); ++i) {
2789 if ((*i)->short_name() == buf) {
2794 if (i == _outputs.end()) {
2803 IO::set_active (bool yn)
2806 active_changed(); /* EMIT SIGNAL */
2810 IO::name_from_state (const XMLNode& node)
2812 const XMLProperty* prop;
2814 if ((prop = node.property ("name")) != 0) {
2815 return prop->value();
2822 IO::set_name_in_state (XMLNode& node, const string& new_name)
2824 const XMLProperty* prop;
2826 if ((prop = node.property ("name")) != 0) {
2827 node.add_property ("name", new_name);