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>
28 #include <glibmm/thread.h>
30 #include <pbd/xml++.h>
31 #include <pbd/replace_all.h>
32 #include <pbd/unknown_type.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/io.h>
36 #include <ardour/route.h>
37 #include <ardour/port.h>
38 #include <ardour/audio_port.h>
39 #include <ardour/midi_port.h>
40 #include <ardour/auto_bundle.h>
41 #include <ardour/session.h>
42 #include <ardour/cycle_timer.h>
43 #include <ardour/panner.h>
44 #include <ardour/buffer_set.h>
45 #include <ardour/meter.h>
46 #include <ardour/amp.h>
53 A bug in OS X's cmath that causes isnan() and isinf() to be
54 "undeclared". the following works around that
57 #if defined(__APPLE__) && defined(__MACH__)
58 extern "C" int isnan (double);
59 extern "C" int isinf (double);
62 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
65 using namespace ARDOUR;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,ChanCount> IO::PortCountChanged;
77 sigc::signal<int> IO::PortsCreated;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
100 /** @param default_type The type of port that will be created by ensure_io
101 * and friends if no type is explicitly requested (to avoid breakage).
103 IO::IO (Session& s, const string& name,
104 int input_min, int input_max, int output_min, int output_max,
105 DataType default_type, bool public_ports)
106 : Automatable (s, name),
107 _output_buffers (new BufferSet()),
109 _default_type (default_type),
110 _public_ports (public_ports),
111 _input_minimum (ChanCount::ZERO),
112 _input_maximum (ChanCount::INFINITE),
113 _output_minimum (ChanCount::ZERO),
114 _output_maximum (ChanCount::INFINITE)
116 _panner = new Panner (name, _session);
117 _meter = new PeakMeter (_session);
120 _input_minimum = ChanCount(_default_type, input_min);
122 if (input_max >= 0) {
123 _input_maximum = ChanCount(_default_type, input_max);
125 if (output_min > 0) {
126 _output_minimum = ChanCount(_default_type, output_min);
128 if (output_max >= 0) {
129 _output_maximum = ChanCount(_default_type, output_max);
134 pending_state_node = 0;
135 no_panner_reset = false;
136 _phase_invert = false;
139 boost::shared_ptr<AutomationList> gl(
140 new AutomationList(Parameter(GainAutomation)));
142 _gain_control = boost::shared_ptr<GainControl>(
143 new GainControl(X_("gaincontrol"), *this, gl));
145 add_control(_gain_control);
147 apply_gain_automation = false;
150 // IO::Meter is emitted from another thread so the
151 // Meter signal must be protected.
152 Glib::Mutex::Lock guard (m_meter_signal_lock);
153 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
156 // Connect to our own PortCountChanged signal to connect output buffers
157 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
159 _session.add_controllable (_gain_control);
161 create_bundles_for_inputs_and_outputs ();
164 IO::IO (Session& s, const XMLNode& node, DataType dt)
165 : Automatable (s, "unnamed io"),
166 _output_buffers (new BufferSet()),
170 _meter = new PeakMeter (_session);
171 _public_ports = true; // XXX get this from node
174 no_panner_reset = false;
178 apply_gain_automation = false;
180 boost::shared_ptr<AutomationList> gl(
181 new AutomationList(Parameter(GainAutomation)));
183 _gain_control = boost::shared_ptr<GainControl>(
184 new GainControl(X_("gaincontrol"), *this, gl));
186 add_control(_gain_control);
191 // IO::Meter is emitted from another thread so the
192 // Meter signal must be protected.
193 Glib::Mutex::Lock guard (m_meter_signal_lock);
194 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
197 // Connect to our own PortCountChanged signal to connect output buffers
198 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
200 _session.add_controllable (_gain_control);
202 create_bundles_for_inputs_and_outputs ();
207 Glib::Mutex::Lock guard (m_meter_signal_lock);
208 Glib::Mutex::Lock lm (io_lock);
210 BLOCK_PROCESS_CALLBACK ();
212 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
213 _session.engine().unregister_port (*i);
216 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
217 _session.engine().unregister_port (*i);
220 m_meter_connection.disconnect();
224 delete _output_buffers;
228 IO::silence (nframes_t nframes, nframes_t offset)
230 /* io_lock, not taken: function must be called from Session::process() calltree */
232 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
233 i->get_buffer().silence (nframes, offset);
237 /** Deliver bufs to the IO's output ports
239 * This function should automatically do whatever it necessary to correctly deliver bufs
240 * to the outputs, eg applying gain or pan or whatever else needs to be done.
243 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
245 // FIXME: type specific code doesn't actually need to be here, it will go away in time
247 /* ********** AUDIO ********** */
249 // Apply gain if gain automation isn't playing
250 if ( ! apply_gain_automation) {
252 gain_t dg = _gain; // desired gain
255 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
263 if (dg != _gain || dg != 1.0)
264 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
267 // Use the panner to distribute audio to output port buffers
268 if (_panner && !_panner->empty() && !_panner->bypassed()) {
269 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
271 const DataType type = DataType::AUDIO;
273 // Copy any audio 1:1 to outputs
275 BufferSet::iterator o = output_buffers().begin(type);
276 BufferSet::iterator i = bufs.begin(type);
277 BufferSet::iterator prev = i;
279 while (i != bufs.end(type) && o != output_buffers().end (type)) {
280 o->read_from(*i, nframes, offset);
286 /* extra outputs get a copy of the last buffer */
288 while (o != output_buffers().end(type)) {
289 o->read_from(*prev, nframes, offset);
294 /* ********** MIDI ********** */
296 // No MIDI, we're done here
297 if (bufs.count().n_midi() == 0) {
301 const DataType type = DataType::MIDI;
303 // Copy any MIDI 1:1 to outputs
304 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
305 BufferSet::iterator o = output_buffers().begin(type);
306 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
307 o->read_from(*i, nframes, offset);
312 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
314 assert(outs.available() >= n_inputs());
316 if (n_inputs() == ChanCount::ZERO)
319 outs.set_count(n_inputs());
321 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
323 BufferSet::iterator o = outs.begin(*t);
324 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
325 o->read_from(i->get_buffer(), nframes, offset);
332 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
333 nframes_t nframes, nframes_t offset)
335 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
337 collect_input (bufs, nframes, offset);
339 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
344 IO::check_bundles_connected_to_inputs ()
346 check_bundles (_bundles_connected_to_inputs, inputs());
350 IO::check_bundles_connected_to_outputs ()
352 check_bundles (_bundles_connected_to_outputs, outputs());
356 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
358 std::vector<UserBundleInfo> new_list;
360 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
362 ChanCount const N = i->bundle->nchannels ();
364 if (ports.num_ports (default_type()) < N.get (default_type())) {
369 uint32_t n = N.get (default_type());
371 for (uint32_t j = 0; j < n; ++j) {
372 /* Every port on bundle channel j must be connected to our input j */
373 PortList const pl = i->bundle->channel_ports (j);
374 for (uint32_t k = 0; k < pl.size(); ++k) {
375 if (ports.port(j)->connected_to (pl[k]) == false) {
387 new_list.push_back (*i);
389 i->configuration_will_change.disconnect ();
390 i->configuration_has_changed.disconnect ();
391 i->ports_will_change.disconnect ();
392 i->ports_have_changed.disconnect ();
401 IO::disconnect_input (Port* our_port, string other_port, void* src)
403 if (other_port.length() == 0 || our_port == 0) {
408 BLOCK_PROCESS_CALLBACK ();
411 Glib::Mutex::Lock lm (io_lock);
413 /* check that our_port is really one of ours */
415 if ( ! _inputs.contains(our_port)) {
419 /* disconnect it from the source */
421 if (_session.engine().disconnect (other_port, our_port->name())) {
422 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
426 check_bundles_connected_to_inputs ();
430 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
431 _session.set_dirty ();
437 IO::connect_input (Port* our_port, string other_port, void* src)
439 if (other_port.length() == 0 || our_port == 0) {
444 BLOCK_PROCESS_CALLBACK ();
447 Glib::Mutex::Lock lm (io_lock);
449 /* check that our_port is really one of ours */
451 if ( ! _inputs.contains(our_port) ) {
455 /* connect it to the source */
457 if (_session.engine().connect (other_port, our_port->name())) {
463 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
464 _session.set_dirty ();
469 IO::disconnect_output (Port* our_port, string other_port, void* src)
471 if (other_port.length() == 0 || our_port == 0) {
476 BLOCK_PROCESS_CALLBACK ();
479 Glib::Mutex::Lock lm (io_lock);
481 /* check that our_port is really one of ours */
483 if ( ! _outputs.contains(our_port) ) {
487 /* disconnect it from the destination */
489 if (_session.engine().disconnect (our_port->name(), other_port)) {
490 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
494 check_bundles_connected_to_outputs ();
498 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
499 _session.set_dirty ();
504 IO::connect_output (Port* our_port, string other_port, void* src)
506 if (other_port.length() == 0 || our_port == 0) {
511 BLOCK_PROCESS_CALLBACK ();
515 Glib::Mutex::Lock lm (io_lock);
517 /* check that our_port is really one of ours */
519 if ( ! _outputs.contains(our_port) ) {
523 /* connect it to the destination */
525 if (_session.engine().connect (our_port->name(), other_port)) {
531 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
532 _session.set_dirty ();
537 IO::set_input (Port* other_port, void* src)
539 /* this removes all but one ports, and connects that one port
540 to the specified source.
543 if (_input_minimum.n_total() > 1) {
544 /* sorry, you can't do this */
548 if (other_port == 0) {
549 if (_input_minimum == ChanCount::ZERO) {
550 return ensure_inputs (ChanCount::ZERO, false, true, src);
556 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
560 return connect_input (_inputs.port(0), other_port->name(), src);
564 IO::remove_output_port (Port* port, void* src)
566 IOChange change (NoChange);
569 BLOCK_PROCESS_CALLBACK ();
573 Glib::Mutex::Lock lm (io_lock);
575 if (n_outputs() <= _output_minimum) {
576 /* sorry, you can't do this */
580 if (_outputs.remove(port)) {
581 change = IOChange (change|ConfigurationChanged);
583 if (port->connected()) {
584 change = IOChange (change|ConnectionsChanged);
587 _session.engine().unregister_port (*port);
588 check_bundles_connected_to_outputs ();
590 setup_peak_meters ();
595 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
598 if (change == ConnectionsChanged) {
599 setup_bundles_for_inputs_and_outputs ();
602 if (change != NoChange) {
603 output_changed (change, src);
604 _session.set_dirty ();
611 /** Add an output port.
613 * @param destination Name of input port to connect new port to.
614 * @param src Source for emitted ConfigurationChanged signal.
615 * @param type Data type of port. Default value (NIL) will use this IO's default type.
618 IO::add_output_port (string destination, void* src, DataType type)
622 if (type == DataType::NIL)
623 type = _default_type;
626 BLOCK_PROCESS_CALLBACK ();
630 Glib::Mutex::Lock lm (io_lock);
632 if (n_outputs() >= _output_maximum) {
636 /* Create a new output port */
638 string portname = build_legal_port_name (type, false);
640 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
641 error << string_compose(_("IO: cannot register output port %1"), portname) << 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)
727 if (type == DataType::NIL)
728 type = _default_type;
731 BLOCK_PROCESS_CALLBACK ();
734 Glib::Mutex::Lock lm (io_lock);
736 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
740 /* Create a new input port */
742 string portname = build_legal_port_name (type, true);
744 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
745 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
749 _inputs.add (our_port);
750 setup_peak_meters ();
754 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
757 if (source.length()) {
759 if (_session.engine().connect (source, our_port->name())) {
764 // pan_changed (src); /* EMIT SIGNAL */
765 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
766 setup_bundles_for_inputs_and_outputs ();
767 _session.set_dirty ();
773 IO::disconnect_inputs (void* src)
776 BLOCK_PROCESS_CALLBACK ();
779 Glib::Mutex::Lock lm (io_lock);
781 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
782 _session.engine().disconnect (*i);
785 check_bundles_connected_to_inputs ();
789 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
795 IO::disconnect_outputs (void* src)
798 BLOCK_PROCESS_CALLBACK ();
801 Glib::Mutex::Lock lm (io_lock);
803 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
804 _session.engine().disconnect (*i);
807 check_bundles_connected_to_outputs ();
811 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
812 _session.set_dirty ();
818 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
820 Port* input_port = 0;
821 bool changed = false;
824 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
826 const size_t n = count.get(*t);
828 /* remove unused ports */
829 for (size_t i = n_inputs().get(*t); i > n; --i) {
830 input_port = _inputs.port(*t, i-1);
833 _inputs.remove(input_port);
834 _session.engine().unregister_port (*input_port);
839 /* create any necessary new ports */
840 while (n_inputs().get(*t) < n) {
842 string portname = build_legal_port_name (*t, true);
846 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
847 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
852 catch (AudioEngine::PortRegistrationFailure& err) {
853 setup_peak_meters ();
856 throw AudioEngine::PortRegistrationFailure();
859 _inputs.add (input_port);
865 check_bundles_connected_to_inputs ();
866 setup_peak_meters ();
868 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
869 _session.set_dirty ();
873 /* disconnect all existing ports so that we get a fresh start */
874 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
875 _session.engine().disconnect (*i);
882 /** Attach output_buffers to port buffers.
884 * Connected to IO's own PortCountChanged signal.
887 IO::attach_buffers(ChanCount ignored)
889 _output_buffers->attach_buffers(_outputs);
893 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
895 bool in_changed = false;
896 bool out_changed = false;
897 bool need_pan_reset = false;
899 in = min (_input_maximum, in);
901 out = min (_output_maximum, out);
903 if (in == n_inputs() && out == n_outputs() && !clear) {
908 BLOCK_PROCESS_CALLBACK ();
909 Glib::Mutex::Lock lm (io_lock);
913 if (n_outputs() != out) {
914 need_pan_reset = true;
917 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
919 const size_t nin = in.get(*t);
920 const size_t nout = out.get(*t);
922 Port* output_port = 0;
923 Port* input_port = 0;
925 /* remove unused output ports */
926 for (size_t i = n_outputs().get(*t); i > nout; --i) {
927 output_port = _outputs.port(*t, i-1);
930 _outputs.remove(output_port);
931 _session.engine().unregister_port (*output_port);
936 /* remove unused input ports */
937 for (size_t i = n_inputs().get(*t); i > nin; --i) {
938 input_port = _inputs.port(*t, i-1);
941 _inputs.remove(input_port);
942 _session.engine().unregister_port (*input_port);
947 /* create any necessary new input ports */
949 while (n_inputs().get(*t) < nin) {
951 string portname = build_legal_port_name (*t, true);
954 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
955 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
960 catch (AudioEngine::PortRegistrationFailure& err) {
961 setup_peak_meters ();
964 throw AudioEngine::PortRegistrationFailure();
971 /* create any necessary new output ports */
973 while (n_outputs().get(*t) < nout) {
975 string portname = build_legal_port_name (*t, false);
978 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
979 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
984 catch (AudioEngine::PortRegistrationFailure& err) {
985 setup_peak_meters ();
988 throw AudioEngine::PortRegistrationFailure ();
998 /* disconnect all existing ports so that we get a fresh start */
1000 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1001 _session.engine().disconnect (*i);
1004 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1005 _session.engine().disconnect (*i);
1009 if (in_changed || out_changed) {
1010 setup_peak_meters ();
1016 check_bundles_connected_to_outputs ();
1017 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1021 check_bundles_connected_to_inputs ();
1022 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1025 if (in_changed || out_changed) {
1026 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1027 setup_bundles_for_inputs_and_outputs ();
1028 _session.set_dirty ();
1035 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1037 bool changed = false;
1039 count = min (_input_maximum, count);
1041 if (count == n_inputs() && !clear) {
1046 BLOCK_PROCESS_CALLBACK ();
1047 Glib::Mutex::Lock im (io_lock);
1048 changed = ensure_inputs_locked (count, clear, src);
1050 changed = ensure_inputs_locked (count, clear, src);
1054 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1055 setup_bundles_for_inputs_and_outputs ();
1056 _session.set_dirty ();
1062 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1064 Port* output_port = 0;
1065 bool changed = false;
1066 bool need_pan_reset = false;
1068 if (n_outputs() != count) {
1069 need_pan_reset = true;
1072 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1074 const size_t n = count.get(*t);
1076 /* remove unused ports */
1077 for (size_t i = n_outputs().get(*t); i > n; --i) {
1078 output_port = _outputs.port(*t, i-1);
1080 assert(output_port);
1081 _outputs.remove(output_port);
1082 _session.engine().unregister_port (*output_port);
1087 /* create any necessary new ports */
1088 while (n_outputs().get(*t) < n) {
1090 string portname = build_legal_port_name (*t, false);
1092 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1093 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1097 _outputs.add (output_port);
1099 setup_peak_meters ();
1101 if (need_pan_reset) {
1108 check_bundles_connected_to_outputs ();
1109 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1110 _session.set_dirty ();
1114 /* disconnect all existing ports so that we get a fresh start */
1115 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1116 _session.engine().disconnect (*i);
1124 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1126 bool changed = false;
1128 if (_output_maximum < ChanCount::INFINITE) {
1129 count = min (_output_maximum, count);
1130 if (count == n_outputs() && !clear) {
1135 /* XXX caller should hold io_lock, but generally doesn't */
1138 BLOCK_PROCESS_CALLBACK ();
1139 Glib::Mutex::Lock im (io_lock);
1140 changed = ensure_outputs_locked (count, clear, src);
1142 changed = ensure_outputs_locked (count, clear, src);
1146 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1147 setup_bundles_for_inputs_and_outputs ();
1154 IO::effective_gain () const
1156 if (_gain_control->automation_playback()) {
1157 return _gain_control->get_value();
1159 return _desired_gain;
1166 if (panners_legal) {
1167 if (!no_panner_reset) {
1168 _panner->reset (n_outputs().n_audio(), pans_required());
1171 panner_legal_c.disconnect ();
1172 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1177 IO::panners_became_legal ()
1179 _panner->reset (n_outputs().n_audio(), pans_required());
1180 _panner->load (); // automation
1181 panner_legal_c.disconnect ();
1186 IO::defer_pan_reset ()
1188 no_panner_reset = true;
1192 IO::allow_pan_reset ()
1194 no_panner_reset = false;
1200 IO::get_state (void)
1202 return state (true);
1206 IO::state (bool full_state)
1208 XMLNode* node = new XMLNode (state_node_name);
1211 vector<string>::iterator ci;
1213 LocaleGuard lg (X_("POSIX"));
1214 Glib::Mutex::Lock lm (io_lock);
1216 node->add_property("name", _name);
1217 id().print (buf, sizeof (buf));
1218 node->add_property("id", buf);
1221 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1222 i != _bundles_connected_to_inputs.end();
1226 XMLNode* n = new XMLNode ("InputBundle");
1227 n->add_property ("name", i->bundle->name ());
1228 node->add_child_nocopy (*n);
1232 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1233 i != _bundles_connected_to_outputs.end();
1237 XMLNode* n = new XMLNode ("OutputBundle");
1238 n->add_property ("name", i->bundle->name ());
1239 node->add_child_nocopy (*n);
1244 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1246 vector<string> connections;
1248 if (i->get_connections (connections)) {
1252 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1257 /* if its a connection to our own port,
1258 return only the port name, not the
1259 whole thing. this allows connections
1260 to be re-established even when our
1261 client name is different.
1264 str += _session.engine().make_port_name_relative (*ci);
1274 node->add_property ("inputs", str);
1278 for (PortSet::iterator i = _outputs.begin(); i != _outputs.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 str += _session.engine().make_port_name_relative (*ci);
1301 node->add_property ("outputs", str);
1303 node->add_child_nocopy (_panner->state (full_state));
1304 node->add_child_nocopy (_gain_control->get_state ());
1306 snprintf (buf, sizeof(buf), "%2.12f", gain());
1307 node->add_property ("gain", buf);
1309 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1313 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1314 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1316 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1318 node->add_property ("iolimits", buf);
1323 node->add_child_nocopy (get_automation_state());
1329 IO::set_state (const XMLNode& node)
1331 const XMLProperty* prop;
1332 XMLNodeConstIterator iter;
1333 LocaleGuard lg (X_("POSIX"));
1335 /* force use of non-localized representation of decimal point,
1336 since we use it a lot in XML files and so forth.
1339 if (node.name() != state_node_name) {
1340 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1344 if ((prop = node.property ("name")) != 0) {
1345 _name = prop->value();
1346 /* used to set panner name with this, but no more */
1349 if ((prop = node.property ("id")) != 0) {
1350 _id = prop->value ();
1358 if ((prop = node.property ("iolimits")) != 0) {
1359 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1360 &in_min, &in_max, &out_min, &out_max);
1362 /* Correct for the difference between the way we write things to session files and the
1363 way things are described by ChanCount; see comments in io.h about what the different
1364 ChanCount values mean. */
1367 _input_minimum = ChanCount::ZERO;
1369 _input_minimum = ChanCount (_default_type, in_min);
1373 _input_maximum = ChanCount::INFINITE;
1375 _input_maximum = ChanCount (_default_type, in_max);
1379 _output_minimum = ChanCount::ZERO;
1381 _output_minimum = ChanCount (_default_type, out_min);
1385 _output_maximum = ChanCount::INFINITE;
1387 _output_maximum = ChanCount (_default_type, out_max);
1391 if ((prop = node.property ("gain")) != 0) {
1392 set_gain (atof (prop->value().c_str()), this);
1393 _gain = _desired_gain;
1396 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1397 /* old school automation handling */
1400 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1402 if ((*iter)->name() == "Panner") {
1404 _panner = new Panner (_name, _session);
1406 _panner->set_state (**iter);
1409 if ((*iter)->name() == X_("Automation")) {
1411 set_automation_state (*(*iter), Parameter(GainAutomation));
1414 if ((*iter)->name() == X_("controllable")) {
1415 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1416 _gain_control->set_state (**iter);
1423 if (create_ports (node)) {
1429 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1432 if (panners_legal) {
1435 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1438 if (connecting_legal) {
1440 if (make_connections (node)) {
1446 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1449 if (!ports_legal || !connecting_legal) {
1450 pending_state_node = new XMLNode (node);
1457 IO::load_automation (string path)
1462 uint32_t linecnt = 0;
1464 LocaleGuard lg (X_("POSIX"));
1466 fullpath = Glib::build_filename(_session.automation_dir(), path);
1468 in.open (fullpath.c_str());
1471 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1473 in.open (fullpath.c_str());
1476 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1481 clear_automation ();
1483 while (in.getline (line, sizeof(line), '\n')) {
1488 if (++linecnt == 1) {
1489 if (memcmp (line, "version", 7) == 0) {
1490 if (sscanf (line, "version %f", &version) != 1) {
1491 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1495 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1502 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1503 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1509 _gain_control->list()->fast_simple_add (when, value);
1519 /* older (pre-1.0) versions of ardour used this */
1523 warning << _("dubious automation event found (and ignored)") << endmsg;
1531 IO::connecting_became_legal ()
1535 if (pending_state_node == 0) {
1536 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1541 connection_legal_c.disconnect ();
1543 ret = make_connections (*pending_state_node);
1546 delete pending_state_node;
1547 pending_state_node = 0;
1553 IO::ports_became_legal ()
1557 if (pending_state_node == 0) {
1558 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1563 port_legal_c.disconnect ();
1565 ret = create_ports (*pending_state_node);
1567 if (connecting_legal) {
1568 delete pending_state_node;
1569 pending_state_node = 0;
1575 boost::shared_ptr<Bundle>
1576 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1578 static const string digits = "0123456789";
1580 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1583 int bundle_number, mask;
1584 string possible_name;
1585 bool stereo = false;
1586 string::size_type last_non_digit_pos;
1588 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1591 // find numeric suffix of desired name
1594 last_non_digit_pos = desired_name.find_last_not_of(digits);
1596 if (last_non_digit_pos != string::npos) {
1598 s << desired_name.substr(last_non_digit_pos);
1602 // see if it's a stereo connection e.g. "in 3+4"
1604 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1605 int left_bundle_number = 0;
1606 string::size_type left_last_non_digit_pos;
1608 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1610 if (left_last_non_digit_pos != string::npos) {
1612 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1613 s >> left_bundle_number;
1615 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1626 // find highest set bit
1628 while ((mask <= bundle_number) && (mask <<= 1));
1630 // "wrap" bundle number into largest possible power of 2
1635 if (bundle_number & mask) {
1636 bundle_number &= ~mask;
1639 s << default_name << " " << bundle_number + 1;
1642 s << "+" << bundle_number + 2;
1645 possible_name = s.str();
1647 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1654 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1657 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1668 IO::create_ports (const XMLNode& node)
1670 XMLProperty const * prop;
1671 ChanCount num_inputs;
1672 ChanCount num_outputs;
1674 if ((prop = node.property ("input-connection")) != 0) {
1676 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1682 num_inputs = c->nchannels();
1684 } else if ((prop = node.property ("inputs")) != 0) {
1686 num_inputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1689 if ((prop = node.property ("output-connection")) != 0) {
1691 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1697 num_outputs = c->nchannels ();
1699 } else if ((prop = node.property ("outputs")) != 0) {
1701 num_outputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1704 no_panner_reset = true;
1706 if (ensure_io (num_inputs, num_outputs, true, this)) {
1707 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1711 no_panner_reset = false;
1713 set_deferred_state ();
1721 IO::make_connections (const XMLNode& node)
1724 const XMLProperty* prop;
1726 if ((prop = node.property ("input-connection")) != 0) {
1727 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1733 connect_input_ports_to_bundle (c, this);
1735 } else if ((prop = node.property ("inputs")) != 0) {
1736 if (set_inputs (prop->value())) {
1737 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1742 if ((prop = node.property ("output-connection")) != 0) {
1743 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1749 connect_output_ports_to_bundle (c, this);
1751 } else if ((prop = node.property ("outputs")) != 0) {
1752 if (set_outputs (prop->value())) {
1753 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1758 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1760 if ((*i)->name() == "InputBundle") {
1761 XMLProperty const * prop = (*i)->property ("name");
1763 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1765 connect_input_ports_to_bundle (b, this);
1769 } else if ((*i)->name() == "OutputBundle") {
1770 XMLProperty const * prop = (*i)->property ("name");
1772 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1774 connect_output_ports_to_bundle (b, this);
1784 IO::set_inputs (const string& str)
1786 vector<string> ports;
1791 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1795 // FIXME: audio-only
1796 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1800 string::size_type start, end, ostart;
1807 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1810 if ((end = str.find_first_of ('}', start)) == string::npos) {
1811 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1815 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1816 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1822 for (int x = 0; x < n; ++x) {
1823 connect_input (input (i), ports[x], this);
1835 IO::set_outputs (const string& str)
1837 vector<string> ports;
1842 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1846 // FIXME: audio-only
1847 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1851 string::size_type start, end, ostart;
1858 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1861 if ((end = str.find_first_of ('}', start)) == string::npos) {
1862 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1866 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1867 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1873 for (int x = 0; x < n; ++x) {
1874 connect_output (output (i), ports[x], this);
1886 IO::parse_io_string (const string& str, vector<string>& ports)
1888 string::size_type pos, opos;
1890 if (str.length() == 0) {
1899 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1900 ports.push_back (str.substr (opos, pos - opos));
1904 if (opos < str.length()) {
1905 ports.push_back (str.substr(opos));
1908 return ports.size();
1912 IO::parse_gain_string (const string& str, vector<string>& ports)
1914 string::size_type pos, opos;
1920 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1921 ports.push_back (str.substr (opos, pos - opos));
1925 if (opos < str.length()) {
1926 ports.push_back (str.substr(opos));
1929 return ports.size();
1933 IO::set_name (const string& requested_name)
1935 if (requested_name == _name) {
1941 if ( (rt = dynamic_cast<Route *>(this))) {
1942 name = Route::ensure_track_or_route_name(requested_name, _session);
1944 name = requested_name;
1948 /* replace all colons in the name. i wish we didn't have to do this */
1950 if (replace_all (name, ":", "-")) {
1951 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1954 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1955 string current_name = i->short_name();
1956 current_name.replace (current_name.find (_name), _name.length(), name);
1957 i->set_name (current_name);
1960 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1961 string current_name = i->short_name();
1962 current_name.replace (current_name.find (_name), _name.length(), name);
1963 i->set_name (current_name);
1966 bool const r = SessionObject::set_name(name);
1968 setup_bundles_for_inputs_and_outputs ();
1974 IO::set_input_minimum (ChanCount n)
1980 IO::set_input_maximum (ChanCount n)
1986 IO::set_output_minimum (ChanCount n)
1988 _output_minimum = n;
1992 IO::set_output_maximum (ChanCount n)
1994 _output_maximum = n;
1998 IO::set_port_latency (nframes_t nframes)
2000 Glib::Mutex::Lock lm (io_lock);
2002 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2003 i->set_latency (nframes);
2008 IO::output_latency () const
2010 nframes_t max_latency;
2015 /* io lock not taken - must be protected by other means */
2017 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2018 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2019 max_latency = latency;
2027 IO::input_latency () const
2029 nframes_t max_latency;
2034 /* io lock not taken - must be protected by other means */
2036 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2037 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2038 max_latency = latency;
2046 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2049 BLOCK_PROCESS_CALLBACK ();
2050 Glib::Mutex::Lock lm2 (io_lock);
2052 /* Connect to the bundle, not worrying about any connections
2053 that are already made. */
2055 ChanCount const channels = c->nchannels ();
2056 uint32_t cnt = channels.get (default_type());
2058 for (uint32_t n = 0; n < cnt; ++n) {
2059 const PortList& pl = c->channel_ports (n);
2061 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2063 if (!_inputs.port(n)->connected_to (*i)) {
2065 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2073 /* If this is a UserBundle, make a note of what we've done */
2075 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2078 /* See if we already know about this one */
2079 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2080 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2084 if (i == _bundles_connected_to_inputs.end()) {
2085 /* We don't, so make a note */
2086 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2091 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2096 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2099 BLOCK_PROCESS_CALLBACK ();
2100 Glib::Mutex::Lock lm2 (io_lock);
2102 /* Connect to the bundle, not worrying about any connections
2103 that are already made. */
2105 ChanCount const channels = c->nchannels ();
2106 uint32_t cnt = channels.get (default_type());
2108 for (uint32_t n = 0; n < cnt; ++n) {
2110 const PortList& pl = c->channel_ports (n);
2112 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2114 if (!_outputs.port(n)->connected_to (*i)) {
2116 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2123 /* If this is a UserBundle, make a note of what we've done */
2125 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2128 /* See if we already know about this one */
2129 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2130 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2134 if (i == _bundles_connected_to_outputs.end()) {
2135 /* We don't, so make a note */
2136 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2141 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2147 IO::disable_connecting ()
2149 connecting_legal = false;
2154 IO::enable_connecting ()
2156 connecting_legal = true;
2157 return ConnectingLegal ();
2161 IO::disable_ports ()
2163 ports_legal = false;
2171 return PortsLegal ();
2175 IO::disable_panners (void)
2177 panners_legal = false;
2182 IO::reset_panners ()
2184 panners_legal = true;
2185 return PannersLegal ();
2189 IO::bundle_configuration_will_change ()
2192 // connect_input_ports_to_bundle (_input_bundle, this);
2196 IO::bundle_configuration_has_changed ()
2199 // connect_input_ports_to_bundle (_input_bundle, this);
2203 IO::bundle_ports_will_change (int ignored)
2206 // connect_output_ports_to_bundle (_output_bundle, this);
2210 IO::bundle_ports_have_changed (int ignored)
2213 // connect_output_ports_to_bundle (_output_bundle, this);
2217 IO::GainControl::set_value (float val)
2219 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2220 if (val > 1.99526231f)
2224 _io.set_gain (val, this);
2226 Changed(); /* EMIT SIGNAL */
2230 IO::GainControl::get_value (void) const
2232 return AutomationControl::get_value();
2236 IO::setup_peak_meters()
2238 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2239 _meter->configure_io (max_streams, max_streams);
2243 Update the peak meters.
2245 The meter signal lock is taken to prevent modification of the
2246 Meter signal while updating the meters, taking the meter signal
2247 lock prior to taking the io_lock ensures that all IO will remain
2248 valid while metering.
2253 Glib::Mutex::Lock guard (m_meter_signal_lock);
2254 Meter(); /* EMIT SIGNAL */
2260 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2262 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2267 IO::clear_automation ()
2269 Automatable::clear (); // clears gain automation
2270 _panner->clear_automation ();
2274 IO::set_parameter_automation_state (Parameter param, AutoState state)
2276 // XXX: would be nice to get rid of this special hack
2278 if (param.type() == GainAutomation) {
2280 bool changed = false;
2283 Glib::Mutex::Lock lm (_control_lock);
2285 boost::shared_ptr<AutomationList> gain_auto
2286 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2288 if (state != gain_auto->automation_state()) {
2290 _last_automation_snapshot = 0;
2291 gain_auto->set_automation_state (state);
2294 // FIXME: shouldn't this use Curve?
2295 set_gain (gain_auto->eval (_session.transport_frame()), this);
2301 _session.set_dirty ();
2305 Automatable::set_parameter_automation_state(param, state);
2310 IO::inc_gain (gain_t factor, void *src)
2312 if (_desired_gain == 0.0f)
2313 set_gain (0.000001f + (0.000001f * factor), src);
2315 set_gain (_desired_gain + (_desired_gain * factor), src);
2319 IO::set_gain (gain_t val, void *src)
2321 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2322 if (val > 1.99526231f)
2325 if (src != _gain_control.get()) {
2326 _gain_control->set_value(val);
2327 // bit twisty, this will come back and call us again
2328 // (this keeps control in sync with reality)
2333 Glib::Mutex::Lock dm (declick_lock);
2334 _desired_gain = val;
2337 if (_session.transport_stopped()) {
2341 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2342 _gain_control->list()->add (_session.transport_frame(), val);
2346 _session.set_dirty();
2350 IO::start_pan_touch (uint32_t which)
2352 if (which < _panner->size()) {
2353 (*_panner)[which]->pan_control()->start_touch();
2358 IO::end_pan_touch (uint32_t which)
2360 if (which < _panner->size()) {
2361 (*_panner)[which]->pan_control()->stop_touch();
2367 IO::automation_snapshot (nframes_t now, bool force)
2369 Automatable::automation_snapshot (now, force);
2371 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2372 _panner->snapshot (now);
2375 _panner->snapshot (now);
2376 _last_automation_snapshot = now;
2380 IO::transport_stopped (nframes_t frame)
2382 _gain_control->list()->reposition_for_rt_add (frame);
2384 if (_gain_control->automation_state() != Off) {
2386 /* the src=0 condition is a special signal to not propagate
2387 automation gain changes into the mix group when locating.
2390 // FIXME: shouldn't this use Curve?
2391 set_gain (_gain_control->list()->eval (frame), 0);
2394 _panner->transport_stopped (frame);
2398 IO::build_legal_port_name (DataType type, bool in)
2400 const int name_size = jack_port_name_size();
2405 if (type == DataType::AUDIO) {
2406 suffix = _("audio");
2407 } else if (type == DataType::MIDI) {
2410 throw unknown_type();
2415 maxports = _input_maximum.get(type);
2417 suffix += _("_out");
2418 maxports = _output_maximum.get(type);
2421 if (maxports == 1) {
2422 // allow space for the slash + the suffix
2423 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2424 char buf[name_size+1];
2425 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2426 return string (buf);
2429 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2431 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2433 char buf1[name_size+1];
2434 char buf2[name_size+1];
2436 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2441 port_number = find_input_port_hole (buf1);
2443 port_number = find_output_port_hole (buf1);
2446 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2448 return string (buf2);
2452 IO::find_input_port_hole (const char* base)
2454 /* CALLER MUST HOLD IO LOCK */
2458 if (_inputs.empty()) {
2462 /* we only allow up to 4 characters for the port number
2465 for (n = 1; n < 9999; ++n) {
2466 char buf[jack_port_name_size()];
2467 PortSet::iterator i = _inputs.begin();
2469 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2471 for ( ; i != _inputs.end(); ++i) {
2472 if (i->short_name() == buf) {
2477 if (i == _inputs.end()) {
2485 IO::find_output_port_hole (const char* base)
2487 /* CALLER MUST HOLD IO LOCK */
2491 if (_outputs.empty()) {
2495 /* we only allow up to 4 characters for the port number
2498 for (n = 1; n < 9999; ++n) {
2499 char buf[jack_port_name_size()];
2500 PortSet::iterator i = _outputs.begin();
2502 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2504 for ( ; i != _outputs.end(); ++i) {
2505 if (i->short_name() == buf) {
2510 if (i == _outputs.end()) {
2519 IO::set_active (bool yn)
2522 active_changed(); /* EMIT SIGNAL */
2527 IO::audio_input(uint32_t n) const
2529 return dynamic_cast<AudioPort*>(input(n));
2533 IO::audio_output(uint32_t n) const
2535 return dynamic_cast<AudioPort*>(output(n));
2539 IO::midi_input(uint32_t n) const
2541 return dynamic_cast<MidiPort*>(input(n));
2545 IO::midi_output(uint32_t n) const
2547 return dynamic_cast<MidiPort*>(output(n));
2551 IO::set_phase_invert (bool yn, void *src)
2553 if (_phase_invert != yn) {
2555 // phase_invert_changed (src); /* EMIT SIGNAL */
2560 IO::set_denormal_protection (bool yn, void *src)
2562 if (_denormal_protection != yn) {
2563 _denormal_protection = yn;
2564 // denormal_protection_changed (src); /* EMIT SIGNAL */
2569 IO::update_port_total_latencies ()
2571 /* io_lock, not taken: function must be called from Session::process() calltree */
2573 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2574 _session.engine().update_total_latency (*i);
2577 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2578 _session.engine().update_total_latency (*i);
2584 * Setup bundles that describe our inputs and outputs.
2588 IO::setup_bundles_for_inputs_and_outputs ()
2592 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2593 _bundle_for_inputs->set_name (buf);
2594 uint32_t const ni = inputs().num_ports();
2595 _bundle_for_inputs->set_channels (ni);
2596 for (uint32_t i = 0; i < ni; ++i) {
2597 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2600 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2601 _bundle_for_outputs->set_name (buf);
2602 uint32_t const no = outputs().num_ports();
2603 _bundle_for_outputs->set_channels (no);
2604 for (uint32_t i = 0; i < no; ++i) {
2605 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2611 * Create and setup bundles that describe our inputs and outputs.
2615 IO::create_bundles_for_inputs_and_outputs ()
2617 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2618 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2619 setup_bundles_for_inputs_and_outputs ();
2622 /** Add a bundle to a list if is connected to our inputs.
2623 * @param b Bundle to check.
2624 * @param bundles List to add to.
2627 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2629 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2631 if (ab == 0 || ab->ports_are_outputs() == false) {
2635 if (ab->nchannels().get (default_type()) != n_inputs().n_total ()) {
2639 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2641 PortList const & pl = b->channel_ports (i);
2647 if (!input(i)->connected_to (pl[0])) {
2652 bundles->push_back (b);
2655 /** @return Bundles connected to our inputs */
2656 std::vector<boost::shared_ptr<Bundle> >
2657 IO::bundles_connected_to_inputs ()
2659 std::vector<boost::shared_ptr<Bundle> > bundles;
2662 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2663 bundles.push_back (i->bundle);
2667 _session.foreach_bundle (
2668 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2675 /** Add a bundle to a list if is connected to our outputs.
2676 * @param b Bundle to check.
2677 * @param bundles List to add to.
2680 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2682 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2683 if (ab == 0 || ab->ports_are_inputs() == false) {
2687 if (ab->nchannels ().get (default_type()) != n_outputs().n_total ()) {
2691 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2693 PortList const & pl = b->channel_ports (i);
2699 if (!output(i)->connected_to (pl[0])) {
2704 bundles->push_back (b);
2708 /* @return Bundles connected to our outputs */
2709 std::vector<boost::shared_ptr<Bundle> >
2710 IO::bundles_connected_to_outputs ()
2712 std::vector<boost::shared_ptr<Bundle> > bundles;
2715 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2716 bundles.push_back (i->bundle);
2720 _session.foreach_bundle (
2721 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2728 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2731 configuration_will_change = b->ConfigurationWillChange.connect (
2732 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2734 configuration_has_changed = b->ConfigurationHasChanged.connect (
2735 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2737 ports_will_change = b->PortsWillChange.connect (
2738 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2740 ports_have_changed = b->PortsHaveChanged.connect (
2741 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)