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.
25 #include <sigc++/bind.h>
27 #include <glibmm/thread.h>
29 #include <pbd/xml++.h>
30 #include <pbd/replace_all.h>
32 #include <ardour/audioengine.h>
33 #include <ardour/io.h>
34 #include <ardour/port.h>
35 #include <ardour/audio_port.h>
36 #include <ardour/midi_port.h>
37 #include <ardour/auto_bundle.h>
38 #include <ardour/session.h>
39 #include <ardour/cycle_timer.h>
40 #include <ardour/panner.h>
41 #include <ardour/buffer_set.h>
42 #include <ardour/meter.h>
43 #include <ardour/amp.h>
50 A bug in OS X's cmath that causes isnan() and isinf() to be
51 "undeclared". the following works around that
54 #if defined(__APPLE__) && defined(__MACH__)
55 extern "C" int isnan (double);
56 extern "C" int isinf (double);
59 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
62 using namespace ARDOUR;
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,ChanCount> IO::PortCountChanged;
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.
83 static gain_t direct_control_to_gain (double fract) {
84 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
85 /* this maxes at +6dB */
86 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
89 static double direct_gain_to_control (gain_t gain) {
90 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
91 if (gain == 0) return 0.0;
93 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
97 /** @param default_type The type of port that will be created by ensure_io
98 * and friends if no type is explicitly requested (to avoid breakage).
100 IO::IO (Session& s, const string& name,
101 int input_min, int input_max, int output_min, int output_max,
102 DataType default_type)
103 : Automatable (s, name),
104 _output_buffers (new BufferSet()),
105 _default_type (default_type),
106 _input_minimum (ChanCount::ZERO),
107 _input_maximum (ChanCount::INFINITE),
108 _output_minimum (ChanCount::ZERO),
109 _output_maximum (ChanCount::INFINITE)
111 _panner = new Panner (name, _session);
112 _meter = new PeakMeter (_session);
115 _input_minimum = ChanCount(_default_type, input_min);
117 if (input_max >= 0) {
118 _input_maximum = ChanCount(_default_type, input_max);
120 if (output_min > 0) {
121 _output_minimum = ChanCount(_default_type, output_min);
123 if (output_max >= 0) {
124 _output_maximum = ChanCount(_default_type, output_max);
129 pending_state_node = 0;
130 no_panner_reset = false;
131 _phase_invert = false;
134 boost::shared_ptr<AutomationList> gl(
135 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
137 _gain_control = boost::shared_ptr<GainControl>(
138 new GainControl(X_("gaincontrol"), *this, gl));
140 add_control(_gain_control);
142 apply_gain_automation = false;
145 // IO::Meter is emitted from another thread so the
146 // Meter signal must be protected.
147 Glib::Mutex::Lock guard (m_meter_signal_lock);
148 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
151 // Connect to our own PortCountChanged signal to connect output buffers
152 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
154 _session.add_controllable (_gain_control);
156 create_bundles_for_inputs_and_outputs ();
159 IO::IO (Session& s, const XMLNode& node, DataType dt)
160 : Automatable (s, "unnamed io"),
161 _output_buffers (new BufferSet()),
164 _meter = new PeakMeter (_session);
168 no_panner_reset = false;
172 apply_gain_automation = false;
174 boost::shared_ptr<AutomationList> gl(
175 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
177 _gain_control = boost::shared_ptr<GainControl>(
178 new GainControl(X_("gaincontrol"), *this, gl));
180 add_control(_gain_control);
185 // IO::Meter is emitted from another thread so the
186 // Meter signal must be protected.
187 Glib::Mutex::Lock guard (m_meter_signal_lock);
188 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
191 // Connect to our own PortCountChanged signal to connect output buffers
192 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
194 _session.add_controllable (_gain_control);
196 create_bundles_for_inputs_and_outputs ();
201 cerr << "Deleting IO called " << _name << endl;
203 Glib::Mutex::Lock guard (m_meter_signal_lock);
205 Glib::Mutex::Lock lm (io_lock);
207 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
208 _session.engine().unregister_port (*i);
211 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
212 _session.engine().unregister_port (*i);
215 m_meter_connection.disconnect();
219 delete _output_buffers;
223 IO::silence (nframes_t nframes, nframes_t offset)
225 /* io_lock, not taken: function must be called from Session::process() calltree */
227 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
228 i->get_buffer().silence (nframes, offset);
232 /** Deliver bufs to the IO's Jack outputs.
234 * This function should automatically do whatever it necessary to correctly deliver bufs
235 * to the outputs, eg applying gain or pan or whatever else needs to be done.
238 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
240 // FIXME: type specific code doesn't actually need to be here, it will go away in time
242 /* ********** AUDIO ********** */
244 // Apply gain if gain automation isn't playing
245 if ( ! apply_gain_automation) {
247 gain_t dg = _gain; // desired gain
250 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
258 if (dg != _gain || dg != 1.0)
259 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
262 // Use the panner to distribute audio to output port buffers
263 if (_panner && !_panner->empty() && !_panner->bypassed()) {
264 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
266 const DataType type = DataType::AUDIO;
268 // Copy any audio 1:1 to outputs
270 BufferSet::iterator o = output_buffers().begin(type);
271 BufferSet::iterator i = bufs.begin(type);
272 BufferSet::iterator prev = i;
274 while (i != bufs.end(type) && o != output_buffers().end (type)) {
275 o->read_from(*i, nframes, offset);
281 /* extra outputs get a copy of the last buffer */
283 while (o != output_buffers().end(type)) {
284 o->read_from(*prev, nframes, offset);
289 /* ********** MIDI ********** */
291 // No MIDI, we're done here
292 if (bufs.count().n_midi() == 0) {
296 const DataType type = DataType::MIDI;
298 // Copy any MIDI 1:1 to outputs
299 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
300 BufferSet::iterator o = output_buffers().begin(type);
301 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
302 o->read_from(*i, nframes, offset);
307 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
309 assert(outs.available() >= n_inputs());
311 outs.set_count(n_inputs());
313 if (outs.count() == ChanCount::ZERO)
316 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
318 BufferSet::iterator o = outs.begin(*t);
319 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
320 o->read_from(i->get_buffer(), nframes, offset);
327 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
328 nframes_t nframes, nframes_t offset)
330 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
332 collect_input (bufs, nframes, offset);
334 _meter->run(bufs, start_frame, end_frame, nframes, offset);
339 IO::check_bundles_connected_to_inputs ()
341 check_bundles (_bundles_connected_to_inputs, inputs());
345 IO::check_bundles_connected_to_outputs ()
347 check_bundles (_bundles_connected_to_outputs, outputs());
351 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
353 std::vector<UserBundleInfo> new_list;
355 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
357 uint32_t const N = i->bundle->nchannels ();
359 if (ports.num_ports() < N) {
364 for (uint32_t j = 0; j < N; ++j) {
365 /* Every port on bundle channel j must be connected to our input j */
366 PortList const pl = i->bundle->channel_ports (j);
367 for (uint32_t k = 0; k < pl.size(); ++k) {
368 if (ports.port(j)->connected_to (pl[k]) == false) {
380 new_list.push_back (*i);
382 i->configuration_will_change.disconnect ();
383 i->configuration_has_changed.disconnect ();
384 i->ports_will_change.disconnect ();
385 i->ports_have_changed.disconnect ();
394 IO::disconnect_input (Port* our_port, string other_port, void* src)
396 if (other_port.length() == 0 || our_port == 0) {
401 BLOCK_PROCESS_CALLBACK ();
404 Glib::Mutex::Lock lm (io_lock);
406 /* check that our_port is really one of ours */
408 if ( ! _inputs.contains(our_port)) {
412 /* disconnect it from the source */
414 if (_session.engine().disconnect (other_port, our_port->name())) {
415 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
419 check_bundles_connected_to_inputs ();
423 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
424 _session.set_dirty ();
430 IO::connect_input (Port* our_port, string other_port, void* src)
432 if (other_port.length() == 0 || our_port == 0) {
437 BLOCK_PROCESS_CALLBACK ();
440 Glib::Mutex::Lock lm (io_lock);
442 /* check that our_port is really one of ours */
444 if ( ! _inputs.contains(our_port) ) {
448 /* connect it to the source */
450 if (_session.engine().connect (other_port, our_port->name())) {
456 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
457 _session.set_dirty ();
462 IO::disconnect_output (Port* our_port, string other_port, void* src)
464 if (other_port.length() == 0 || our_port == 0) {
469 BLOCK_PROCESS_CALLBACK ();
472 Glib::Mutex::Lock lm (io_lock);
474 /* check that our_port is really one of ours */
476 if ( ! _outputs.contains(our_port) ) {
480 /* disconnect it from the destination */
482 if (_session.engine().disconnect (our_port->name(), other_port)) {
483 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
487 check_bundles_connected_to_outputs ();
491 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
492 _session.set_dirty ();
497 IO::connect_output (Port* our_port, string other_port, void* src)
499 if (other_port.length() == 0 || our_port == 0) {
504 BLOCK_PROCESS_CALLBACK ();
508 Glib::Mutex::Lock lm (io_lock);
510 /* check that our_port is really one of ours */
512 if ( ! _outputs.contains(our_port) ) {
516 /* connect it to the destination */
518 if (_session.engine().connect (our_port->name(), other_port)) {
524 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
525 _session.set_dirty ();
530 IO::set_input (Port* other_port, void* src)
532 /* this removes all but one ports, and connects that one port
533 to the specified source.
536 if (_input_minimum.n_total() > 1) {
537 /* sorry, you can't do this */
541 if (other_port == 0) {
542 if (_input_minimum == ChanCount::ZERO) {
543 return ensure_inputs (ChanCount::ZERO, false, true, src);
549 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
553 return connect_input (_inputs.port(0), other_port->name(), src);
557 IO::remove_output_port (Port* port, void* src)
559 IOChange change (NoChange);
562 BLOCK_PROCESS_CALLBACK ();
566 Glib::Mutex::Lock lm (io_lock);
568 if (n_outputs() <= _output_minimum) {
569 /* sorry, you can't do this */
573 if (_outputs.remove(port)) {
574 change = IOChange (change|ConfigurationChanged);
576 if (port->connected()) {
577 change = IOChange (change|ConnectionsChanged);
580 _session.engine().unregister_port (*port);
581 check_bundles_connected_to_outputs ();
583 setup_peak_meters ();
588 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
591 if (change == ConnectionsChanged) {
592 setup_bundles_for_inputs_and_outputs ();
595 if (change != NoChange) {
596 output_changed (change, src);
597 _session.set_dirty ();
604 /** Add an output port.
606 * @param destination Name of input port to connect new port to.
607 * @param src Source for emitted ConfigurationChanged signal.
608 * @param type Data type of port. Default value (NIL) will use this IO's default type.
611 IO::add_output_port (string destination, void* src, DataType type)
616 if (type == DataType::NIL)
617 type = _default_type;
620 BLOCK_PROCESS_CALLBACK ();
624 Glib::Mutex::Lock lm (io_lock);
626 if (n_outputs() >= _output_maximum) {
630 /* Create a new output port */
632 // FIXME: naming scheme for differently typed ports?
633 if (_output_maximum.get(type) == 1) {
634 snprintf (name, sizeof (name), _("%s/out"), _name.c_str());
636 snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
639 if ((our_port = _session.engine().register_output_port (Jack, type, name)) == 0) {
640 error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
644 _outputs.add (our_port);
645 setup_peak_meters ();
649 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
652 if (destination.length()) {
653 if (_session.engine().connect (our_port->name(), destination)) {
658 // pan_changed (src); /* EMIT SIGNAL */
659 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
660 setup_bundles_for_inputs_and_outputs ();
661 _session.set_dirty ();
667 IO::remove_input_port (Port* port, void* src)
669 IOChange change (NoChange);
672 BLOCK_PROCESS_CALLBACK ();
676 Glib::Mutex::Lock lm (io_lock);
678 if (n_inputs() <= _input_minimum) {
679 /* sorry, you can't do this */
683 if (_inputs.remove(port)) {
684 change = IOChange (change|ConfigurationChanged);
686 if (port->connected()) {
687 change = IOChange (change|ConnectionsChanged);
690 _session.engine().unregister_port (*port);
691 check_bundles_connected_to_inputs ();
693 setup_peak_meters ();
698 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
701 if (change == ConfigurationChanged) {
702 setup_bundles_for_inputs_and_outputs ();
705 if (change != NoChange) {
706 input_changed (change, src);
707 _session.set_dirty ();
715 /** Add an input port.
717 * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
718 * @param destination Name of input port to connect new port to.
719 * @param src Source for emitted ConfigurationChanged signal.
722 IO::add_input_port (string source, void* src, DataType type)
727 if (type == DataType::NIL)
728 type = _default_type;
731 BLOCK_PROCESS_CALLBACK ();
734 Glib::Mutex::Lock lm (io_lock);
736 if (n_inputs() >= _input_maximum) {
740 /* Create a new input port */
742 // FIXME: naming scheme for differently typed ports?
743 if (_input_maximum.get(type) == 1) {
744 snprintf (name, sizeof (name), _("%s/in"), _name.c_str());
746 snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
749 if ((our_port = _session.engine().register_input_port (Jack, type, name)) == 0) {
750 error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
754 _inputs.add (our_port);
755 setup_peak_meters ();
759 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
762 if (source.length()) {
764 if (_session.engine().connect (source, our_port->name())) {
769 // pan_changed (src); /* EMIT SIGNAL */
770 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
771 setup_bundles_for_inputs_and_outputs ();
772 _session.set_dirty ();
778 IO::disconnect_inputs (void* src)
781 BLOCK_PROCESS_CALLBACK ();
784 Glib::Mutex::Lock lm (io_lock);
786 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
787 _session.engine().disconnect (*i);
790 check_bundles_connected_to_inputs ();
794 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
800 IO::disconnect_outputs (void* src)
803 BLOCK_PROCESS_CALLBACK ();
806 Glib::Mutex::Lock lm (io_lock);
808 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
809 _session.engine().disconnect (*i);
812 check_bundles_connected_to_outputs ();
816 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
817 _session.set_dirty ();
823 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
825 Port* input_port = 0;
826 bool changed = false;
829 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
831 const size_t n = count.get(*t);
833 /* remove unused ports */
834 for (size_t i = n_inputs().get(*t); i > n; --i) {
835 input_port = _inputs.port(*t, i-1);
838 _inputs.remove(input_port);
839 _session.engine().unregister_port (*input_port);
844 /* create any necessary new ports */
845 while (n_inputs().get(*t) < n) {
849 if (_input_maximum.get(*t) == 1) {
850 snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
852 snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
857 if ((input_port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
858 error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
863 catch (AudioEngine::PortRegistrationFailure& err) {
864 setup_peak_meters ();
867 throw AudioEngine::PortRegistrationFailure();
870 _inputs.add (input_port);
876 check_bundles_connected_to_inputs ();
877 setup_peak_meters ();
879 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
880 _session.set_dirty ();
884 /* disconnect all existing ports so that we get a fresh start */
885 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
886 _session.engine().disconnect (*i);
893 /** Attach output_buffers to port buffers.
895 * Connected to IO's own PortCountChanged signal.
898 IO::attach_buffers(ChanCount ignored)
900 _output_buffers->attach_buffers(_outputs);
904 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
906 bool in_changed = false;
907 bool out_changed = false;
908 bool need_pan_reset = false;
910 in = min (_input_maximum, in);
912 out = min (_output_maximum, out);
914 if (in == n_inputs() && out == n_outputs() && !clear) {
919 BLOCK_PROCESS_CALLBACK ();
920 Glib::Mutex::Lock lm (io_lock);
924 if (n_outputs() != out) {
925 need_pan_reset = true;
928 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
930 const size_t nin = in.get(*t);
931 const size_t nout = out.get(*t);
933 Port* output_port = 0;
934 Port* input_port = 0;
936 /* remove unused output ports */
937 for (size_t i = n_outputs().get(*t); i > nout; --i) {
938 output_port = _outputs.port(*t, i-1);
941 _outputs.remove(output_port);
942 _session.engine().unregister_port (*output_port);
947 /* remove unused input ports */
948 for (size_t i = n_inputs().get(*t); i > nin; --i) {
949 input_port = _inputs.port(*t, i-1);
952 _inputs.remove(input_port);
953 _session.engine().unregister_port (*input_port);
958 /* create any necessary new input ports */
960 while (n_inputs().get(*t) < nin) {
964 /* Create a new input port */
966 if (_input_maximum.get(*t) == 1) {
967 snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
969 snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
973 if ((port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
974 error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
979 catch (AudioEngine::PortRegistrationFailure& err) {
980 setup_peak_meters ();
983 throw AudioEngine::PortRegistrationFailure();
990 /* create any necessary new output ports */
992 while (n_outputs().get(*t) < nout) {
996 /* Create a new output port */
998 if (_output_maximum.get(*t) == 1) {
999 snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
1001 snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
1005 if ((port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
1006 error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
1011 catch (AudioEngine::PortRegistrationFailure& err) {
1012 setup_peak_meters ();
1015 throw AudioEngine::PortRegistrationFailure ();
1018 _outputs.add (port);
1025 /* disconnect all existing ports so that we get a fresh start */
1027 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1028 _session.engine().disconnect (*i);
1031 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1032 _session.engine().disconnect (*i);
1036 if (in_changed || out_changed) {
1037 setup_peak_meters ();
1043 check_bundles_connected_to_outputs ();
1044 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1048 check_bundles_connected_to_inputs ();
1049 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1052 if (in_changed || out_changed) {
1053 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1054 setup_bundles_for_inputs_and_outputs ();
1055 _session.set_dirty ();
1062 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1064 bool changed = false;
1066 count = min (_input_maximum, count);
1068 if (count == n_inputs() && !clear) {
1073 BLOCK_PROCESS_CALLBACK ();
1074 Glib::Mutex::Lock im (io_lock);
1075 changed = ensure_inputs_locked (count, clear, src);
1077 changed = ensure_inputs_locked (count, clear, src);
1081 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1082 setup_bundles_for_inputs_and_outputs ();
1083 _session.set_dirty ();
1089 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1091 Port* output_port = 0;
1092 bool changed = false;
1093 bool need_pan_reset = false;
1095 if (n_outputs() != count) {
1096 need_pan_reset = true;
1099 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1101 const size_t n = count.get(*t);
1103 /* remove unused ports */
1104 for (size_t i = n_outputs().get(*t); i > n; --i) {
1105 output_port = _outputs.port(*t, i-1);
1107 assert(output_port);
1108 _outputs.remove(output_port);
1109 _session.engine().unregister_port (*output_port);
1114 /* create any necessary new ports */
1115 while (n_outputs().get(*t) < n) {
1119 if (_output_maximum.get(*t) == 1) {
1120 snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
1122 snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
1125 if ((output_port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
1126 error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
1130 _outputs.add (output_port);
1132 setup_peak_meters ();
1134 if (need_pan_reset) {
1141 check_bundles_connected_to_outputs ();
1142 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1143 _session.set_dirty ();
1147 /* disconnect all existing ports so that we get a fresh start */
1148 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1149 _session.engine().disconnect (*i);
1157 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1159 bool changed = false;
1161 if (_output_maximum < ChanCount::INFINITE) {
1162 count = min (_output_maximum, count);
1163 if (count == n_outputs() && !clear) {
1168 /* XXX caller should hold io_lock, but generally doesn't */
1171 BLOCK_PROCESS_CALLBACK ();
1172 Glib::Mutex::Lock im (io_lock);
1173 changed = ensure_outputs_locked (count, clear, src);
1175 changed = ensure_outputs_locked (count, clear, src);
1179 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1180 setup_bundles_for_inputs_and_outputs ();
1187 IO::effective_gain () const
1189 if (_gain_control->list()->automation_playback()) {
1190 return _gain_control->get_value();
1192 return _desired_gain;
1199 if (panners_legal) {
1200 if (!no_panner_reset) {
1201 _panner->reset (n_outputs().n_audio(), pans_required());
1204 panner_legal_c.disconnect ();
1205 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1210 IO::panners_became_legal ()
1212 _panner->reset (n_outputs().n_audio(), pans_required());
1213 _panner->load (); // automation
1214 panner_legal_c.disconnect ();
1219 IO::defer_pan_reset ()
1221 no_panner_reset = true;
1225 IO::allow_pan_reset ()
1227 no_panner_reset = false;
1233 IO::get_state (void)
1235 return state (true);
1239 IO::state (bool full_state)
1241 XMLNode* node = new XMLNode (state_node_name);
1244 LocaleGuard lg (X_("POSIX"));
1245 Glib::Mutex::Lock lm (io_lock);
1247 node->add_property("name", _name);
1248 id().print (buf, sizeof (buf));
1249 node->add_property("id", buf);
1252 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1253 i != _bundles_connected_to_inputs.end();
1257 XMLNode* n = new XMLNode ("InputBundle");
1258 n->add_property ("name", i->bundle->name ());
1259 node->add_child_nocopy (*n);
1263 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1264 i != _bundles_connected_to_outputs.end();
1268 XMLNode* n = new XMLNode ("OutputBundle");
1269 n->add_property ("name", i->bundle->name ());
1270 node->add_child_nocopy (*n);
1275 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1277 const char **connections = i->get_connections();
1279 if (connections && connections[0]) {
1282 for (int n = 0; connections && connections[n]; ++n) {
1287 /* if its a connection to our own port,
1288 return only the port name, not the
1289 whole thing. this allows connections
1290 to be re-established even when our
1291 client name is different.
1294 str += _session.engine().make_port_name_relative (connections[n]);
1306 node->add_property ("inputs", str);
1310 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1312 const char **connections = i->get_connections();
1314 if (connections && connections[0]) {
1318 for (int n = 0; connections[n]; ++n) {
1323 str += _session.engine().make_port_name_relative (connections[n]);
1335 node->add_property ("outputs", str);
1337 node->add_child_nocopy (_panner->state (full_state));
1338 node->add_child_nocopy (_gain_control->get_state ());
1340 snprintf (buf, sizeof(buf), "%2.12f", gain());
1341 node->add_property ("gain", buf);
1343 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1347 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1348 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1350 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1352 node->add_property ("iolimits", buf);
1357 node->add_child_nocopy (get_automation_state());
1363 IO::set_state (const XMLNode& node)
1365 const XMLProperty* prop;
1366 XMLNodeConstIterator iter;
1367 LocaleGuard lg (X_("POSIX"));
1369 /* force use of non-localized representation of decimal point,
1370 since we use it a lot in XML files and so forth.
1373 if (node.name() != state_node_name) {
1374 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1378 if ((prop = node.property ("name")) != 0) {
1379 _name = prop->value();
1380 /* used to set panner name with this, but no more */
1383 if ((prop = node.property ("id")) != 0) {
1384 _id = prop->value ();
1392 if ((prop = node.property ("iolimits")) != 0) {
1393 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1394 &in_min, &in_max, &out_min, &out_max);
1396 /* Correct for the difference between the way we write things to session files and the
1397 way things are described by ChanCount; see comments in io.h about what the different
1398 ChanCount values mean. */
1401 _input_minimum = ChanCount::ZERO;
1403 _input_minimum = ChanCount (_default_type, in_min);
1407 _input_maximum = ChanCount::INFINITE;
1409 _input_maximum = ChanCount (_default_type, in_max);
1413 _output_minimum = ChanCount::ZERO;
1415 _output_minimum = ChanCount (_default_type, out_min);
1419 _output_maximum = ChanCount::INFINITE;
1421 _output_maximum = ChanCount (_default_type, out_max);
1425 if ((prop = node.property ("gain")) != 0) {
1426 set_gain (atof (prop->value().c_str()), this);
1427 _gain = _desired_gain;
1430 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1431 /* old school automation handling */
1434 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1436 if ((*iter)->name() == "Panner") {
1438 _panner = new Panner (_name, _session);
1440 _panner->set_state (**iter);
1443 if ((*iter)->name() == X_("Automation")) {
1445 set_automation_state (*(*iter), Parameter(GainAutomation));
1448 if ((*iter)->name() == X_("controllable")) {
1449 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1450 _gain_control->set_state (**iter);
1457 if (create_ports (node)) {
1463 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1466 if (panners_legal) {
1469 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1472 if (connecting_legal) {
1474 if (make_connections (node)) {
1480 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1483 if (!ports_legal || !connecting_legal) {
1484 pending_state_node = new XMLNode (node);
1491 IO::load_automation (string path)
1496 uint32_t linecnt = 0;
1498 LocaleGuard lg (X_("POSIX"));
1500 fullpath = _session.automation_dir();
1503 in.open (fullpath.c_str());
1506 fullpath = _session.automation_dir();
1507 fullpath += _session.snap_name();
1511 in.open (fullpath.c_str());
1514 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1519 clear_automation ();
1521 while (in.getline (line, sizeof(line), '\n')) {
1526 if (++linecnt == 1) {
1527 if (memcmp (line, "version", 7) == 0) {
1528 if (sscanf (line, "version %f", &version) != 1) {
1529 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1533 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1540 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1541 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1547 _gain_control->list()->fast_simple_add (when, value);
1557 /* older (pre-1.0) versions of ardour used this */
1561 warning << _("dubious automation event found (and ignored)") << endmsg;
1569 IO::connecting_became_legal ()
1573 if (pending_state_node == 0) {
1574 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1579 connection_legal_c.disconnect ();
1581 ret = make_connections (*pending_state_node);
1584 delete pending_state_node;
1585 pending_state_node = 0;
1591 IO::ports_became_legal ()
1595 if (pending_state_node == 0) {
1596 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1601 port_legal_c.disconnect ();
1603 ret = create_ports (*pending_state_node);
1605 if (connecting_legal) {
1606 delete pending_state_node;
1607 pending_state_node = 0;
1614 IO::create_ports (const XMLNode& node)
1616 XMLProperty const * prop;
1618 int num_outputs = 0;
1620 if ((prop = node.property ("inputs")) != 0) {
1621 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1622 } else if ((prop = node.property ("outputs")) != 0) {
1623 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1626 no_panner_reset = true;
1628 // FIXME: audio-only
1629 if (ensure_io (ChanCount(DataType::AUDIO, num_inputs), ChanCount(DataType::AUDIO, num_outputs), true, this)) {
1630 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1634 no_panner_reset = false;
1636 set_deferred_state ();
1644 IO::make_connections (const XMLNode& node)
1646 XMLProperty const * prop;
1648 if ((prop = node.property ("inputs")) != 0) {
1649 if (set_inputs (prop->value())) {
1650 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1656 if ((prop = node.property ("outputs")) != 0) {
1657 if (set_outputs (prop->value())) {
1658 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1663 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1665 if ((*i)->name() == "InputBundle") {
1666 XMLProperty const * prop = (*i)->property ("name");
1668 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1670 connect_input_ports_to_bundle (b, this);
1672 error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
1676 } else if ((*i)->name() == "OutputBundle") {
1677 XMLProperty const * prop = (*i)->property ("name");
1679 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1681 connect_output_ports_to_bundle (b, this);
1683 error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
1693 IO::set_inputs (const string& str)
1695 vector<string> ports;
1700 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1704 // FIXME: audio-only
1705 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1709 string::size_type start, end, ostart;
1716 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1719 if ((end = str.find_first_of ('}', start)) == string::npos) {
1720 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1724 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1725 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1731 for (int x = 0; x < n; ++x) {
1732 connect_input (input (i), ports[x], this);
1744 IO::set_outputs (const string& str)
1746 vector<string> ports;
1751 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1755 // FIXME: audio-only
1756 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1760 string::size_type start, end, ostart;
1767 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1770 if ((end = str.find_first_of ('}', start)) == string::npos) {
1771 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1775 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1776 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1782 for (int x = 0; x < n; ++x) {
1783 connect_output (output (i), ports[x], this);
1795 IO::parse_io_string (const string& str, vector<string>& ports)
1797 string::size_type pos, opos;
1799 if (str.length() == 0) {
1808 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1809 ports.push_back (str.substr (opos, pos - opos));
1813 if (opos < str.length()) {
1814 ports.push_back (str.substr(opos));
1817 return ports.size();
1821 IO::parse_gain_string (const string& str, vector<string>& ports)
1823 string::size_type pos, opos;
1829 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1830 ports.push_back (str.substr (opos, pos - opos));
1834 if (opos < str.length()) {
1835 ports.push_back (str.substr(opos));
1838 return ports.size();
1842 IO::set_name (const string& str)
1848 /* replace all colons in the name. i wish we didn't have to do this */
1851 if (replace_all (name, ":", "-")) {
1852 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1855 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1856 string current_name = i->short_name();
1857 current_name.replace (current_name.find (_name), _name.length(), name);
1858 i->set_name (current_name);
1861 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1862 string current_name = i->short_name();
1863 current_name.replace (current_name.find (_name), _name.length(), name);
1864 i->set_name (current_name);
1867 bool const r = SessionObject::set_name(name);
1869 setup_bundles_for_inputs_and_outputs ();
1875 IO::set_input_minimum (ChanCount n)
1881 IO::set_input_maximum (ChanCount n)
1887 IO::set_output_minimum (ChanCount n)
1889 _output_minimum = n;
1893 IO::set_output_maximum (ChanCount n)
1895 _output_maximum = n;
1899 IO::set_port_latency (nframes_t nframes)
1901 Glib::Mutex::Lock lm (io_lock);
1903 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1904 i->set_latency (nframes);
1909 IO::output_latency () const
1911 nframes_t max_latency;
1916 /* io lock not taken - must be protected by other means */
1918 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1919 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1920 max_latency = latency;
1928 IO::input_latency () const
1930 nframes_t max_latency;
1935 /* io lock not taken - must be protected by other means */
1937 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1938 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1939 max_latency = latency;
1947 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1950 BLOCK_PROCESS_CALLBACK ();
1951 Glib::Mutex::Lock lm2 (io_lock);
1953 /* Connect to the bundle, not worrying about any connections
1954 that are already made. */
1956 uint32_t const channels = c->nchannels ();
1958 for (uint32_t n = 0; n < channels; ++n) {
1959 const PortList& pl = c->channel_ports (n);
1961 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
1963 if (!_inputs.port(n)->connected_to (*i)) {
1965 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
1973 /* If this is a UserBundle, make a note of what we've done */
1975 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1978 /* See if we already know about this one */
1979 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1980 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
1984 if (i == _bundles_connected_to_inputs.end()) {
1985 /* We don't, so make a note */
1986 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
1991 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
1996 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1999 BLOCK_PROCESS_CALLBACK ();
2000 Glib::Mutex::Lock lm2 (io_lock);
2002 /* Connect to the bundle, not worrying about any connections
2003 that are already made. */
2005 uint32_t const channels = c->nchannels ();
2007 for (uint32_t n = 0; n < channels; ++n) {
2009 const PortList& pl = c->channel_ports (n);
2011 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2013 if (!_outputs.port(n)->connected_to (*i)) {
2015 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2022 /* If this is a UserBundle, make a note of what we've done */
2024 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2027 /* See if we already know about this one */
2028 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2029 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2033 if (i == _bundles_connected_to_outputs.end()) {
2034 /* We don't, so make a note */
2035 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2040 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2046 IO::disable_connecting ()
2048 connecting_legal = false;
2053 IO::enable_connecting ()
2055 connecting_legal = true;
2056 return ConnectingLegal ();
2060 IO::disable_ports ()
2062 ports_legal = false;
2070 return PortsLegal ();
2074 IO::disable_panners (void)
2076 panners_legal = false;
2081 IO::reset_panners ()
2083 panners_legal = true;
2084 return PannersLegal ();
2088 IO::bundle_configuration_will_change ()
2091 // connect_input_ports_to_bundle (_input_bundle, this);
2095 IO::bundle_configuration_has_changed ()
2098 // connect_input_ports_to_bundle (_input_bundle, this);
2102 IO::bundle_ports_will_change (int ignored)
2105 // connect_output_ports_to_bundle (_output_bundle, this);
2109 IO::bundle_ports_have_changed (int ignored)
2112 // connect_output_ports_to_bundle (_output_bundle, this);
2116 IO::GainControl::set_value (float val)
2118 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2119 if (val > 1.99526231f)
2123 _io.set_gain (val, this);
2125 Changed(); /* EMIT SIGNAL */
2129 IO::GainControl::get_value (void) const
2131 return AutomationControl::get_value();
2135 IO::setup_peak_meters()
2137 ChanCount max_streams = std::max(_inputs.count(), _outputs.count());
2138 _meter->configure_io(max_streams, max_streams);
2142 Update the peak meters.
2144 The meter signal lock is taken to prevent modification of the
2145 Meter signal while updating the meters, taking the meter signal
2146 lock prior to taking the io_lock ensures that all IO will remain
2147 valid while metering.
2152 Glib::Mutex::Lock guard (m_meter_signal_lock);
2154 Meter(); /* EMIT SIGNAL */
2160 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2162 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2167 IO::clear_automation ()
2169 Automatable::clear_automation (); // clears gain automation
2170 _panner->clear_automation ();
2174 IO::set_parameter_automation_state (Parameter param, AutoState state)
2176 // XXX: would be nice to get rid of this special hack
2178 if (param.type() == GainAutomation) {
2180 bool changed = false;
2183 Glib::Mutex::Lock lm (_automation_lock);
2185 boost::shared_ptr<AutomationList> gain_auto = _gain_control->list();
2187 if (state != gain_auto->automation_state()) {
2189 _last_automation_snapshot = 0;
2190 gain_auto->set_automation_state (state);
2193 // FIXME: shouldn't this use Curve?
2194 set_gain (gain_auto->eval (_session.transport_frame()), this);
2200 _session.set_dirty ();
2204 Automatable::set_parameter_automation_state(param, state);
2209 IO::inc_gain (gain_t factor, void *src)
2211 if (_desired_gain == 0.0f)
2212 set_gain (0.000001f + (0.000001f * factor), src);
2214 set_gain (_desired_gain + (_desired_gain * factor), src);
2218 IO::set_gain (gain_t val, void *src)
2220 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2221 if (val > 1.99526231f)
2224 if (src != _gain_control.get()) {
2225 _gain_control->set_value(val);
2226 // bit twisty, this will come back and call us again
2227 // (this keeps control in sync with reality)
2232 Glib::Mutex::Lock dm (declick_lock);
2233 _desired_gain = val;
2236 if (_session.transport_stopped()) {
2240 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->list()->automation_write()) {
2241 _gain_control->list()->add (_session.transport_frame(), val);
2245 _session.set_dirty();
2249 IO::start_pan_touch (uint32_t which)
2251 if (which < _panner->size()) {
2252 (*_panner)[which]->pan_control()->list()->start_touch();
2257 IO::end_pan_touch (uint32_t which)
2259 if (which < _panner->size()) {
2260 (*_panner)[which]->pan_control()->list()->stop_touch();
2266 IO::automation_snapshot (nframes_t now)
2268 Automatable::automation_snapshot (now);
2270 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2271 _panner->snapshot (now);
2276 IO::transport_stopped (nframes_t frame)
2278 _gain_control->list()->reposition_for_rt_add (frame);
2280 if (_gain_control->list()->automation_state() != Off) {
2282 /* the src=0 condition is a special signal to not propagate
2283 automation gain changes into the mix group when locating.
2286 // FIXME: shouldn't this use Curve?
2287 set_gain (_gain_control->list()->eval (frame), 0);
2290 _panner->transport_stopped (frame);
2294 IO::find_input_port_hole ()
2296 /* CALLER MUST HOLD IO LOCK */
2300 if (_inputs.empty()) {
2304 for (n = 1; n < UINT_MAX; ++n) {
2305 char buf[jack_port_name_size()];
2306 PortSet::iterator i = _inputs.begin();
2308 snprintf (buf, jack_port_name_size(), _("%s/in %u"), _name.c_str(), n);
2310 for ( ; i != _inputs.end(); ++i) {
2311 if (i->short_name() == buf) {
2316 if (i == _inputs.end()) {
2324 IO::find_output_port_hole ()
2326 /* CALLER MUST HOLD IO LOCK */
2330 if (_outputs.empty()) {
2334 for (n = 1; n < UINT_MAX; ++n) {
2335 char buf[jack_port_name_size()];
2336 PortSet::iterator i = _outputs.begin();
2338 snprintf (buf, jack_port_name_size(), _("%s/out %u"), _name.c_str(), n);
2340 for ( ; i != _outputs.end(); ++i) {
2341 if (i->short_name() == buf) {
2346 if (i == _outputs.end()) {
2355 IO::audio_input(uint32_t n) const
2357 return dynamic_cast<AudioPort*>(input(n));
2361 IO::audio_output(uint32_t n) const
2363 return dynamic_cast<AudioPort*>(output(n));
2367 IO::midi_input(uint32_t n) const
2369 return dynamic_cast<MidiPort*>(input(n));
2373 IO::midi_output(uint32_t n) const
2375 return dynamic_cast<MidiPort*>(output(n));
2379 IO::set_phase_invert (bool yn, void *src)
2381 if (_phase_invert != yn) {
2383 // phase_invert_changed (src); /* EMIT SIGNAL */
2388 IO::set_denormal_protection (bool yn, void *src)
2390 if (_denormal_protection != yn) {
2391 _denormal_protection = yn;
2392 // denormal_protection_changed (src); /* EMIT SIGNAL */
2397 IO::update_port_total_latencies ()
2399 /* io_lock, not taken: function must be called from Session::process() calltree */
2401 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2402 _session.engine().update_total_latency (*i);
2405 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2406 _session.engine().update_total_latency (*i);
2412 * Setup bundles that describe our inputs and outputs.
2416 IO::setup_bundles_for_inputs_and_outputs ()
2420 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2421 _bundle_for_inputs->set_name (buf);
2422 uint32_t const ni = inputs().num_ports();
2423 _bundle_for_inputs->set_channels (ni);
2424 for (uint32_t i = 0; i < ni; ++i) {
2425 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2428 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2429 _bundle_for_outputs->set_name (buf);
2430 uint32_t const no = outputs().num_ports();
2431 _bundle_for_outputs->set_channels (no);
2432 for (uint32_t i = 0; i < no; ++i) {
2433 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2439 * Create and setup bundles that describe our inputs and outputs.
2443 IO::create_bundles_for_inputs_and_outputs ()
2445 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2446 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2447 setup_bundles_for_inputs_and_outputs ();
2450 /** Add a bundle to a list if is connected to our inputs.
2451 * @param b Bundle to check.
2452 * @param bundles List to add to.
2455 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2457 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2458 if (ab == 0 || ab->ports_are_outputs() == false) {
2462 if (ab->nchannels () != n_inputs().n_total ()) {
2466 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2468 PortList const & pl = b->channel_ports (i);
2474 if (!input(i)->connected_to (pl[0])) {
2479 bundles->push_back (b);
2482 /** @return Bundles connected to our inputs */
2483 std::vector<boost::shared_ptr<Bundle> >
2484 IO::bundles_connected_to_inputs ()
2486 std::vector<boost::shared_ptr<Bundle> > bundles;
2489 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2490 bundles.push_back (i->bundle);
2494 _session.foreach_bundle (
2495 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2502 /** Add a bundle to a list if is connected to our outputs.
2503 * @param b Bundle to check.
2504 * @param bundles List to add to.
2507 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2509 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2510 if (ab == 0 || ab->ports_are_inputs() == false) {
2514 if (ab->nchannels () != n_outputs().n_total ()) {
2518 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2520 PortList const & pl = b->channel_ports (i);
2526 if (!output(i)->connected_to (pl[0])) {
2531 bundles->push_back (b);
2535 /* @return Bundles connected to our outputs */
2536 std::vector<boost::shared_ptr<Bundle> >
2537 IO::bundles_connected_to_outputs ()
2539 std::vector<boost::shared_ptr<Bundle> > bundles;
2542 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2543 bundles.push_back (i->bundle);
2547 _session.foreach_bundle (
2548 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2555 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2558 configuration_will_change = b->ConfigurationWillChange.connect (
2559 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2561 configuration_has_changed = b->ConfigurationHasChanged.connect (
2562 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2564 ports_will_change = b->PortsWillChange.connect (
2565 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2567 ports_have_changed = b->PortsHaveChanged.connect (
2568 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)