2 Copyright (C) 2000-2006 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.
24 #include <sigc++/bind.h>
26 #include <glibmm/thread.h>
28 #include <pbd/xml++.h>
30 #include <ardour/audioengine.h>
31 #include <ardour/io.h>
32 #include <ardour/port.h>
33 #include <ardour/audio_port.h>
34 #include <ardour/midi_port.h>
35 #include <ardour/connection.h>
36 #include <ardour/session.h>
37 #include <ardour/cycle_timer.h>
38 #include <ardour/panner.h>
39 #include <ardour/dB.h>
46 A bug in OS X's cmath that causes isnan() and isinf() to be
47 "undeclared". the following works around that
50 #if defined(__APPLE__) && defined(__MACH__)
51 extern "C" int isnan (double);
52 extern "C" int isinf (double);
57 using namespace ARDOUR;
61 static float current_automation_version_number = 1.0;
63 jack_nframes_t IO::_automation_interval = 0;
64 const string IO::state_node_name = "IO";
65 bool IO::connecting_legal = false;
66 bool IO::ports_legal = false;
67 bool IO::panners_legal = false;
68 sigc::signal<void> IO::Meter;
69 sigc::signal<int> IO::ConnectingLegal;
70 sigc::signal<int> IO::PortsLegal;
71 sigc::signal<int> IO::PannersLegal;
72 sigc::signal<void,ChanCount> IO::MoreOutputs;
73 sigc::signal<int> IO::PortsCreated;
75 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
77 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
78 others can be imagined.
81 static gain_t direct_control_to_gain (double fract) {
82 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
83 /* this maxes at +6dB */
84 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
87 static double direct_gain_to_control (gain_t gain) {
88 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
89 if (gain == 0) return 0.0;
91 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();
102 /** @param default_type The type of port that will be created by ensure_io
103 * and friends if no type is explicitly requested (to avoid breakage).
105 IO::IO (Session& s, string name,
106 int input_min, int input_max, int output_min, int output_max,
107 DataType default_type)
110 _default_type(default_type),
111 _gain_control (*this),
112 _gain_automation_curve (0.0, 2.0, 1.0),
113 _input_minimum (_default_type, input_min),
114 _input_maximum (_default_type, input_max),
115 _output_minimum (_default_type, output_min),
116 _output_maximum (_default_type, output_max)
118 _panner = new Panner (name, _session);
121 _input_connection = 0;
122 _output_connection = 0;
123 pending_state_node = 0;
124 no_panner_reset = false;
127 apply_gain_automation = false;
129 last_automation_snapshot = 0;
131 _gain_automation_state = Off;
132 _gain_automation_style = Absolute;
135 // IO::Meter is emitted from another thread so the
136 // Meter signal must be protected.
137 Glib::Mutex::Lock guard (m_meter_signal_lock);
138 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
145 Glib::Mutex::Lock guard (m_meter_signal_lock);
146 Glib::Mutex::Lock lm (io_lock);
148 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
149 _session.engine().unregister_port (*i);
152 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
153 _session.engine().unregister_port (*i);
156 m_meter_connection.disconnect();
160 IO::silence (jack_nframes_t nframes, jack_nframes_t offset)
162 /* io_lock, not taken: function must be called from Session::process() calltree */
164 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
165 (*i)->silence (nframes, offset);
170 IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity)
172 jack_nframes_t declick = min ((jack_nframes_t)128, nframes);
175 double fractional_shift;
176 double fractional_pos;
177 gain_t polscale = invert_polarity ? -1.0f : 1.0f;
179 if (nframes == 0) return;
181 fractional_shift = -1.0/declick;
183 if (target < initial) {
184 /* fade out: remove more and more of delta from initial */
185 delta = -(initial - target);
187 /* fade in: add more and more of delta from initial */
188 delta = target - initial;
191 for (uint32_t n = 0; n < nbufs; ++n) {
194 fractional_pos = 1.0;
196 for (jack_nframes_t nx = 0; nx < declick; ++nx) {
197 buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
198 fractional_pos += fractional_shift;
201 /* now ensure the rest of the buffer has the target value
202 applied, if necessary.
205 if (declick != nframes) {
207 if (invert_polarity) {
212 memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
213 } else if (target != 1.0) {
214 for (jack_nframes_t nx = declick; nx < nframes; ++nx) {
215 buffer[nx] *= target;
223 IO::pan_automated (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t start, jack_nframes_t end, jack_nframes_t nframes, jack_nframes_t offset)
227 /* io_lock, not taken: function must be called from Session::process() calltree */
229 if (n_outputs().get(DataType::AUDIO) == 0) {
233 if (n_outputs().get(DataType::AUDIO) == 1) {
235 dst = audio_output(0)->get_audio_buffer().data (nframes, offset);
237 for (uint32_t n = 0; n < nbufs; ++n) {
238 if (bufs[n] != dst) {
239 memcpy (dst, bufs[n], sizeof (Sample) * nframes);
243 output(0)->mark_silence (false);
249 vector<Sample *>::iterator in;
250 Panner::iterator pan;
251 Sample* obufs[n_outputs().get(DataType::AUDIO)];
253 /* the terrible silence ... */
254 for (PortSet::audio_iterator out = _outputs.audio_begin(); out != _outputs.audio_end(); ++out, ++o) {
255 (*out)->silence(nframes, offset);
256 obufs[o] = (*out)->get_audio_buffer().data(nframes, offset);
261 for (pan = _panner->begin(), n = 0; n < nbufs; ++n, ++pan) {
262 (*pan)->distribute_automated (bufs[n], obufs, start, end, nframes, _session.pan_automation_buffer());
267 IO::pan (vector<Sample*>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff)
272 /* io_lock, not taken: function must be called from Session::process() calltree */
274 if (n_outputs().get(DataType::AUDIO) == 0) {
278 /* the panner can be empty if there are no inputs to the
279 route, but still outputs
282 if (_panner->bypassed() || _panner->empty()) {
283 deliver_output_no_pan (bufs, nbufs, nframes, offset);
287 if (n_outputs().get(DataType::AUDIO) == 1) {
289 dst = audio_output(0)->get_audio_buffer().data(nframes, offset);
291 if (gain_coeff == 0.0f) {
293 /* only one output, and gain was zero, so make it silent */
295 memset (dst, 0, sizeof (Sample) * nframes);
297 } else if (gain_coeff == 1.0f){
299 /* mix all buffers into the output */
303 memcpy (dst, bufs[0], sizeof (Sample) * nframes);
305 for (n = 1; n < nbufs; ++n) {
308 for (jack_nframes_t n = 0; n < nframes; ++n) {
313 audio_output(0)->mark_silence (false);
317 /* mix all buffers into the output, scaling them all by the gain */
323 for (jack_nframes_t n = 0; n < nframes; ++n) {
324 dst[n] = src[n] * gain_coeff;
327 for (n = 1; n < nbufs; ++n) {
330 for (jack_nframes_t n = 0; n < nframes; ++n) {
331 dst[n] += src[n] * gain_coeff;
335 audio_output(0)->mark_silence (false);
342 vector<Sample *>::iterator in;
343 Panner::iterator pan;
344 Sample* obufs[n_outputs().get(DataType::AUDIO)];
346 /* the terrible silence ... */
348 /* XXX this is wasteful but i see no way to avoid it */
350 for (PortSet::audio_iterator out = _outputs.audio_begin(); out != _outputs.audio_end(); ++out, ++o) {
351 obufs[o] = (*out)->get_audio_buffer().data (nframes, offset);
352 memset (obufs[o], 0, sizeof (Sample) * nframes);
353 (*out)->mark_silence (false);
358 for (pan = _panner->begin(), n = 0; n < nbufs; ++n) {
359 Panner::iterator tmp;
364 (*pan)->distribute (bufs[n], obufs, gain_coeff, nframes);
366 if (tmp != _panner->end()) {
373 IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
375 /* io_lock, not taken: function must be called from Session::process() calltree */
377 if (n_outputs().get(DataType::AUDIO) == 0) {
381 if (_panner->bypassed() || _panner->empty()) {
382 deliver_output_no_pan (bufs, nbufs, nframes, offset);
388 gain_t pangain = _gain;
391 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
401 apply_declick (bufs, nbufs, nframes, _gain, dg, false);
406 /* simple, non-automation panning to outputs */
408 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
409 pan (bufs, nbufs, nframes, offset, pangain * speed_quietning);
411 pan (bufs, nbufs, nframes, offset, pangain);
416 IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
418 /* io_lock, not taken: function must be called from Session::process() calltree */
420 if (n_outputs().get(DataType::AUDIO) == 0) {
425 gain_t old_gain = _gain;
427 if (apply_gain_automation) {
429 /* gain has already been applied by automation code. do nothing here except
438 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
450 vector<Sample*> outs;
454 /* unlikely condition */
456 for (PortSet::audio_iterator o = _outputs.audio_begin(); o != _outputs.audio_end(); ++o, ++i) {
457 outs.push_back ((*o)->get_audio_buffer().data (nframes, offset));
461 /* reduce nbufs to the index of the last input buffer */
465 if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
466 actual_gain = _gain * speed_quietning;
472 for (PortSet::audio_iterator o = _outputs.audio_begin(); o != _outputs.audio_end(); ++o, ++i) {
474 dst = (*o)->get_audio_buffer().data(nframes, offset);
475 src = bufs[min(nbufs,i)];
477 if (dg != _gain || actual_gain == 1.0f) {
478 memcpy (dst, src, sizeof (Sample) * nframes);
479 } else if (actual_gain == 0.0f) {
480 memset (dst, 0, sizeof (Sample) * nframes);
482 for (jack_nframes_t x = 0; x < nframes; ++x) {
483 dst[x] = src[x] * actual_gain;
487 (*o)->mark_silence (false);
491 apply_declick (outs, outs.size(), nframes, _gain, dg, false);
495 if (apply_gain_automation) {
501 IO::collect_input (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset)
503 /* io_lock, not taken: function must be called from Session::process() calltree */
508 /* we require that bufs.size() >= 1 */
510 for (PortSet::audio_iterator i = _inputs.audio_begin(); n < nbufs; ++i, ++n) {
511 if (i == _inputs.audio_end()) {
515 /* XXX always read the full extent of the port buffer that
516 we need. One day, we may use jack_port_get_buffer_at_offset()
517 or something similar. For now, this simple hack will
520 Hack? Why yes .. we only need to read nframes-worth of
521 data, but the data we want is at 'offset' within the
525 last = (*i)->get_audio_buffer().data(nframes, offset);
526 // the dest buffer's offset has already been applied
527 memcpy (bufs[n], last, sizeof (Sample) * nframes);
530 /* fill any excess outputs with the last input */
532 while (n < nbufs && last) {
533 // the dest buffer's offset has already been applied
534 memcpy (bufs[n], last, sizeof (Sample) * nframes);
540 IO::just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame,
541 jack_nframes_t nframes, jack_nframes_t offset)
543 vector<Sample*>& bufs = _session.get_passthru_buffers ();
544 uint32_t nbufs = n_process_buffers ();
546 collect_input (bufs, nbufs, nframes, offset);
548 for (uint32_t n = 0; n < nbufs; ++n) {
549 _peak_power[n] = Session::compute_peak (bufs[n], nframes, _peak_power[n]);
554 IO::drop_input_connection ()
556 _input_connection = 0;
557 input_connection_configuration_connection.disconnect();
558 input_connection_connection_connection.disconnect();
559 _session.set_dirty ();
563 IO::drop_output_connection ()
565 _output_connection = 0;
566 output_connection_configuration_connection.disconnect();
567 output_connection_connection_connection.disconnect();
568 _session.set_dirty ();
572 IO::disconnect_input (Port* our_port, string other_port, void* src)
574 if (other_port.length() == 0 || our_port == 0) {
579 Glib::Mutex::Lock em (_session.engine().process_lock());
582 Glib::Mutex::Lock lm (io_lock);
584 /* check that our_port is really one of ours */
586 if ( ! _inputs.contains(our_port)) {
590 /* disconnect it from the source */
592 if (_session.engine().disconnect (other_port, our_port->name())) {
593 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
597 drop_input_connection();
601 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
602 _session.set_dirty ();
608 IO::connect_input (Port* our_port, string other_port, void* src)
610 if (other_port.length() == 0 || our_port == 0) {
615 Glib::Mutex::Lock em(_session.engine().process_lock());
618 Glib::Mutex::Lock lm (io_lock);
620 /* check that our_port is really one of ours */
622 if ( ! _inputs.contains(our_port) ) {
626 /* connect it to the source */
628 if (_session.engine().connect (other_port, our_port->name())) {
632 drop_input_connection ();
636 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
637 _session.set_dirty ();
642 IO::disconnect_output (Port* our_port, string other_port, void* src)
644 if (other_port.length() == 0 || our_port == 0) {
649 Glib::Mutex::Lock em(_session.engine().process_lock());
652 Glib::Mutex::Lock lm (io_lock);
654 /* check that our_port is really one of ours */
656 if ( ! _outputs.contains(our_port) ) {
660 /* disconnect it from the destination */
662 if (_session.engine().disconnect (our_port->name(), other_port)) {
663 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
667 drop_output_connection ();
671 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
672 _session.set_dirty ();
677 IO::connect_output (Port* our_port, string other_port, void* src)
679 if (other_port.length() == 0 || our_port == 0) {
684 Glib::Mutex::Lock em(_session.engine().process_lock());
687 Glib::Mutex::Lock lm (io_lock);
689 /* check that our_port is really one of ours */
691 if ( ! _outputs.contains(our_port) ) {
695 /* connect it to the destination */
697 if (_session.engine().connect (our_port->name(), other_port)) {
701 drop_output_connection ();
705 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
706 _session.set_dirty ();
711 IO::set_input (Port* other_port, void* src)
713 /* this removes all but one ports, and connects that one port
714 to the specified source.
717 if (_input_minimum.get_total() > 1) {
718 /* sorry, you can't do this */
722 if (other_port == 0) {
723 if (_input_minimum == ChanCount::ZERO) {
724 return ensure_inputs (0, false, true, src);
730 if (ensure_inputs (1, true, true, src)) {
734 return connect_input (_inputs.port(0), other_port->name(), src);
738 IO::remove_output_port (Port* port, void* src)
742 IOChange change (NoChange);
745 Glib::Mutex::Lock em(_session.engine().process_lock());
748 Glib::Mutex::Lock lm (io_lock);
750 if (_noutputs - 1 == (uint32_t) _output_minimum) {
751 /* sorry, you can't do this */
755 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
757 change = IOChange (change|ConfigurationChanged);
758 if (port->connected()) {
759 change = IOChange (change|ConnectionsChanged);
762 _session.engine().unregister_port (*i);
765 drop_output_connection ();
771 if (change != NoChange) {
772 setup_peak_meters ();
778 if (change != NoChange) {
779 output_changed (change, src); /* EMIT SIGNAL */
780 _session.set_dirty ();
787 /** Add an output port.
789 * @param destination Name of input port to connect new port to.
790 * @param src Source for emitted ConfigurationChanged signal.
791 * @param type Data type of port. Default value (NIL) will use this IO's default type.
794 IO::add_output_port (string destination, void* src, DataType type)
799 if (type == DataType::NIL)
800 type = _default_type;
803 Glib::Mutex::Lock em(_session.engine().process_lock());
806 Glib::Mutex::Lock lm (io_lock);
808 if (n_outputs() >= _output_maximum) {
812 /* Create a new output port */
814 // FIXME: naming scheme for differently typed ports?
815 if (_output_maximum.get_total() == 1) {
816 snprintf (name, sizeof (name), _("%s/out"), _name.c_str());
818 snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
821 if ((our_port = _session.engine().register_output_port (type, name)) == 0) {
822 error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
826 _outputs.add_port (our_port);
827 drop_output_connection ();
828 setup_peak_meters ();
832 MoreOutputs (n_outputs()); /* EMIT SIGNAL */
835 if (destination.length()) {
836 if (_session.engine().connect (our_port->name(), destination)) {
841 // pan_changed (src); /* EMIT SIGNAL */
842 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
843 _session.set_dirty ();
849 IO::remove_input_port (Port* port, void* src)
853 IOChange change (NoChange);
856 Glib::Mutex::Lock em(_session.engine().process_lock());
859 Glib::Mutex::Lock lm (io_lock);
861 if (((int)_ninputs - 1) < _input_minimum) {
862 /* sorry, you can't do this */
865 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
868 change = IOChange (change|ConfigurationChanged);
870 if (port->connected()) {
871 change = IOChange (change|ConnectionsChanged);
874 _session.engine().unregister_port (*i);
877 drop_input_connection ();
883 if (change != NoChange) {
884 setup_peak_meters ();
890 if (change != NoChange) {
891 input_changed (change, src);
892 _session.set_dirty ();
900 /** Add an input port.
902 * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
903 * @param destination Name of input port to connect new port to.
904 * @param src Source for emitted ConfigurationChanged signal.
907 IO::add_input_port (string source, void* src, DataType type)
912 if (type == DataType::NIL)
913 type = _default_type;
916 Glib::Mutex::Lock em (_session.engine().process_lock());
919 Glib::Mutex::Lock lm (io_lock);
921 if (n_inputs() >= _input_maximum) {
925 /* Create a new input port */
927 // FIXME: naming scheme for differently typed ports?
928 if (_input_maximum.get_total() == 1) {
929 snprintf (name, sizeof (name), _("%s/in"), _name.c_str());
931 snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
934 if ((our_port = _session.engine().register_input_port (type, name)) == 0) {
935 error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
939 _inputs.add_port(our_port);
940 drop_input_connection ();
941 setup_peak_meters ();
945 MoreOutputs (n_inputs()); /* EMIT SIGNAL */
948 if (source.length()) {
950 if (_session.engine().connect (source, our_port->name())) {
955 // pan_changed (src); /* EMIT SIGNAL */
956 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
957 _session.set_dirty ();
963 IO::disconnect_inputs (void* src)
966 Glib::Mutex::Lock em (_session.engine().process_lock());
969 Glib::Mutex::Lock lm (io_lock);
971 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
972 _session.engine().disconnect (*i);
975 drop_input_connection ();
979 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
985 IO::disconnect_outputs (void* src)
988 Glib::Mutex::Lock em (_session.engine().process_lock());
991 Glib::Mutex::Lock lm (io_lock);
993 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
994 _session.engine().disconnect (*i);
997 drop_output_connection ();
1001 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
1002 _session.set_dirty ();
1008 IO::ensure_inputs_locked (uint32_t n, bool clear, void* src)
1011 bool changed = false;
1013 /* remove unused ports */
1015 while (n_inputs().get(_default_type) > n) {
1018 _session.engine().unregister_port (_inputs.back());
1025 /* create any necessary new ports */
1027 while (n_inputs().get(_default_type) < n) {
1031 /* Create a new input port (of the default type) */
1033 if (_input_maximum.get_total() == 1) {
1034 snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
1037 snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
1042 if ((input_port = _session.engine().register_input_port (_default_type, buf)) == 0) {
1043 error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
1048 catch (AudioEngine::PortRegistrationFailure& err) {
1049 setup_peak_meters ();
1055 _inputs.add_port (input_port);
1060 drop_input_connection ();
1061 setup_peak_meters ();
1063 MoreOutputs (n_inputs()); /* EMIT SIGNAL */
1064 _session.set_dirty ();
1068 /* disconnect all existing ports so that we get a fresh start */
1070 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1071 _session.engine().disconnect (*i);
1079 IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
1081 bool in_changed = false;
1082 bool out_changed = false;
1083 bool need_pan_reset;
1085 nin = min (_input_maximum.get(_default_type), static_cast<size_t>(nin));
1087 nout = min (_output_maximum.get(_default_type), static_cast<size_t>(nout));
1089 if (nin == n_inputs().get(_default_type) && nout == n_outputs().get(_default_type) && !clear) {
1094 Glib::Mutex::Lock em (_session.engine().process_lock());
1095 Glib::Mutex::Lock lm (io_lock);
1099 if (n_outputs().get(_default_type) == nout) {
1100 need_pan_reset = false;
1102 need_pan_reset = true;
1105 /* remove unused ports */
1107 while (n_inputs().get(_default_type) > nin) {
1110 _session.engine().unregister_port (_inputs.back());
1113 in_changed = true;*/
1116 while (n_outputs().get(_default_type) > nout) {
1119 _session.engine().unregister_port (_outputs.back());
1120 _outputs.pop_back();
1122 out_changed = true;*/
1125 /* create any necessary new ports (of the default type) */
1127 while (n_inputs().get(_default_type) < nin) {
1131 /* Create a new input port */
1133 if (_input_maximum.get_total() == 1) {
1134 snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
1137 snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
1141 if ((port = _session.engine().register_input_port (_default_type, buf)) == 0) {
1142 error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
1147 catch (AudioEngine::PortRegistrationFailure& err) {
1148 setup_peak_meters ();
1154 _inputs.add_port (port);
1158 /* create any necessary new ports */
1160 while (n_outputs().get(_default_type) < nout) {
1164 /* Create a new output port */
1166 if (_output_maximum.get_total() == 1) {
1167 snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
1169 snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
1173 if ((port = _session.engine().register_output_port (_default_type, buf)) == 0) {
1174 error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
1179 catch (AudioEngine::PortRegistrationFailure& err) {
1180 setup_peak_meters ();
1186 _outputs.add_port (port);
1192 /* disconnect all existing ports so that we get a fresh start */
1194 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1195 _session.engine().disconnect (*i);
1198 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1199 _session.engine().disconnect (*i);
1203 if (in_changed || out_changed) {
1204 setup_peak_meters ();
1210 drop_output_connection ();
1211 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1215 drop_input_connection ();
1216 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1219 if (in_changed || out_changed) {
1220 MoreOutputs (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1221 _session.set_dirty ();
1228 IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
1230 bool changed = false;
1232 n = min (_input_maximum.get(_default_type), static_cast<size_t>(n));
1234 if (n == n_inputs().get(_default_type) && !clear) {
1239 Glib::Mutex::Lock em (_session.engine().process_lock());
1240 Glib::Mutex::Lock im (io_lock);
1241 changed = ensure_inputs_locked (n, clear, src);
1243 changed = ensure_inputs_locked (n, clear, src);
1247 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1248 _session.set_dirty ();
1254 IO::ensure_outputs_locked (uint32_t n, bool clear, void* src)
1257 bool changed = false;
1258 bool need_pan_reset;
1260 if (n_outputs().get(_default_type) == n) {
1261 need_pan_reset = false;
1263 need_pan_reset = true;
1266 /* remove unused ports */
1268 while (n_outputs().get(_default_type) > n) {
1271 _session.engine().unregister_port (_outputs.back());
1272 _outputs.pop_back();
1278 /* create any necessary new ports */
1280 while (n_outputs().get(_default_type) < n) {
1284 /* Create a new output port */
1286 if (_output_maximum.get(_default_type) == 1) {
1287 snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
1289 snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
1292 if ((output_port = _session.engine().register_output_port (_default_type, buf)) == 0) {
1293 error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
1297 _outputs.add_port (output_port);
1299 setup_peak_meters ();
1301 if (need_pan_reset) {
1307 drop_output_connection ();
1308 MoreOutputs (n_outputs()); /* EMIT SIGNAL */
1309 _session.set_dirty ();
1313 /* disconnect all existing ports so that we get a fresh start */
1315 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1316 _session.engine().disconnect (*i);
1324 IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* src)
1326 bool changed = false;
1328 if (_output_maximum < ChanCount::INFINITE) {
1329 n = min (_output_maximum.get(_default_type), static_cast<size_t>(n));
1330 if (n == n_outputs().get(_default_type) && !clear) {
1335 /* XXX caller should hold io_lock, but generally doesn't */
1338 Glib::Mutex::Lock em (_session.engine().process_lock());
1339 Glib::Mutex::Lock im (io_lock);
1340 changed = ensure_outputs_locked (n, clear, src);
1342 changed = ensure_outputs_locked (n, clear, src);
1346 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1352 IO::effective_gain () const
1354 if (gain_automation_playback()) {
1355 return _effective_gain;
1357 return _desired_gain;
1364 if (panners_legal) {
1365 if (!no_panner_reset) {
1366 _panner->reset (n_outputs().get(_default_type), pans_required());
1369 panner_legal_c.disconnect ();
1370 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1375 IO::panners_became_legal ()
1377 _panner->reset (n_outputs().get(_default_type), pans_required());
1378 _panner->load (); // automation
1379 panner_legal_c.disconnect ();
1384 IO::defer_pan_reset ()
1386 no_panner_reset = true;
1390 IO::allow_pan_reset ()
1392 no_panner_reset = false;
1398 IO::get_state (void)
1400 return state (true);
1404 IO::state (bool full_state)
1406 XMLNode* node = new XMLNode (state_node_name);
1409 bool need_ins = true;
1410 bool need_outs = true;
1411 LocaleGuard lg (X_("POSIX"));
1412 Glib::Mutex::Lock lm (io_lock);
1414 node->add_property("name", _name);
1416 node->add_property("id", buf);
1420 if (_input_connection) {
1421 node->add_property ("input-connection", _input_connection->name());
1425 if (_output_connection) {
1426 node->add_property ("output-connection", _output_connection->name());
1431 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1433 const char **connections = (*i)->get_connections();
1435 if (connections && connections[0]) {
1438 for (int n = 0; connections && connections[n]; ++n) {
1443 /* if its a connection to our own port,
1444 return only the port name, not the
1445 whole thing. this allows connections
1446 to be re-established even when our
1447 client name is different.
1450 str += _session.engine().make_port_name_relative (connections[n]);
1462 node->add_property ("inputs", str);
1468 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1470 const char **connections = (*i)->get_connections();
1472 if (connections && connections[0]) {
1476 for (int n = 0; connections[n]; ++n) {
1481 str += _session.engine().make_port_name_relative (connections[n]);
1493 node->add_property ("outputs", str);
1496 node->add_child_nocopy (_panner->state (full_state));
1498 snprintf (buf, sizeof(buf), "%2.12f", gain());
1499 node->add_property ("gain", buf);
1501 const int in_min = (_input_minimum == ChanCount::ZERO) ? -1 : _input_minimum.get(_default_type);
1502 const int in_max = (_input_maximum == ChanCount::INFINITE) ? -1 : _input_maximum.get(_default_type);
1503 const int out_min = (_output_minimum == ChanCount::ZERO) ? -1 : _output_minimum.get(_default_type);
1504 const int out_max = (_output_maximum == ChanCount::INFINITE) ? -1 : _output_maximum.get(_default_type);
1506 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", in_min, in_max, out_min, out_max);
1508 node->add_property ("iolimits", buf);
1513 snprintf (buf, sizeof (buf), "0x%x", (int) _gain_automation_curve.automation_state());
1515 /* never store anything except Off for automation state in a template */
1516 snprintf (buf, sizeof (buf), "0x%x", ARDOUR::Off);
1518 node->add_property ("automation-state", buf);
1519 snprintf (buf, sizeof (buf), "0x%x", (int) _gain_automation_curve.automation_style());
1520 node->add_property ("automation-style", buf);
1522 /* XXX same for pan etc. */
1528 IO::connecting_became_legal ()
1532 if (pending_state_node == 0) {
1533 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1538 connection_legal_c.disconnect ();
1540 ret = make_connections (*pending_state_node);
1543 delete pending_state_node;
1544 pending_state_node = 0;
1551 IO::ports_became_legal ()
1555 if (pending_state_node == 0) {
1556 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1561 port_legal_c.disconnect ();
1563 ret = create_ports (*pending_state_node);
1565 if (connecting_legal) {
1566 delete pending_state_node;
1567 pending_state_node = 0;
1574 IO::set_state (const XMLNode& node)
1576 const XMLProperty* prop;
1577 XMLNodeConstIterator iter;
1578 LocaleGuard lg (X_("POSIX"));
1580 /* force use of non-localized representation of decimal point,
1581 since we use it a lot in XML files and so forth.
1584 if (node.name() != state_node_name) {
1585 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1589 if ((prop = node.property ("name")) != 0) {
1590 _name = prop->value();
1591 _panner->set_name (_name);
1594 if ((prop = node.property ("id")) != 0) {
1595 _id = prop->value ();
1600 size_t out_min = -1;
1601 size_t out_max = -1;
1603 if ((prop = node.property ("iolimits")) != 0) {
1604 sscanf (prop->value().c_str(), "%zd,%zd,%zd,%zd",
1605 &in_min, &in_max, &out_min, &out_max);
1606 _input_minimum = ChanCount(_default_type, in_min);
1607 _input_maximum = ChanCount(_default_type, in_max);
1608 _output_minimum = ChanCount(_default_type, out_min);
1609 _output_maximum = ChanCount(_default_type, out_max);
1612 if ((prop = node.property ("gain")) != 0) {
1613 set_gain (atof (prop->value().c_str()), this);
1614 _gain = _desired_gain;
1617 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1618 if ((*iter)->name() == "Panner") {
1619 _panner->set_state (**iter);
1623 if ((prop = node.property ("automation-state")) != 0) {
1626 x = strtol (prop->value().c_str(), 0, 16);
1627 set_gain_automation_state (AutoState (x));
1630 if ((prop = node.property ("automation-style")) != 0) {
1633 x = strtol (prop->value().c_str(), 0, 16);
1634 set_gain_automation_style (AutoStyle (x));
1639 if (create_ports (node)) {
1645 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1648 if (panners_legal) {
1651 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1654 if (connecting_legal) {
1656 if (make_connections (node)) {
1662 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1665 if (!ports_legal || !connecting_legal) {
1666 pending_state_node = new XMLNode (node);
1673 IO::create_ports (const XMLNode& node)
1675 const XMLProperty* prop;
1677 int num_outputs = 0;
1679 if ((prop = node.property ("input-connection")) != 0) {
1681 Connection* c = _session.connection_by_name (prop->value());
1684 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
1686 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
1687 error << _("No input connections available as a replacement")
1691 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
1696 num_inputs = c->nports();
1698 } else if ((prop = node.property ("inputs")) != 0) {
1700 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1703 if ((prop = node.property ("output-connection")) != 0) {
1704 Connection* c = _session.connection_by_name (prop->value());
1707 error << string_compose(_("Unknown connection \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
1709 if ((c = _session.connection_by_name (_("out 1"))) == 0) {
1710 error << _("No output connections available as a replacement")
1714 info << string_compose (_("Connection %1 was not available - \"out 1\" used instead"), prop->value())
1719 num_outputs = c->nports ();
1721 } else if ((prop = node.property ("outputs")) != 0) {
1722 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1725 no_panner_reset = true;
1727 if (ensure_io (num_inputs, num_outputs, true, this)) {
1728 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1732 no_panner_reset = false;
1734 set_deferred_state ();
1742 IO::make_connections (const XMLNode& node)
1744 const XMLProperty* prop;
1746 if ((prop = node.property ("input-connection")) != 0) {
1747 Connection* c = _session.connection_by_name (prop->value());
1750 error << string_compose(_("Unknown connection \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
1752 if ((c = _session.connection_by_name (_("in 1"))) == 0) {
1753 error << _("No input connections available as a replacement")
1757 info << string_compose (_("Connection %1 was not available - \"in 1\" used instead"), prop->value())
1762 use_input_connection (*c, this);
1764 } else if ((prop = node.property ("inputs")) != 0) {
1765 if (set_inputs (prop->value())) {
1766 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1771 if ((prop = node.property ("output-connection")) != 0) {
1772 Connection* c = _session.connection_by_name (prop->value());
1775 error << string_compose(_("Unknown connection \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
1777 if ((c = _session.connection_by_name (_("out 1"))) == 0) {
1778 error << _("No output connections available as a replacement")
1782 info << string_compose (_("Connection %1 was not available - \"out 1\" used instead"), prop->value())
1787 use_output_connection (*c, this);
1789 } else if ((prop = node.property ("outputs")) != 0) {
1790 if (set_outputs (prop->value())) {
1791 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1800 IO::set_inputs (const string& str)
1802 vector<string> ports;
1807 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1811 if (ensure_inputs (nports, true, true, this)) {
1815 string::size_type start, end, ostart;
1822 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1825 if ((end = str.find_first_of ('}', start)) == string::npos) {
1826 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1830 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1831 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1837 for (int x = 0; x < n; ++x) {
1838 connect_input (input (i), ports[x], this);
1850 IO::set_outputs (const string& str)
1852 vector<string> ports;
1857 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1861 if (ensure_outputs (nports, true, true, this)) {
1865 string::size_type start, end, ostart;
1872 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1875 if ((end = str.find_first_of ('}', start)) == string::npos) {
1876 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1880 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1881 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1887 for (int x = 0; x < n; ++x) {
1888 connect_output (output (i), ports[x], this);
1900 IO::parse_io_string (const string& str, vector<string>& ports)
1902 string::size_type pos, opos;
1904 if (str.length() == 0) {
1913 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1914 ports.push_back (str.substr (opos, pos - opos));
1918 if (opos < str.length()) {
1919 ports.push_back (str.substr(opos));
1922 return ports.size();
1926 IO::parse_gain_string (const string& str, vector<string>& ports)
1928 string::size_type pos, opos;
1934 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1935 ports.push_back (str.substr (opos, pos - opos));
1939 if (opos < str.length()) {
1940 ports.push_back (str.substr(opos));
1943 return ports.size();
1947 IO::set_name (string name, void* src)
1949 if (name == _name) {
1953 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1954 string current_name = (*i)->short_name();
1955 current_name.replace (current_name.find (_name), _name.length(), name);
1956 (*i)->set_name (current_name);
1959 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1960 string current_name = (*i)->short_name();
1961 current_name.replace (current_name.find (_name), _name.length(), name);
1962 (*i)->set_name (current_name);
1966 name_changed (src); /* EMIT SIGNAL */
1972 IO::set_input_minimum (int n)
1975 _input_minimum = ChanCount::ZERO;
1977 _input_minimum = ChanCount(_default_type, n);
1981 IO::set_input_maximum (int n)
1984 _input_maximum = ChanCount::INFINITE;
1986 _input_maximum = ChanCount(_default_type, n);
1990 IO::set_output_minimum (int n)
1993 _output_minimum = ChanCount::ZERO;
1995 _output_minimum = ChanCount(_default_type, n);
1999 IO::set_output_maximum (int n)
2002 _output_maximum = ChanCount::INFINITE;
2004 _output_maximum = ChanCount(_default_type, n);
2008 IO::set_input_minimum (ChanCount n)
2014 IO::set_input_maximum (ChanCount n)
2020 IO::set_output_minimum (ChanCount n)
2022 _output_minimum = n;
2026 IO::set_output_maximum (ChanCount n)
2028 _output_maximum = n;
2032 IO::set_port_latency (jack_nframes_t nframes)
2034 Glib::Mutex::Lock lm (io_lock);
2036 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2037 (*i)->set_latency (nframes);
2042 IO::output_latency () const
2044 jack_nframes_t max_latency;
2045 jack_nframes_t latency;
2049 /* io lock not taken - must be protected by other means */
2051 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2052 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2053 max_latency = latency;
2061 IO::input_latency () const
2063 jack_nframes_t max_latency;
2064 jack_nframes_t latency;
2068 /* io lock not taken - must be protected by other means */
2070 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2071 if ((latency = _session.engine().get_port_total_latency (*(*i))) > max_latency) {
2072 max_latency = latency;
2080 IO::use_input_connection (Connection& c, void* src)
2085 Glib::Mutex::Lock lm (_session.engine().process_lock());
2086 Glib::Mutex::Lock lm2 (io_lock);
2090 drop_input_connection ();
2092 if (ensure_inputs (limit, false, false, src)) {
2096 /* first pass: check the current state to see what's correctly
2097 connected, and drop anything that we don't want.
2100 for (uint32_t n = 0; n < limit; ++n) {
2101 const Connection::PortList& pl = c.port_connections (n);
2103 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2105 if (!_inputs.port(n)->connected_to ((*i))) {
2107 /* clear any existing connections */
2109 _session.engine().disconnect (_inputs.port(n));
2111 } else if (_inputs.port(n)->connected() > 1) {
2113 /* OK, it is connected to the port we want,
2114 but its also connected to other ports.
2115 Change that situation.
2118 /* XXX could be optimized to not drop
2122 _session.engine().disconnect (_inputs.port(n));
2128 /* second pass: connect all requested ports where necessary */
2130 for (uint32_t n = 0; n < limit; ++n) {
2131 const Connection::PortList& pl = c.port_connections (n);
2133 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2135 if (!_inputs.port(n)->connected_to ((*i))) {
2137 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2145 _input_connection = &c;
2147 input_connection_configuration_connection = c.ConfigurationChanged.connect
2148 (mem_fun (*this, &IO::input_connection_configuration_changed));
2149 input_connection_connection_connection = c.ConnectionsChanged.connect
2150 (mem_fun (*this, &IO::input_connection_connection_changed));
2153 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2158 IO::use_output_connection (Connection& c, void* src)
2163 Glib::Mutex::Lock lm (_session.engine().process_lock());
2164 Glib::Mutex::Lock lm2 (io_lock);
2168 drop_output_connection ();
2170 if (ensure_outputs (limit, false, false, src)) {
2174 /* first pass: check the current state to see what's correctly
2175 connected, and drop anything that we don't want.
2178 for (uint32_t n = 0; n < limit; ++n) {
2180 const Connection::PortList& pl = c.port_connections (n);
2182 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2184 if (!_outputs.port(n)->connected_to ((*i))) {
2186 /* clear any existing connections */
2188 _session.engine().disconnect (_outputs.port(n));
2190 } else if (_outputs.port(n)->connected() > 1) {
2192 /* OK, it is connected to the port we want,
2193 but its also connected to other ports.
2194 Change that situation.
2197 /* XXX could be optimized to not drop
2201 _session.engine().disconnect (_outputs.port(n));
2206 /* second pass: connect all requested ports where necessary */
2208 for (uint32_t n = 0; n < limit; ++n) {
2210 const Connection::PortList& pl = c.port_connections (n);
2212 for (Connection::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2214 if (!_outputs.port(n)->connected_to ((*i))) {
2216 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2223 _output_connection = &c;
2225 output_connection_configuration_connection = c.ConfigurationChanged.connect
2226 (mem_fun (*this, &IO::output_connection_configuration_changed));
2227 output_connection_connection_connection = c.ConnectionsChanged.connect
2228 (mem_fun (*this, &IO::output_connection_connection_changed));
2231 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2237 IO::disable_connecting ()
2239 connecting_legal = false;
2244 IO::enable_connecting ()
2246 connecting_legal = true;
2247 return ConnectingLegal ();
2251 IO::disable_ports ()
2253 ports_legal = false;
2261 return PortsLegal ();
2265 IO::disable_panners (void)
2267 panners_legal = false;
2272 IO::reset_panners ()
2274 panners_legal = true;
2275 return PannersLegal ();
2279 IO::input_connection_connection_changed (int ignored)
2281 use_input_connection (*_input_connection, this);
2285 IO::input_connection_configuration_changed ()
2287 use_input_connection (*_input_connection, this);
2291 IO::output_connection_connection_changed (int ignored)
2293 use_output_connection (*_output_connection, this);
2297 IO::output_connection_configuration_changed ()
2299 use_output_connection (*_output_connection, this);
2303 IO::GainControllable::set_value (float val)
2305 io.set_gain (direct_control_to_gain (val), this);
2309 IO::GainControllable::get_value (void) const
2311 return direct_gain_to_control (io.effective_gain());
2315 IO::reset_peak_meters ()
2317 uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO));
2319 for (uint32_t i = 0; i < limit; ++i) {
2325 IO::setup_peak_meters ()
2327 uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO));
2329 while (_peak_power.size() < limit) {
2330 _peak_power.push_back (0);
2331 _visible_peak_power.push_back (0);
2336 IO::get_memento() const
2338 return sigc::bind (mem_fun (*(const_cast<IO *>(this)), &StateManager::use_state), _current_state_id);
2342 IO::restore_state (StateManager::State& state)
2347 StateManager::State*
2348 IO::state_factory (std::string why) const
2350 StateManager::State* state = new StateManager::State (why);
2355 Update the peak meters.
2357 The meter signal lock is taken to prevent modification of the
2358 Meter signal while updating the meters, taking the meter signal
2359 lock prior to taking the io_lock ensures that all IO will remain
2360 valid while metering.
2365 Glib::Mutex::Lock guard (m_meter_signal_lock);
2373 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2374 uint32_t limit = max (n_inputs().get(DataType::AUDIO), n_outputs().get(DataType::AUDIO));
2376 for (uint32_t n = 0; n < limit; ++n) {
2378 /* XXX we should use atomic exchange here */
2380 /* grab peak since last read */
2382 float new_peak = _peak_power[n];
2385 /* compute new visible value using falloff */
2387 if (new_peak > 0.0) {
2388 new_peak = coefficient_to_dB (new_peak);
2390 new_peak = minus_infinity();
2393 if (_session.meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
2394 _visible_peak_power[n] = new_peak;
2397 new_peak = _visible_peak_power[n] - _session.meter_falloff();
2398 _visible_peak_power[n] = max (new_peak, -INFINITY);
2404 IO::save_automation (const string& path)
2409 fullpath = _session.automation_dir();
2412 out.open (fullpath.c_str());
2415 error << string_compose(_("%1: could not open automation event file \"%2\""), _name, fullpath) << endmsg;
2419 out << X_("version ") << current_automation_version_number << endl;
2421 /* XXX use apply_to_points to get thread safety */
2423 for (AutomationList::iterator i = _gain_automation_curve.begin(); i != _gain_automation_curve.end(); ++i) {
2424 out << "g " << (jack_nframes_t) floor ((*i)->when) << ' ' << (*i)->value << endl;
2433 IO::load_automation (const string& path)
2438 uint32_t linecnt = 0;
2440 LocaleGuard lg (X_("POSIX"));
2442 fullpath = _session.automation_dir();
2445 in.open (fullpath.c_str());
2448 fullpath = _session.automation_dir();
2449 fullpath += _session.snap_name();
2452 in.open (fullpath.c_str());
2454 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
2459 clear_automation ();
2461 while (in.getline (line, sizeof(line), '\n')) {
2463 jack_nframes_t when;
2466 if (++linecnt == 1) {
2467 if (memcmp (line, "version", 7) == 0) {
2468 if (sscanf (line, "version %f", &version) != 1) {
2469 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
2473 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
2477 if (version != current_automation_version_number) {
2478 error << string_compose(_("mismatched automation event file version (%1)"), version) << endmsg;
2485 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
2486 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
2492 _gain_automation_curve.add (when, value, true);
2502 /* older (pre-1.0) versions of ardour used this */
2506 warning << _("dubious automation event found (and ignored)") << endmsg;
2510 _gain_automation_curve.save_state (_("loaded from disk"));
2516 IO::clear_automation ()
2518 Glib::Mutex::Lock lm (automation_lock);
2519 _gain_automation_curve.clear ();
2520 _panner->clear_automation ();
2524 IO::set_gain_automation_state (AutoState state)
2526 bool changed = false;
2529 Glib::Mutex::Lock lm (automation_lock);
2531 if (state != _gain_automation_curve.automation_state()) {
2533 last_automation_snapshot = 0;
2534 _gain_automation_curve.set_automation_state (state);
2537 set_gain (_gain_automation_curve.eval (_session.transport_frame()), this);
2543 _session.set_dirty ();
2544 gain_automation_state_changed (); /* EMIT SIGNAL */
2549 IO::set_gain_automation_style (AutoStyle style)
2551 bool changed = false;
2554 Glib::Mutex::Lock lm (automation_lock);
2556 if (style != _gain_automation_curve.automation_style()) {
2558 _gain_automation_curve.set_automation_style (style);
2563 gain_automation_style_changed (); /* EMIT SIGNAL */
2567 IO::inc_gain (gain_t factor, void *src)
2569 if (_desired_gain == 0.0f)
2570 set_gain (0.000001f + (0.000001f * factor), src);
2572 set_gain (_desired_gain + (_desired_gain * factor), src);
2576 IO::set_gain (gain_t val, void *src)
2578 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2579 if (val>1.99526231f) val=1.99526231f;
2582 Glib::Mutex::Lock dm (declick_lock);
2583 _desired_gain = val;
2586 if (_session.transport_stopped()) {
2587 _effective_gain = val;
2592 _gain_control.Changed (); /* EMIT SIGNAL */
2594 if (_session.transport_stopped() && src != 0 && src != this && gain_automation_recording()) {
2595 _gain_automation_curve.add (_session.transport_frame(), val);
2599 _session.set_dirty();
2603 IO::start_gain_touch ()
2605 _gain_automation_curve.start_touch ();
2609 IO::end_gain_touch ()
2611 _gain_automation_curve.stop_touch ();
2615 IO::start_pan_touch (uint32_t which)
2617 if (which < _panner->size()) {
2618 (*_panner)[which]->automation().start_touch();
2623 IO::end_pan_touch (uint32_t which)
2625 if (which < _panner->size()) {
2626 (*_panner)[which]->automation().stop_touch();
2632 IO::automation_snapshot (jack_nframes_t now)
2634 if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) {
2636 if (gain_automation_recording()) {
2637 _gain_automation_curve.rt_add (now, gain());
2640 _panner->snapshot (now);
2642 last_automation_snapshot = now;
2647 IO::transport_stopped (jack_nframes_t frame)
2649 _gain_automation_curve.reposition_for_rt_add (frame);
2651 if (_gain_automation_curve.automation_state() != Off) {
2653 if (gain_automation_recording()) {
2654 _gain_automation_curve.save_state (_("automation write/touch"));
2657 /* the src=0 condition is a special signal to not propagate
2658 automation gain changes into the mix group when locating.
2661 set_gain (_gain_automation_curve.eval (frame), 0);
2664 _panner->transport_stopped (frame);
2668 IO::find_input_port_hole ()
2670 /* CALLER MUST HOLD IO LOCK */
2674 if (_inputs.empty()) {
2678 for (n = 1; n < UINT_MAX; ++n) {
2679 char buf[jack_port_name_size()];
2680 PortSet::iterator i = _inputs.begin();
2682 snprintf (buf, jack_port_name_size(), _("%s/in %u"), _name.c_str(), n);
2684 for ( ; i != _inputs.end(); ++i) {
2685 if ((*i)->short_name() == buf) {
2690 if (i == _inputs.end()) {
2698 IO::find_output_port_hole ()
2700 /* CALLER MUST HOLD IO LOCK */
2704 if (_outputs.empty()) {
2708 for (n = 1; n < UINT_MAX; ++n) {
2709 char buf[jack_port_name_size()];
2710 PortSet::iterator i = _outputs.begin();
2712 snprintf (buf, jack_port_name_size(), _("%s/out %u"), _name.c_str(), n);
2714 for ( ; i != _outputs.end(); ++i) {
2715 if ((*i)->short_name() == buf) {
2720 if (i == _outputs.end()) {
2729 IO::audio_input(uint32_t n) const
2731 return dynamic_cast<AudioPort*>(input(n));
2735 IO::audio_output(uint32_t n) const
2737 return dynamic_cast<AudioPort*>(output(n));
2741 IO::midi_input(uint32_t n) const
2743 return dynamic_cast<MidiPort*>(input(n));
2747 IO::midi_output(uint32_t n) const
2749 return dynamic_cast<MidiPort*>(output(n));