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()),
106 _default_type (default_type),
107 _public_ports (public_ports),
108 _input_minimum (ChanCount::ZERO),
109 _input_maximum (ChanCount::INFINITE),
110 _output_minimum (ChanCount::ZERO),
111 _output_maximum (ChanCount::INFINITE)
113 _panner = new Panner (name, _session);
114 _meter = new PeakMeter (_session);
117 _input_minimum = ChanCount(_default_type, input_min);
119 if (input_max >= 0) {
120 _input_maximum = ChanCount(_default_type, input_max);
122 if (output_min > 0) {
123 _output_minimum = ChanCount(_default_type, output_min);
125 if (output_max >= 0) {
126 _output_maximum = ChanCount(_default_type, output_max);
131 pending_state_node = 0;
132 no_panner_reset = false;
133 _phase_invert = false;
136 boost::shared_ptr<AutomationList> gl(
137 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
139 _gain_control = boost::shared_ptr<GainControl>(
140 new GainControl(X_("gaincontrol"), *this, gl));
142 add_control(_gain_control);
144 apply_gain_automation = false;
147 // IO::Meter is emitted from another thread so the
148 // Meter signal must be protected.
149 Glib::Mutex::Lock guard (m_meter_signal_lock);
150 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
153 // Connect to our own PortCountChanged signal to connect output buffers
154 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
156 _session.add_controllable (_gain_control);
158 create_bundles_for_inputs_and_outputs ();
161 IO::IO (Session& s, const XMLNode& node, DataType dt)
162 : Automatable (s, "unnamed io"),
163 _output_buffers (new BufferSet()),
166 _meter = new PeakMeter (_session);
167 _public_ports = true; // XXX get this from node
170 no_panner_reset = false;
174 apply_gain_automation = false;
176 boost::shared_ptr<AutomationList> gl(
177 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
179 _gain_control = boost::shared_ptr<GainControl>(
180 new GainControl(X_("gaincontrol"), *this, gl));
182 add_control(_gain_control);
187 // IO::Meter is emitted from another thread so the
188 // Meter signal must be protected.
189 Glib::Mutex::Lock guard (m_meter_signal_lock);
190 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
193 // Connect to our own PortCountChanged signal to connect output buffers
194 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
196 _session.add_controllable (_gain_control);
198 create_bundles_for_inputs_and_outputs ();
203 Glib::Mutex::Lock guard (m_meter_signal_lock);
204 Glib::Mutex::Lock lm (io_lock);
206 BLOCK_PROCESS_CALLBACK ();
208 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
209 _session.engine().unregister_port (*i);
212 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
213 _session.engine().unregister_port (*i);
216 m_meter_connection.disconnect();
220 delete _output_buffers;
224 IO::silence (nframes_t nframes, nframes_t offset)
226 /* io_lock, not taken: function must be called from Session::process() calltree */
228 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
229 i->get_buffer().silence (nframes, offset);
233 /** Deliver bufs to the IO's output ports
235 * This function should automatically do whatever it necessary to correctly deliver bufs
236 * to the outputs, eg applying gain or pan or whatever else needs to be done.
239 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
241 // FIXME: type specific code doesn't actually need to be here, it will go away in time
243 /* ********** AUDIO ********** */
245 // Apply gain if gain automation isn't playing
246 if ( ! apply_gain_automation) {
248 gain_t dg = _gain; // desired gain
251 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
259 if (dg != _gain || dg != 1.0)
260 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
263 // Use the panner to distribute audio to output port buffers
264 if (_panner && !_panner->empty() && !_panner->bypassed()) {
265 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
267 const DataType type = DataType::AUDIO;
269 // Copy any audio 1:1 to outputs
271 BufferSet::iterator o = output_buffers().begin(type);
272 BufferSet::iterator i = bufs.begin(type);
273 BufferSet::iterator prev = i;
275 while (i != bufs.end(type) && o != output_buffers().end (type)) {
276 o->read_from(*i, nframes, offset);
282 /* extra outputs get a copy of the last buffer */
284 while (o != output_buffers().end(type)) {
285 o->read_from(*prev, nframes, offset);
290 /* ********** MIDI ********** */
292 // No MIDI, we're done here
293 if (bufs.count().n_midi() == 0) {
297 const DataType type = DataType::MIDI;
299 // Copy any MIDI 1:1 to outputs
300 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
301 BufferSet::iterator o = output_buffers().begin(type);
302 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
303 o->read_from(*i, nframes, offset);
308 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
310 assert(outs.available() >= n_inputs());
312 if (n_inputs() == ChanCount::ZERO)
315 outs.set_count(n_inputs());
317 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
319 BufferSet::iterator o = outs.begin(*t);
320 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
321 o->read_from(i->get_buffer(), nframes, offset);
328 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
329 nframes_t nframes, nframes_t offset)
331 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
333 collect_input (bufs, nframes, offset);
335 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
340 IO::check_bundles_connected_to_inputs ()
342 check_bundles (_bundles_connected_to_inputs, inputs());
346 IO::check_bundles_connected_to_outputs ()
348 check_bundles (_bundles_connected_to_outputs, outputs());
352 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
354 std::vector<UserBundleInfo> new_list;
356 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
358 uint32_t const N = i->bundle->nchannels ();
360 if (ports.num_ports() < N) {
365 for (uint32_t j = 0; j < N; ++j) {
366 /* Every port on bundle channel j must be connected to our input j */
367 PortList const pl = i->bundle->channel_ports (j);
368 for (uint32_t k = 0; k < pl.size(); ++k) {
369 if (ports.port(j)->connected_to (pl[k]) == false) {
381 new_list.push_back (*i);
383 i->configuration_will_change.disconnect ();
384 i->configuration_has_changed.disconnect ();
385 i->ports_will_change.disconnect ();
386 i->ports_have_changed.disconnect ();
395 IO::disconnect_input (Port* our_port, string other_port, void* src)
397 if (other_port.length() == 0 || our_port == 0) {
402 BLOCK_PROCESS_CALLBACK ();
405 Glib::Mutex::Lock lm (io_lock);
407 /* check that our_port is really one of ours */
409 if ( ! _inputs.contains(our_port)) {
413 /* disconnect it from the source */
415 if (_session.engine().disconnect (other_port, our_port->name())) {
416 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
420 check_bundles_connected_to_inputs ();
424 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
425 _session.set_dirty ();
431 IO::connect_input (Port* our_port, string other_port, void* src)
433 if (other_port.length() == 0 || our_port == 0) {
438 BLOCK_PROCESS_CALLBACK ();
441 Glib::Mutex::Lock lm (io_lock);
443 /* check that our_port is really one of ours */
445 if ( ! _inputs.contains(our_port) ) {
449 /* connect it to the source */
451 if (_session.engine().connect (other_port, our_port->name())) {
457 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
458 _session.set_dirty ();
463 IO::disconnect_output (Port* our_port, string other_port, void* src)
465 if (other_port.length() == 0 || our_port == 0) {
470 BLOCK_PROCESS_CALLBACK ();
473 Glib::Mutex::Lock lm (io_lock);
475 /* check that our_port is really one of ours */
477 if ( ! _outputs.contains(our_port) ) {
481 /* disconnect it from the destination */
483 if (_session.engine().disconnect (our_port->name(), other_port)) {
484 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
488 check_bundles_connected_to_outputs ();
492 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
493 _session.set_dirty ();
498 IO::connect_output (Port* our_port, string other_port, void* src)
500 if (other_port.length() == 0 || our_port == 0) {
505 BLOCK_PROCESS_CALLBACK ();
509 Glib::Mutex::Lock lm (io_lock);
511 /* check that our_port is really one of ours */
513 if ( ! _outputs.contains(our_port) ) {
517 /* connect it to the destination */
519 if (_session.engine().connect (our_port->name(), other_port)) {
525 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
526 _session.set_dirty ();
531 IO::set_input (Port* other_port, void* src)
533 /* this removes all but one ports, and connects that one port
534 to the specified source.
537 if (_input_minimum.n_total() > 1) {
538 /* sorry, you can't do this */
542 if (other_port == 0) {
543 if (_input_minimum == ChanCount::ZERO) {
544 return ensure_inputs (ChanCount::ZERO, false, true, src);
550 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
554 return connect_input (_inputs.port(0), other_port->name(), src);
558 IO::remove_output_port (Port* port, void* src)
560 IOChange change (NoChange);
563 BLOCK_PROCESS_CALLBACK ();
567 Glib::Mutex::Lock lm (io_lock);
569 if (n_outputs() <= _output_minimum) {
570 /* sorry, you can't do this */
574 if (_outputs.remove(port)) {
575 change = IOChange (change|ConfigurationChanged);
577 if (port->connected()) {
578 change = IOChange (change|ConnectionsChanged);
581 _session.engine().unregister_port (*port);
582 check_bundles_connected_to_outputs ();
584 setup_peak_meters ();
589 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
592 if (change == ConnectionsChanged) {
593 setup_bundles_for_inputs_and_outputs ();
596 if (change != NoChange) {
597 output_changed (change, src);
598 _session.set_dirty ();
605 /** Add an output port.
607 * @param destination Name of input port to connect new port to.
608 * @param src Source for emitted ConfigurationChanged signal.
609 * @param type Data type of port. Default value (NIL) will use this IO's default type.
612 IO::add_output_port (string destination, void* src, DataType type)
617 if (type == DataType::NIL)
618 type = _default_type;
621 BLOCK_PROCESS_CALLBACK ();
625 Glib::Mutex::Lock lm (io_lock);
627 if (n_outputs() >= _output_maximum) {
631 /* Create a new output port */
633 // FIXME: naming scheme for differently typed ports?
634 if (_output_maximum.get(type) == 1) {
635 snprintf (name, sizeof (name), _("%s/out"), _name.c_str());
637 snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
640 if ((our_port = _session.engine().register_output_port (type, name, _public_ports)) == 0) {
641 error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
645 _outputs.add (our_port);
646 setup_peak_meters ();
650 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
653 if (destination.length()) {
654 if (_session.engine().connect (our_port->name(), destination)) {
659 // pan_changed (src); /* EMIT SIGNAL */
660 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
661 setup_bundles_for_inputs_and_outputs ();
662 _session.set_dirty ();
668 IO::remove_input_port (Port* port, void* src)
670 IOChange change (NoChange);
673 BLOCK_PROCESS_CALLBACK ();
677 Glib::Mutex::Lock lm (io_lock);
679 if (n_inputs() <= _input_minimum) {
680 /* sorry, you can't do this */
684 if (_inputs.remove(port)) {
685 change = IOChange (change|ConfigurationChanged);
687 if (port->connected()) {
688 change = IOChange (change|ConnectionsChanged);
691 _session.engine().unregister_port (*port);
692 check_bundles_connected_to_inputs ();
694 setup_peak_meters ();
699 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
702 if (change == ConfigurationChanged) {
703 setup_bundles_for_inputs_and_outputs ();
706 if (change != NoChange) {
707 input_changed (change, src);
708 _session.set_dirty ();
716 /** Add an input port.
718 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
719 * @param destination Name of input port to connect new port to.
720 * @param src Source for emitted ConfigurationChanged signal.
723 IO::add_input_port (string source, void* src, DataType type)
728 if (type == DataType::NIL)
729 type = _default_type;
732 BLOCK_PROCESS_CALLBACK ();
735 Glib::Mutex::Lock lm (io_lock);
737 if (n_inputs() >= _input_maximum) {
741 /* Create a new input port */
743 // FIXME: naming scheme for differently typed ports?
744 if (_input_maximum.get(type) == 1) {
745 snprintf (name, sizeof (name), _("%s/in"), _name.c_str());
747 snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
750 if ((our_port = _session.engine().register_input_port (type, name, _public_ports)) == 0) {
751 error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
755 _inputs.add (our_port);
756 setup_peak_meters ();
760 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
763 if (source.length()) {
765 if (_session.engine().connect (source, our_port->name())) {
770 // pan_changed (src); /* EMIT SIGNAL */
771 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
772 setup_bundles_for_inputs_and_outputs ();
773 _session.set_dirty ();
779 IO::disconnect_inputs (void* src)
782 BLOCK_PROCESS_CALLBACK ();
785 Glib::Mutex::Lock lm (io_lock);
787 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
788 _session.engine().disconnect (*i);
791 check_bundles_connected_to_inputs ();
795 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
801 IO::disconnect_outputs (void* src)
804 BLOCK_PROCESS_CALLBACK ();
807 Glib::Mutex::Lock lm (io_lock);
809 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
810 _session.engine().disconnect (*i);
813 check_bundles_connected_to_outputs ();
817 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
818 _session.set_dirty ();
824 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
826 Port* input_port = 0;
827 bool changed = false;
830 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
832 const size_t n = count.get(*t);
834 /* remove unused ports */
835 for (size_t i = n_inputs().get(*t); i > n; --i) {
836 input_port = _inputs.port(*t, i-1);
839 _inputs.remove(input_port);
840 _session.engine().unregister_port (*input_port);
845 /* create any necessary new ports */
846 while (n_inputs().get(*t) < n) {
850 if (_input_maximum.get(*t) == 1) {
851 snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
853 snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
858 if ((input_port = _session.engine().register_input_port (*t, buf, _public_ports)) == 0) {
859 error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
864 catch (AudioEngine::PortRegistrationFailure& err) {
865 setup_peak_meters ();
868 throw AudioEngine::PortRegistrationFailure();
871 _inputs.add (input_port);
877 check_bundles_connected_to_inputs ();
878 setup_peak_meters ();
880 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
881 _session.set_dirty ();
885 /* disconnect all existing ports so that we get a fresh start */
886 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
887 _session.engine().disconnect (*i);
894 /** Attach output_buffers to port buffers.
896 * Connected to IO's own PortCountChanged signal.
899 IO::attach_buffers(ChanCount ignored)
901 _output_buffers->attach_buffers(_outputs);
905 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
907 bool in_changed = false;
908 bool out_changed = false;
909 bool need_pan_reset = false;
911 in = min (_input_maximum, in);
913 out = min (_output_maximum, out);
915 if (in == n_inputs() && out == n_outputs() && !clear) {
920 BLOCK_PROCESS_CALLBACK ();
921 Glib::Mutex::Lock lm (io_lock);
925 if (n_outputs() != out) {
926 need_pan_reset = true;
929 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
931 const size_t nin = in.get(*t);
932 const size_t nout = out.get(*t);
934 Port* output_port = 0;
935 Port* input_port = 0;
937 /* remove unused output ports */
938 for (size_t i = n_outputs().get(*t); i > nout; --i) {
939 output_port = _outputs.port(*t, i-1);
942 _outputs.remove(output_port);
943 _session.engine().unregister_port (*output_port);
948 /* remove unused input ports */
949 for (size_t i = n_inputs().get(*t); i > nin; --i) {
950 input_port = _inputs.port(*t, i-1);
953 _inputs.remove(input_port);
954 _session.engine().unregister_port (*input_port);
959 /* create any necessary new input ports */
961 while (n_inputs().get(*t) < nin) {
965 /* Create a new input port */
967 if (_input_maximum.get(*t) == 1) {
968 snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str());
970 snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole());
974 if ((port = _session.engine().register_input_port (*t, buf, _public_ports)) == 0) {
975 error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
980 catch (AudioEngine::PortRegistrationFailure& err) {
981 setup_peak_meters ();
984 throw AudioEngine::PortRegistrationFailure();
991 /* create any necessary new output ports */
993 while (n_outputs().get(*t) < nout) {
997 /* Create a new output port */
999 if (_output_maximum.get(*t) == 1) {
1000 snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
1002 snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
1006 if ((port = _session.engine().register_output_port (*t, buf, _public_ports)) == 0) {
1007 error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
1012 catch (AudioEngine::PortRegistrationFailure& err) {
1013 setup_peak_meters ();
1016 throw AudioEngine::PortRegistrationFailure ();
1019 _outputs.add (port);
1026 /* disconnect all existing ports so that we get a fresh start */
1028 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1029 _session.engine().disconnect (*i);
1032 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1033 _session.engine().disconnect (*i);
1037 if (in_changed || out_changed) {
1038 setup_peak_meters ();
1044 check_bundles_connected_to_outputs ();
1045 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1049 check_bundles_connected_to_inputs ();
1050 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1053 if (in_changed || out_changed) {
1054 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1055 setup_bundles_for_inputs_and_outputs ();
1056 _session.set_dirty ();
1063 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1065 bool changed = false;
1067 count = min (_input_maximum, count);
1069 if (count == n_inputs() && !clear) {
1074 BLOCK_PROCESS_CALLBACK ();
1075 Glib::Mutex::Lock im (io_lock);
1076 changed = ensure_inputs_locked (count, clear, src);
1078 changed = ensure_inputs_locked (count, clear, src);
1082 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1083 setup_bundles_for_inputs_and_outputs ();
1084 _session.set_dirty ();
1090 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1092 Port* output_port = 0;
1093 bool changed = false;
1094 bool need_pan_reset = false;
1096 if (n_outputs() != count) {
1097 need_pan_reset = true;
1100 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1102 const size_t n = count.get(*t);
1104 /* remove unused ports */
1105 for (size_t i = n_outputs().get(*t); i > n; --i) {
1106 output_port = _outputs.port(*t, i-1);
1108 assert(output_port);
1109 _outputs.remove(output_port);
1110 _session.engine().unregister_port (*output_port);
1115 /* create any necessary new ports */
1116 while (n_outputs().get(*t) < n) {
1120 if (_output_maximum.get(*t) == 1) {
1121 snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str());
1123 snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
1126 if ((output_port = _session.engine().register_output_port (*t, buf, _public_ports)) == 0) {
1127 error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
1131 _outputs.add (output_port);
1133 setup_peak_meters ();
1135 if (need_pan_reset) {
1142 check_bundles_connected_to_outputs ();
1143 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1144 _session.set_dirty ();
1148 /* disconnect all existing ports so that we get a fresh start */
1149 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1150 _session.engine().disconnect (*i);
1158 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1160 bool changed = false;
1162 if (_output_maximum < ChanCount::INFINITE) {
1163 count = min (_output_maximum, count);
1164 if (count == n_outputs() && !clear) {
1169 /* XXX caller should hold io_lock, but generally doesn't */
1172 BLOCK_PROCESS_CALLBACK ();
1173 Glib::Mutex::Lock im (io_lock);
1174 changed = ensure_outputs_locked (count, clear, src);
1176 changed = ensure_outputs_locked (count, clear, src);
1180 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1181 setup_bundles_for_inputs_and_outputs ();
1188 IO::effective_gain () const
1190 if (_gain_control->list()->automation_playback()) {
1191 return _gain_control->get_value();
1193 return _desired_gain;
1200 if (panners_legal) {
1201 if (!no_panner_reset) {
1202 _panner->reset (n_outputs().n_audio(), pans_required());
1205 panner_legal_c.disconnect ();
1206 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1211 IO::panners_became_legal ()
1213 _panner->reset (n_outputs().n_audio(), pans_required());
1214 _panner->load (); // automation
1215 panner_legal_c.disconnect ();
1220 IO::defer_pan_reset ()
1222 no_panner_reset = true;
1226 IO::allow_pan_reset ()
1228 no_panner_reset = false;
1234 IO::get_state (void)
1236 return state (true);
1240 IO::state (bool full_state)
1242 XMLNode* node = new XMLNode (state_node_name);
1245 vector<string>::iterator ci;
1247 LocaleGuard lg (X_("POSIX"));
1248 Glib::Mutex::Lock lm (io_lock);
1250 node->add_property("name", _name);
1251 id().print (buf, sizeof (buf));
1252 node->add_property("id", buf);
1255 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1256 i != _bundles_connected_to_inputs.end();
1260 XMLNode* n = new XMLNode ("InputBundle");
1261 n->add_property ("name", i->bundle->name ());
1262 node->add_child_nocopy (*n);
1266 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1267 i != _bundles_connected_to_outputs.end();
1271 XMLNode* n = new XMLNode ("OutputBundle");
1272 n->add_property ("name", i->bundle->name ());
1273 node->add_child_nocopy (*n);
1278 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1280 vector<string> connections;
1282 if (i->get_connections (connections)) {
1286 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1291 /* if its a connection to our own port,
1292 return only the port name, not the
1293 whole thing. this allows connections
1294 to be re-established even when our
1295 client name is different.
1298 str += _session.engine().make_port_name_relative (*ci);
1308 node->add_property ("inputs", str);
1312 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1314 vector<string> connections;
1316 if (i->get_connections (connections)) {
1320 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1325 str += _session.engine().make_port_name_relative (*ci);
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::set_active (bool yn)
2358 active_changed(); /* EMIT SIGNAL */
2363 IO::audio_input(uint32_t n) const
2365 return dynamic_cast<AudioPort*>(input(n));
2369 IO::audio_output(uint32_t n) const
2371 return dynamic_cast<AudioPort*>(output(n));
2375 IO::midi_input(uint32_t n) const
2377 return dynamic_cast<MidiPort*>(input(n));
2381 IO::midi_output(uint32_t n) const
2383 return dynamic_cast<MidiPort*>(output(n));
2387 IO::set_phase_invert (bool yn, void *src)
2389 if (_phase_invert != yn) {
2391 // phase_invert_changed (src); /* EMIT SIGNAL */
2396 IO::set_denormal_protection (bool yn, void *src)
2398 if (_denormal_protection != yn) {
2399 _denormal_protection = yn;
2400 // denormal_protection_changed (src); /* EMIT SIGNAL */
2405 IO::update_port_total_latencies ()
2407 /* io_lock, not taken: function must be called from Session::process() calltree */
2409 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2410 _session.engine().update_total_latency (*i);
2413 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2414 _session.engine().update_total_latency (*i);
2420 * Setup bundles that describe our inputs and outputs.
2424 IO::setup_bundles_for_inputs_and_outputs ()
2428 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2429 _bundle_for_inputs->set_name (buf);
2430 uint32_t const ni = inputs().num_ports();
2431 _bundle_for_inputs->set_channels (ni);
2432 for (uint32_t i = 0; i < ni; ++i) {
2433 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2436 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2437 _bundle_for_outputs->set_name (buf);
2438 uint32_t const no = outputs().num_ports();
2439 _bundle_for_outputs->set_channels (no);
2440 for (uint32_t i = 0; i < no; ++i) {
2441 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2447 * Create and setup bundles that describe our inputs and outputs.
2451 IO::create_bundles_for_inputs_and_outputs ()
2453 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2454 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2455 setup_bundles_for_inputs_and_outputs ();
2458 /** Add a bundle to a list if is connected to our inputs.
2459 * @param b Bundle to check.
2460 * @param bundles List to add to.
2463 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2465 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2466 if (ab == 0 || ab->ports_are_outputs() == false) {
2470 if (ab->nchannels () != n_inputs().n_total ()) {
2474 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2476 PortList const & pl = b->channel_ports (i);
2482 if (!input(i)->connected_to (pl[0])) {
2487 bundles->push_back (b);
2490 /** @return Bundles connected to our inputs */
2491 std::vector<boost::shared_ptr<Bundle> >
2492 IO::bundles_connected_to_inputs ()
2494 std::vector<boost::shared_ptr<Bundle> > bundles;
2497 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2498 bundles.push_back (i->bundle);
2502 _session.foreach_bundle (
2503 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2510 /** Add a bundle to a list if is connected to our outputs.
2511 * @param b Bundle to check.
2512 * @param bundles List to add to.
2515 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2517 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2518 if (ab == 0 || ab->ports_are_inputs() == false) {
2522 if (ab->nchannels () != n_outputs().n_total ()) {
2526 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2528 PortList const & pl = b->channel_ports (i);
2534 if (!output(i)->connected_to (pl[0])) {
2539 bundles->push_back (b);
2543 /* @return Bundles connected to our outputs */
2544 std::vector<boost::shared_ptr<Bundle> >
2545 IO::bundles_connected_to_outputs ()
2547 std::vector<boost::shared_ptr<Bundle> > bundles;
2550 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2551 bundles.push_back (i->bundle);
2555 _session.foreach_bundle (
2556 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2563 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2566 configuration_will_change = b->ConfigurationWillChange.connect (
2567 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2569 configuration_has_changed = b->ConfigurationHasChanged.connect (
2570 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2572 ports_will_change = b->PortsWillChange.connect (
2573 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2575 ports_have_changed = b->PortsHaveChanged.connect (
2576 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)