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, bool public_ports)
103 : Automatable (s, name),
104 _output_buffers (new BufferSet()),
105 _default_type (default_type),
106 _public_ports (public_ports),
107 _input_minimum (ChanCount::ZERO),
108 _input_maximum (ChanCount::INFINITE),
109 _output_minimum (ChanCount::ZERO),
110 _output_maximum (ChanCount::INFINITE)
112 _panner = new Panner (name, _session);
113 _meter = new PeakMeter (_session);
116 _input_minimum = ChanCount(_default_type, input_min);
118 if (input_max >= 0) {
119 _input_maximum = ChanCount(_default_type, input_max);
121 if (output_min > 0) {
122 _output_minimum = ChanCount(_default_type, output_min);
124 if (output_max >= 0) {
125 _output_maximum = ChanCount(_default_type, output_max);
130 pending_state_node = 0;
131 no_panner_reset = false;
132 _phase_invert = false;
135 boost::shared_ptr<AutomationList> gl(
136 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
138 _gain_control = boost::shared_ptr<GainControl>(
139 new GainControl(X_("gaincontrol"), *this, gl));
141 add_control(_gain_control);
143 apply_gain_automation = false;
146 // IO::Meter is emitted from another thread so the
147 // Meter signal must be protected.
148 Glib::Mutex::Lock guard (m_meter_signal_lock);
149 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
152 // Connect to our own PortCountChanged signal to connect output buffers
153 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
155 _session.add_controllable (_gain_control);
157 create_bundles_for_inputs_and_outputs ();
160 IO::IO (Session& s, const XMLNode& node, DataType dt)
161 : Automatable (s, "unnamed io"),
162 _output_buffers (new BufferSet()),
165 _meter = new PeakMeter (_session);
166 _public_ports = true; // XXX get this from node
169 no_panner_reset = false;
173 apply_gain_automation = false;
175 boost::shared_ptr<AutomationList> gl(
176 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
178 _gain_control = boost::shared_ptr<GainControl>(
179 new GainControl(X_("gaincontrol"), *this, gl));
181 add_control(_gain_control);
186 // IO::Meter is emitted from another thread so the
187 // Meter signal must be protected.
188 Glib::Mutex::Lock guard (m_meter_signal_lock);
189 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
192 // Connect to our own PortCountChanged signal to connect output buffers
193 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
195 _session.add_controllable (_gain_control);
197 create_bundles_for_inputs_and_outputs ();
202 Glib::Mutex::Lock guard (m_meter_signal_lock);
203 Glib::Mutex::Lock lm (io_lock);
205 BLOCK_PROCESS_CALLBACK ();
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 output ports
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 (type, name, _public_ports)) == 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 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 (type, name, _public_ports)) == 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 (*t, buf, _public_ports)) == 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 (*t, buf, _public_ports)) == 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 (*t, buf, _public_ports)) == 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 (*t, buf, _public_ports)) == 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 vector<string>::iterator ci;
1246 LocaleGuard lg (X_("POSIX"));
1247 Glib::Mutex::Lock lm (io_lock);
1249 node->add_property("name", _name);
1250 id().print (buf, sizeof (buf));
1251 node->add_property("id", buf);
1254 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1255 i != _bundles_connected_to_inputs.end();
1259 XMLNode* n = new XMLNode ("InputBundle");
1260 n->add_property ("name", i->bundle->name ());
1261 node->add_child_nocopy (*n);
1265 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1266 i != _bundles_connected_to_outputs.end();
1270 XMLNode* n = new XMLNode ("OutputBundle");
1271 n->add_property ("name", i->bundle->name ());
1272 node->add_child_nocopy (*n);
1277 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1279 vector<string> connections;
1281 if (i->get_connections (connections)) {
1285 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1290 /* if its a connection to our own port,
1291 return only the port name, not the
1292 whole thing. this allows connections
1293 to be re-established even when our
1294 client name is different.
1297 str += _session.engine().make_port_name_relative (*ci);
1307 node->add_property ("inputs", str);
1311 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1313 vector<string> connections;
1315 if (i->get_connections (connections)) {
1319 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1324 str += _session.engine().make_port_name_relative (*ci);
1334 node->add_property ("outputs", str);
1336 node->add_child_nocopy (_panner->state (full_state));
1337 node->add_child_nocopy (_gain_control->get_state ());
1339 snprintf (buf, sizeof(buf), "%2.12f", gain());
1340 node->add_property ("gain", buf);
1342 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1346 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1347 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1349 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1351 node->add_property ("iolimits", buf);
1356 node->add_child_nocopy (get_automation_state());
1362 IO::set_state (const XMLNode& node)
1364 const XMLProperty* prop;
1365 XMLNodeConstIterator iter;
1366 LocaleGuard lg (X_("POSIX"));
1368 /* force use of non-localized representation of decimal point,
1369 since we use it a lot in XML files and so forth.
1372 if (node.name() != state_node_name) {
1373 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1377 if ((prop = node.property ("name")) != 0) {
1378 _name = prop->value();
1379 /* used to set panner name with this, but no more */
1382 if ((prop = node.property ("id")) != 0) {
1383 _id = prop->value ();
1391 if ((prop = node.property ("iolimits")) != 0) {
1392 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1393 &in_min, &in_max, &out_min, &out_max);
1395 /* Correct for the difference between the way we write things to session files and the
1396 way things are described by ChanCount; see comments in io.h about what the different
1397 ChanCount values mean. */
1400 _input_minimum = ChanCount::ZERO;
1402 _input_minimum = ChanCount (_default_type, in_min);
1406 _input_maximum = ChanCount::INFINITE;
1408 _input_maximum = ChanCount (_default_type, in_max);
1412 _output_minimum = ChanCount::ZERO;
1414 _output_minimum = ChanCount (_default_type, out_min);
1418 _output_maximum = ChanCount::INFINITE;
1420 _output_maximum = ChanCount (_default_type, out_max);
1424 if ((prop = node.property ("gain")) != 0) {
1425 set_gain (atof (prop->value().c_str()), this);
1426 _gain = _desired_gain;
1429 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1430 /* old school automation handling */
1433 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1435 if ((*iter)->name() == "Panner") {
1437 _panner = new Panner (_name, _session);
1439 _panner->set_state (**iter);
1442 if ((*iter)->name() == X_("Automation")) {
1444 set_automation_state (*(*iter), Parameter(GainAutomation));
1447 if ((*iter)->name() == X_("controllable")) {
1448 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1449 _gain_control->set_state (**iter);
1456 if (create_ports (node)) {
1462 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1465 if (panners_legal) {
1468 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1471 if (connecting_legal) {
1473 if (make_connections (node)) {
1479 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1482 if (!ports_legal || !connecting_legal) {
1483 pending_state_node = new XMLNode (node);
1490 IO::load_automation (string path)
1495 uint32_t linecnt = 0;
1497 LocaleGuard lg (X_("POSIX"));
1499 fullpath = _session.automation_dir();
1502 in.open (fullpath.c_str());
1505 fullpath = _session.automation_dir();
1506 fullpath += _session.snap_name();
1510 in.open (fullpath.c_str());
1513 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1518 clear_automation ();
1520 while (in.getline (line, sizeof(line), '\n')) {
1525 if (++linecnt == 1) {
1526 if (memcmp (line, "version", 7) == 0) {
1527 if (sscanf (line, "version %f", &version) != 1) {
1528 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1532 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1539 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1540 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1546 _gain_control->list()->fast_simple_add (when, value);
1556 /* older (pre-1.0) versions of ardour used this */
1560 warning << _("dubious automation event found (and ignored)") << endmsg;
1568 IO::connecting_became_legal ()
1572 if (pending_state_node == 0) {
1573 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1578 connection_legal_c.disconnect ();
1580 ret = make_connections (*pending_state_node);
1583 delete pending_state_node;
1584 pending_state_node = 0;
1590 IO::ports_became_legal ()
1594 if (pending_state_node == 0) {
1595 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1600 port_legal_c.disconnect ();
1602 ret = create_ports (*pending_state_node);
1604 if (connecting_legal) {
1605 delete pending_state_node;
1606 pending_state_node = 0;
1613 IO::create_ports (const XMLNode& node)
1615 XMLProperty const * prop;
1617 int num_outputs = 0;
1619 if ((prop = node.property ("inputs")) != 0) {
1620 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1621 } else if ((prop = node.property ("outputs")) != 0) {
1622 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1625 no_panner_reset = true;
1627 // FIXME: audio-only
1628 if (ensure_io (ChanCount(DataType::AUDIO, num_inputs), ChanCount(DataType::AUDIO, num_outputs), true, this)) {
1629 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1633 no_panner_reset = false;
1635 set_deferred_state ();
1643 IO::make_connections (const XMLNode& node)
1645 XMLProperty const * prop;
1647 if ((prop = node.property ("inputs")) != 0) {
1648 if (set_inputs (prop->value())) {
1649 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1655 if ((prop = node.property ("outputs")) != 0) {
1656 if (set_outputs (prop->value())) {
1657 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1662 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1664 if ((*i)->name() == "InputBundle") {
1665 XMLProperty const * prop = (*i)->property ("name");
1667 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1669 connect_input_ports_to_bundle (b, this);
1671 error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
1675 } else if ((*i)->name() == "OutputBundle") {
1676 XMLProperty const * prop = (*i)->property ("name");
1678 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1680 connect_output_ports_to_bundle (b, this);
1682 error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
1692 IO::set_inputs (const string& str)
1694 vector<string> ports;
1699 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1703 // FIXME: audio-only
1704 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1708 string::size_type start, end, ostart;
1715 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1718 if ((end = str.find_first_of ('}', start)) == string::npos) {
1719 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1723 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1724 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1730 for (int x = 0; x < n; ++x) {
1731 connect_input (input (i), ports[x], this);
1743 IO::set_outputs (const string& str)
1745 vector<string> ports;
1750 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1754 // FIXME: audio-only
1755 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1759 string::size_type start, end, ostart;
1766 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1769 if ((end = str.find_first_of ('}', start)) == string::npos) {
1770 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1774 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1775 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1781 for (int x = 0; x < n; ++x) {
1782 connect_output (output (i), ports[x], this);
1794 IO::parse_io_string (const string& str, vector<string>& ports)
1796 string::size_type pos, opos;
1798 if (str.length() == 0) {
1807 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1808 ports.push_back (str.substr (opos, pos - opos));
1812 if (opos < str.length()) {
1813 ports.push_back (str.substr(opos));
1816 return ports.size();
1820 IO::parse_gain_string (const string& str, vector<string>& ports)
1822 string::size_type pos, opos;
1828 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1829 ports.push_back (str.substr (opos, pos - opos));
1833 if (opos < str.length()) {
1834 ports.push_back (str.substr(opos));
1837 return ports.size();
1841 IO::set_name (const string& str)
1847 /* replace all colons in the name. i wish we didn't have to do this */
1850 if (replace_all (name, ":", "-")) {
1851 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1854 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1855 string current_name = i->short_name();
1856 current_name.replace (current_name.find (_name), _name.length(), name);
1857 i->set_name (current_name);
1860 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1861 string current_name = i->short_name();
1862 current_name.replace (current_name.find (_name), _name.length(), name);
1863 i->set_name (current_name);
1866 bool const r = SessionObject::set_name(name);
1868 setup_bundles_for_inputs_and_outputs ();
1874 IO::set_input_minimum (ChanCount n)
1880 IO::set_input_maximum (ChanCount n)
1886 IO::set_output_minimum (ChanCount n)
1888 _output_minimum = n;
1892 IO::set_output_maximum (ChanCount n)
1894 _output_maximum = n;
1898 IO::set_port_latency (nframes_t nframes)
1900 Glib::Mutex::Lock lm (io_lock);
1902 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1903 i->set_latency (nframes);
1908 IO::output_latency () const
1910 nframes_t max_latency;
1915 /* io lock not taken - must be protected by other means */
1917 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1918 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1919 max_latency = latency;
1927 IO::input_latency () const
1929 nframes_t max_latency;
1934 /* io lock not taken - must be protected by other means */
1936 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1937 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1938 max_latency = latency;
1946 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1949 BLOCK_PROCESS_CALLBACK ();
1950 Glib::Mutex::Lock lm2 (io_lock);
1952 /* Connect to the bundle, not worrying about any connections
1953 that are already made. */
1955 uint32_t const channels = c->nchannels ();
1957 for (uint32_t n = 0; n < channels; ++n) {
1958 const PortList& pl = c->channel_ports (n);
1960 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
1962 if (!_inputs.port(n)->connected_to (*i)) {
1964 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
1972 /* If this is a UserBundle, make a note of what we've done */
1974 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1977 /* See if we already know about this one */
1978 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1979 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
1983 if (i == _bundles_connected_to_inputs.end()) {
1984 /* We don't, so make a note */
1985 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
1990 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
1995 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1998 BLOCK_PROCESS_CALLBACK ();
1999 Glib::Mutex::Lock lm2 (io_lock);
2001 /* Connect to the bundle, not worrying about any connections
2002 that are already made. */
2004 uint32_t const channels = c->nchannels ();
2006 for (uint32_t n = 0; n < channels; ++n) {
2008 const PortList& pl = c->channel_ports (n);
2010 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2012 if (!_outputs.port(n)->connected_to (*i)) {
2014 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2021 /* If this is a UserBundle, make a note of what we've done */
2023 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2026 /* See if we already know about this one */
2027 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2028 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2032 if (i == _bundles_connected_to_outputs.end()) {
2033 /* We don't, so make a note */
2034 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2039 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2045 IO::disable_connecting ()
2047 connecting_legal = false;
2052 IO::enable_connecting ()
2054 connecting_legal = true;
2055 return ConnectingLegal ();
2059 IO::disable_ports ()
2061 ports_legal = false;
2069 return PortsLegal ();
2073 IO::disable_panners (void)
2075 panners_legal = false;
2080 IO::reset_panners ()
2082 panners_legal = true;
2083 return PannersLegal ();
2087 IO::bundle_configuration_will_change ()
2090 // connect_input_ports_to_bundle (_input_bundle, this);
2094 IO::bundle_configuration_has_changed ()
2097 // connect_input_ports_to_bundle (_input_bundle, this);
2101 IO::bundle_ports_will_change (int ignored)
2104 // connect_output_ports_to_bundle (_output_bundle, this);
2108 IO::bundle_ports_have_changed (int ignored)
2111 // connect_output_ports_to_bundle (_output_bundle, this);
2115 IO::GainControl::set_value (float val)
2117 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2118 if (val > 1.99526231f)
2122 _io.set_gain (val, this);
2124 Changed(); /* EMIT SIGNAL */
2128 IO::GainControl::get_value (void) const
2130 return AutomationControl::get_value();
2134 IO::setup_peak_meters()
2136 ChanCount max_streams = std::max(_inputs.count(), _outputs.count());
2137 _meter->configure_io(max_streams, max_streams);
2141 Update the peak meters.
2143 The meter signal lock is taken to prevent modification of the
2144 Meter signal while updating the meters, taking the meter signal
2145 lock prior to taking the io_lock ensures that all IO will remain
2146 valid while metering.
2151 Glib::Mutex::Lock guard (m_meter_signal_lock);
2153 Meter(); /* EMIT SIGNAL */
2159 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2161 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2166 IO::clear_automation ()
2168 Automatable::clear_automation (); // clears gain automation
2169 _panner->clear_automation ();
2173 IO::set_parameter_automation_state (Parameter param, AutoState state)
2175 // XXX: would be nice to get rid of this special hack
2177 if (param.type() == GainAutomation) {
2179 bool changed = false;
2182 Glib::Mutex::Lock lm (_automation_lock);
2184 boost::shared_ptr<AutomationList> gain_auto = _gain_control->list();
2186 if (state != gain_auto->automation_state()) {
2188 _last_automation_snapshot = 0;
2189 gain_auto->set_automation_state (state);
2192 // FIXME: shouldn't this use Curve?
2193 set_gain (gain_auto->eval (_session.transport_frame()), this);
2199 _session.set_dirty ();
2203 Automatable::set_parameter_automation_state(param, state);
2208 IO::inc_gain (gain_t factor, void *src)
2210 if (_desired_gain == 0.0f)
2211 set_gain (0.000001f + (0.000001f * factor), src);
2213 set_gain (_desired_gain + (_desired_gain * factor), src);
2217 IO::set_gain (gain_t val, void *src)
2219 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2220 if (val > 1.99526231f)
2223 if (src != _gain_control.get()) {
2224 _gain_control->set_value(val);
2225 // bit twisty, this will come back and call us again
2226 // (this keeps control in sync with reality)
2231 Glib::Mutex::Lock dm (declick_lock);
2232 _desired_gain = val;
2235 if (_session.transport_stopped()) {
2239 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->list()->automation_write()) {
2240 _gain_control->list()->add (_session.transport_frame(), val);
2244 _session.set_dirty();
2248 IO::start_pan_touch (uint32_t which)
2250 if (which < _panner->size()) {
2251 (*_panner)[which]->pan_control()->list()->start_touch();
2256 IO::end_pan_touch (uint32_t which)
2258 if (which < _panner->size()) {
2259 (*_panner)[which]->pan_control()->list()->stop_touch();
2265 IO::automation_snapshot (nframes_t now)
2267 Automatable::automation_snapshot (now);
2269 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2270 _panner->snapshot (now);
2275 IO::transport_stopped (nframes_t frame)
2277 _gain_control->list()->reposition_for_rt_add (frame);
2279 if (_gain_control->list()->automation_state() != Off) {
2281 /* the src=0 condition is a special signal to not propagate
2282 automation gain changes into the mix group when locating.
2285 // FIXME: shouldn't this use Curve?
2286 set_gain (_gain_control->list()->eval (frame), 0);
2289 _panner->transport_stopped (frame);
2293 IO::find_input_port_hole ()
2295 /* CALLER MUST HOLD IO LOCK */
2299 if (_inputs.empty()) {
2303 for (n = 1; n < UINT_MAX; ++n) {
2304 char buf[jack_port_name_size()];
2305 PortSet::iterator i = _inputs.begin();
2307 snprintf (buf, jack_port_name_size(), _("%s/in %u"), _name.c_str(), n);
2309 for ( ; i != _inputs.end(); ++i) {
2310 if (i->short_name() == buf) {
2315 if (i == _inputs.end()) {
2323 IO::find_output_port_hole ()
2325 /* CALLER MUST HOLD IO LOCK */
2329 if (_outputs.empty()) {
2333 for (n = 1; n < UINT_MAX; ++n) {
2334 char buf[jack_port_name_size()];
2335 PortSet::iterator i = _outputs.begin();
2337 snprintf (buf, jack_port_name_size(), _("%s/out %u"), _name.c_str(), n);
2339 for ( ; i != _outputs.end(); ++i) {
2340 if (i->short_name() == buf) {
2345 if (i == _outputs.end()) {
2354 IO::audio_input(uint32_t n) const
2356 return dynamic_cast<AudioPort*>(input(n));
2360 IO::audio_output(uint32_t n) const
2362 return dynamic_cast<AudioPort*>(output(n));
2366 IO::midi_input(uint32_t n) const
2368 return dynamic_cast<MidiPort*>(input(n));
2372 IO::midi_output(uint32_t n) const
2374 return dynamic_cast<MidiPort*>(output(n));
2378 IO::set_phase_invert (bool yn, void *src)
2380 if (_phase_invert != yn) {
2382 // phase_invert_changed (src); /* EMIT SIGNAL */
2387 IO::set_denormal_protection (bool yn, void *src)
2389 if (_denormal_protection != yn) {
2390 _denormal_protection = yn;
2391 // denormal_protection_changed (src); /* EMIT SIGNAL */
2396 IO::update_port_total_latencies ()
2398 /* io_lock, not taken: function must be called from Session::process() calltree */
2400 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2401 _session.engine().update_total_latency (*i);
2404 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2405 _session.engine().update_total_latency (*i);
2411 * Setup bundles that describe our inputs and outputs.
2415 IO::setup_bundles_for_inputs_and_outputs ()
2419 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2420 _bundle_for_inputs->set_name (buf);
2421 uint32_t const ni = inputs().num_ports();
2422 _bundle_for_inputs->set_channels (ni);
2423 for (uint32_t i = 0; i < ni; ++i) {
2424 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2427 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2428 _bundle_for_outputs->set_name (buf);
2429 uint32_t const no = outputs().num_ports();
2430 _bundle_for_outputs->set_channels (no);
2431 for (uint32_t i = 0; i < no; ++i) {
2432 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2438 * Create and setup bundles that describe our inputs and outputs.
2442 IO::create_bundles_for_inputs_and_outputs ()
2444 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2445 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2446 setup_bundles_for_inputs_and_outputs ();
2449 /** Add a bundle to a list if is connected to our inputs.
2450 * @param b Bundle to check.
2451 * @param bundles List to add to.
2454 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2456 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2457 if (ab == 0 || ab->ports_are_outputs() == false) {
2461 if (ab->nchannels () != n_inputs().n_total ()) {
2465 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2467 PortList const & pl = b->channel_ports (i);
2473 if (!input(i)->connected_to (pl[0])) {
2478 bundles->push_back (b);
2481 /** @return Bundles connected to our inputs */
2482 std::vector<boost::shared_ptr<Bundle> >
2483 IO::bundles_connected_to_inputs ()
2485 std::vector<boost::shared_ptr<Bundle> > bundles;
2488 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2489 bundles.push_back (i->bundle);
2493 _session.foreach_bundle (
2494 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2501 /** Add a bundle to a list if is connected to our outputs.
2502 * @param b Bundle to check.
2503 * @param bundles List to add to.
2506 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2508 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2509 if (ab == 0 || ab->ports_are_inputs() == false) {
2513 if (ab->nchannels () != n_outputs().n_total ()) {
2517 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2519 PortList const & pl = b->channel_ports (i);
2525 if (!output(i)->connected_to (pl[0])) {
2530 bundles->push_back (b);
2534 /* @return Bundles connected to our outputs */
2535 std::vector<boost::shared_ptr<Bundle> >
2536 IO::bundles_connected_to_outputs ()
2538 std::vector<boost::shared_ptr<Bundle> > bundles;
2541 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2542 bundles.push_back (i->bundle);
2546 _session.foreach_bundle (
2547 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2554 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2557 configuration_will_change = b->ConfigurationWillChange.connect (
2558 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2560 configuration_has_changed = b->ConfigurationHasChanged.connect (
2561 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2563 ports_will_change = b->PortsWillChange.connect (
2564 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2566 ports_have_changed = b->PortsHaveChanged.connect (
2567 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)