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 : SessionObject(s, name),
107 AutomatableControls (s),
108 _output_buffers (new BufferSet()),
110 _default_type (default_type),
111 _public_ports (public_ports),
112 _input_minimum (ChanCount::ZERO),
113 _input_maximum (ChanCount::INFINITE),
114 _output_minimum (ChanCount::ZERO),
115 _output_maximum (ChanCount::INFINITE)
117 _panner = new Panner (name, _session);
118 _meter = new PeakMeter (_session);
121 _input_minimum = ChanCount(_default_type, input_min);
123 if (input_max >= 0) {
124 _input_maximum = ChanCount(_default_type, input_max);
126 if (output_min > 0) {
127 _output_minimum = ChanCount(_default_type, output_min);
129 if (output_max >= 0) {
130 _output_maximum = ChanCount(_default_type, output_max);
135 pending_state_node = 0;
136 no_panner_reset = false;
137 _phase_invert = false;
140 boost::shared_ptr<AutomationList> gl(
141 new AutomationList(Parameter(GainAutomation)));
143 _gain_control = boost::shared_ptr<GainControl>(
144 new GainControl(X_("gaincontrol"), *this, gl));
146 add_control(_gain_control);
148 apply_gain_automation = false;
151 // IO::Meter is emitted from another thread so the
152 // Meter signal must be protected.
153 Glib::Mutex::Lock guard (m_meter_signal_lock);
154 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
157 // Connect to our own PortCountChanged signal to connect output buffers
158 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
160 _session.add_controllable (_gain_control);
162 create_bundles_for_inputs_and_outputs ();
165 IO::IO (Session& s, const XMLNode& node, DataType dt)
166 : SessionObject(s, "unnamed io"),
167 AutomatableControls (s),
168 _output_buffers (new BufferSet()),
172 _meter = new PeakMeter (_session);
173 _public_ports = true; // XXX get this from node
176 no_panner_reset = false;
180 apply_gain_automation = false;
182 boost::shared_ptr<AutomationList> gl(
183 new AutomationList(Parameter(GainAutomation)));
185 _gain_control = boost::shared_ptr<GainControl>(
186 new GainControl(X_("gaincontrol"), *this, gl));
188 add_control(_gain_control);
193 // IO::Meter is emitted from another thread so the
194 // Meter signal must be protected.
195 Glib::Mutex::Lock guard (m_meter_signal_lock);
196 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
199 // Connect to our own PortCountChanged signal to connect output buffers
200 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
202 _session.add_controllable (_gain_control);
204 create_bundles_for_inputs_and_outputs ();
209 Glib::Mutex::Lock guard (m_meter_signal_lock);
210 Glib::Mutex::Lock lm (io_lock);
212 BLOCK_PROCESS_CALLBACK ();
214 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
215 _session.engine().unregister_port (*i);
218 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
219 _session.engine().unregister_port (*i);
222 m_meter_connection.disconnect();
226 delete _output_buffers;
230 IO::silence (nframes_t nframes, nframes_t offset)
232 /* io_lock, not taken: function must be called from Session::process() calltree */
234 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
235 i->get_buffer().silence (nframes, offset);
239 /** Deliver bufs to the IO's output ports
241 * This function should automatically do whatever it necessary to correctly deliver bufs
242 * to the outputs, eg applying gain or pan or whatever else needs to be done.
245 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
247 // FIXME: type specific code doesn't actually need to be here, it will go away in time
249 /* ********** AUDIO ********** */
251 // Apply gain if gain automation isn't playing
252 if ( ! apply_gain_automation) {
254 gain_t dg = _gain; // desired gain
257 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
265 if (dg != _gain || dg != 1.0)
266 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
269 // Use the panner to distribute audio to output port buffers
270 if (_panner && !_panner->empty() && !_panner->bypassed()) {
271 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
273 const DataType type = DataType::AUDIO;
275 // Copy any audio 1:1 to outputs
277 BufferSet::iterator o = output_buffers().begin(type);
278 BufferSet::iterator i = bufs.begin(type);
279 BufferSet::iterator prev = i;
281 while (i != bufs.end(type) && o != output_buffers().end (type)) {
282 o->read_from(*i, nframes, offset);
288 /* extra outputs get a copy of the last buffer */
290 while (o != output_buffers().end(type)) {
291 o->read_from(*prev, nframes, offset);
296 /* ********** MIDI ********** */
298 // No MIDI, we're done here
299 if (bufs.count().n_midi() == 0) {
303 const DataType type = DataType::MIDI;
305 // Copy any MIDI 1:1 to outputs
306 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
307 BufferSet::iterator o = output_buffers().begin(type);
308 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
309 o->read_from(*i, nframes, offset);
314 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
316 assert(outs.available() >= n_inputs());
318 if (n_inputs() == ChanCount::ZERO)
321 outs.set_count(n_inputs());
323 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
325 BufferSet::iterator o = outs.begin(*t);
326 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
327 o->read_from(i->get_buffer(), nframes, offset);
334 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
335 nframes_t nframes, nframes_t offset)
337 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
339 collect_input (bufs, nframes, offset);
341 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
346 IO::check_bundles_connected_to_inputs ()
348 check_bundles (_bundles_connected_to_inputs, inputs());
352 IO::check_bundles_connected_to_outputs ()
354 check_bundles (_bundles_connected_to_outputs, outputs());
358 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
360 std::vector<UserBundleInfo> new_list;
362 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
364 ChanCount const N = i->bundle->nchannels ();
366 if (ports.num_ports (default_type()) < N.get (default_type())) {
371 uint32_t n = N.get (default_type());
373 for (uint32_t j = 0; j < n; ++j) {
374 /* Every port on bundle channel j must be connected to our input j */
375 PortList const pl = i->bundle->channel_ports (j);
376 for (uint32_t k = 0; k < pl.size(); ++k) {
377 if (ports.port(j)->connected_to (pl[k]) == false) {
389 new_list.push_back (*i);
391 i->configuration_will_change.disconnect ();
392 i->configuration_has_changed.disconnect ();
393 i->ports_will_change.disconnect ();
394 i->ports_have_changed.disconnect ();
403 IO::disconnect_input (Port* our_port, string other_port, void* src)
405 if (other_port.length() == 0 || our_port == 0) {
410 BLOCK_PROCESS_CALLBACK ();
413 Glib::Mutex::Lock lm (io_lock);
415 /* check that our_port is really one of ours */
417 if ( ! _inputs.contains(our_port)) {
421 /* disconnect it from the source */
423 if (_session.engine().disconnect (other_port, our_port->name())) {
424 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
428 check_bundles_connected_to_inputs ();
432 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
433 _session.set_dirty ();
439 IO::connect_input (Port* our_port, string other_port, void* src)
441 if (other_port.length() == 0 || our_port == 0) {
446 BLOCK_PROCESS_CALLBACK ();
449 Glib::Mutex::Lock lm (io_lock);
451 /* check that our_port is really one of ours */
453 if ( ! _inputs.contains(our_port) ) {
457 /* connect it to the source */
459 if (_session.engine().connect (other_port, our_port->name())) {
465 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
466 _session.set_dirty ();
471 IO::disconnect_output (Port* our_port, string other_port, void* src)
473 if (other_port.length() == 0 || our_port == 0) {
478 BLOCK_PROCESS_CALLBACK ();
481 Glib::Mutex::Lock lm (io_lock);
483 /* check that our_port is really one of ours */
485 if ( ! _outputs.contains(our_port) ) {
489 /* disconnect it from the destination */
491 if (_session.engine().disconnect (our_port->name(), other_port)) {
492 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
496 check_bundles_connected_to_outputs ();
500 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
501 _session.set_dirty ();
506 IO::connect_output (Port* our_port, string other_port, void* src)
508 if (other_port.length() == 0 || our_port == 0) {
513 BLOCK_PROCESS_CALLBACK ();
517 Glib::Mutex::Lock lm (io_lock);
519 /* check that our_port is really one of ours */
521 if ( ! _outputs.contains(our_port) ) {
525 /* connect it to the destination */
527 if (_session.engine().connect (our_port->name(), other_port)) {
533 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
534 _session.set_dirty ();
539 IO::set_input (Port* other_port, void* src)
541 /* this removes all but one ports, and connects that one port
542 to the specified source.
545 if (_input_minimum.n_total() > 1) {
546 /* sorry, you can't do this */
550 if (other_port == 0) {
551 if (_input_minimum == ChanCount::ZERO) {
552 return ensure_inputs (ChanCount::ZERO, false, true, src);
558 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
562 return connect_input (_inputs.port(0), other_port->name(), src);
566 IO::remove_output_port (Port* port, void* src)
568 IOChange change (NoChange);
571 BLOCK_PROCESS_CALLBACK ();
575 Glib::Mutex::Lock lm (io_lock);
577 if (n_outputs() <= _output_minimum) {
578 /* sorry, you can't do this */
582 if (_outputs.remove(port)) {
583 change = IOChange (change|ConfigurationChanged);
585 if (port->connected()) {
586 change = IOChange (change|ConnectionsChanged);
589 _session.engine().unregister_port (*port);
590 check_bundles_connected_to_outputs ();
592 setup_peak_meters ();
597 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
600 if (change == ConnectionsChanged) {
601 setup_bundles_for_inputs_and_outputs ();
604 if (change != NoChange) {
605 output_changed (change, src);
606 _session.set_dirty ();
613 /** Add an output port.
615 * @param destination Name of input port to connect new port to.
616 * @param src Source for emitted ConfigurationChanged signal.
617 * @param type Data type of port. Default value (NIL) will use this IO's default type.
620 IO::add_output_port (string destination, void* src, DataType type)
624 if (type == DataType::NIL)
625 type = _default_type;
628 BLOCK_PROCESS_CALLBACK ();
632 Glib::Mutex::Lock lm (io_lock);
634 if (n_outputs() >= _output_maximum) {
638 /* Create a new output port */
640 string portname = build_legal_port_name (type, false);
642 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
643 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
647 _outputs.add (our_port);
648 setup_peak_meters ();
652 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
655 if (destination.length()) {
656 if (_session.engine().connect (our_port->name(), destination)) {
661 // pan_changed (src); /* EMIT SIGNAL */
662 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
663 setup_bundles_for_inputs_and_outputs ();
664 _session.set_dirty ();
670 IO::remove_input_port (Port* port, void* src)
672 IOChange change (NoChange);
675 BLOCK_PROCESS_CALLBACK ();
679 Glib::Mutex::Lock lm (io_lock);
681 if (n_inputs() <= _input_minimum) {
682 /* sorry, you can't do this */
686 if (_inputs.remove(port)) {
687 change = IOChange (change|ConfigurationChanged);
689 if (port->connected()) {
690 change = IOChange (change|ConnectionsChanged);
693 _session.engine().unregister_port (*port);
694 check_bundles_connected_to_inputs ();
696 setup_peak_meters ();
701 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
704 if (change == ConfigurationChanged) {
705 setup_bundles_for_inputs_and_outputs ();
708 if (change != NoChange) {
709 input_changed (change, src);
710 _session.set_dirty ();
718 /** Add an input port.
720 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
721 * @param destination Name of input port to connect new port to.
722 * @param src Source for emitted ConfigurationChanged signal.
725 IO::add_input_port (string source, void* src, DataType type)
729 if (type == DataType::NIL)
730 type = _default_type;
733 BLOCK_PROCESS_CALLBACK ();
736 Glib::Mutex::Lock lm (io_lock);
738 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
742 /* Create a new input port */
744 string portname = build_legal_port_name (type, true);
746 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
747 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
751 _inputs.add (our_port);
752 setup_peak_meters ();
756 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
759 if (source.length()) {
761 if (_session.engine().connect (source, our_port->name())) {
766 // pan_changed (src); /* EMIT SIGNAL */
767 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
768 setup_bundles_for_inputs_and_outputs ();
769 _session.set_dirty ();
775 IO::disconnect_inputs (void* src)
778 BLOCK_PROCESS_CALLBACK ();
781 Glib::Mutex::Lock lm (io_lock);
783 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
784 _session.engine().disconnect (*i);
787 check_bundles_connected_to_inputs ();
791 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
797 IO::disconnect_outputs (void* src)
800 BLOCK_PROCESS_CALLBACK ();
803 Glib::Mutex::Lock lm (io_lock);
805 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
806 _session.engine().disconnect (*i);
809 check_bundles_connected_to_outputs ();
813 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
814 _session.set_dirty ();
820 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
822 Port* input_port = 0;
823 bool changed = false;
826 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
828 const size_t n = count.get(*t);
830 /* remove unused ports */
831 for (size_t i = n_inputs().get(*t); i > n; --i) {
832 input_port = _inputs.port(*t, i-1);
835 _inputs.remove(input_port);
836 _session.engine().unregister_port (*input_port);
841 /* create any necessary new ports */
842 while (n_inputs().get(*t) < n) {
844 string portname = build_legal_port_name (*t, true);
848 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
849 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
854 catch (AudioEngine::PortRegistrationFailure& err) {
855 setup_peak_meters ();
858 throw AudioEngine::PortRegistrationFailure();
861 _inputs.add (input_port);
867 check_bundles_connected_to_inputs ();
868 setup_peak_meters ();
870 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
871 _session.set_dirty ();
875 /* disconnect all existing ports so that we get a fresh start */
876 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
877 _session.engine().disconnect (*i);
884 /** Attach output_buffers to port buffers.
886 * Connected to IO's own PortCountChanged signal.
889 IO::attach_buffers(ChanCount ignored)
891 _output_buffers->attach_buffers(_outputs);
895 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
897 bool in_changed = false;
898 bool out_changed = false;
899 bool need_pan_reset = false;
901 in = min (_input_maximum, in);
903 out = min (_output_maximum, out);
905 if (in == n_inputs() && out == n_outputs() && !clear) {
910 BLOCK_PROCESS_CALLBACK ();
911 Glib::Mutex::Lock lm (io_lock);
915 if (n_outputs() != out) {
916 need_pan_reset = true;
919 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
921 const size_t nin = in.get(*t);
922 const size_t nout = out.get(*t);
924 Port* output_port = 0;
925 Port* input_port = 0;
927 /* remove unused output ports */
928 for (size_t i = n_outputs().get(*t); i > nout; --i) {
929 output_port = _outputs.port(*t, i-1);
932 _outputs.remove(output_port);
933 _session.engine().unregister_port (*output_port);
938 /* remove unused input ports */
939 for (size_t i = n_inputs().get(*t); i > nin; --i) {
940 input_port = _inputs.port(*t, i-1);
943 _inputs.remove(input_port);
944 _session.engine().unregister_port (*input_port);
949 /* create any necessary new input ports */
951 while (n_inputs().get(*t) < nin) {
953 string portname = build_legal_port_name (*t, true);
956 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
957 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
962 catch (AudioEngine::PortRegistrationFailure& err) {
963 setup_peak_meters ();
966 throw AudioEngine::PortRegistrationFailure();
973 /* create any necessary new output ports */
975 while (n_outputs().get(*t) < nout) {
977 string portname = build_legal_port_name (*t, false);
980 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
981 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
986 catch (AudioEngine::PortRegistrationFailure& err) {
987 setup_peak_meters ();
990 throw AudioEngine::PortRegistrationFailure ();
1000 /* disconnect all existing ports so that we get a fresh start */
1002 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1003 _session.engine().disconnect (*i);
1006 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1007 _session.engine().disconnect (*i);
1011 if (in_changed || out_changed) {
1012 setup_peak_meters ();
1018 check_bundles_connected_to_outputs ();
1019 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1023 check_bundles_connected_to_inputs ();
1024 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1027 if (in_changed || out_changed) {
1028 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1029 setup_bundles_for_inputs_and_outputs ();
1030 _session.set_dirty ();
1037 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1039 bool changed = false;
1041 count = min (_input_maximum, count);
1043 if (count == n_inputs() && !clear) {
1048 BLOCK_PROCESS_CALLBACK ();
1049 Glib::Mutex::Lock im (io_lock);
1050 changed = ensure_inputs_locked (count, clear, src);
1052 changed = ensure_inputs_locked (count, clear, src);
1056 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1057 setup_bundles_for_inputs_and_outputs ();
1058 _session.set_dirty ();
1064 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1066 Port* output_port = 0;
1067 bool changed = false;
1068 bool need_pan_reset = false;
1070 if (n_outputs() != count) {
1071 need_pan_reset = true;
1074 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1076 const size_t n = count.get(*t);
1078 /* remove unused ports */
1079 for (size_t i = n_outputs().get(*t); i > n; --i) {
1080 output_port = _outputs.port(*t, i-1);
1082 assert(output_port);
1083 _outputs.remove(output_port);
1084 _session.engine().unregister_port (*output_port);
1089 /* create any necessary new ports */
1090 while (n_outputs().get(*t) < n) {
1092 string portname = build_legal_port_name (*t, false);
1094 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1095 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1099 _outputs.add (output_port);
1101 setup_peak_meters ();
1103 if (need_pan_reset) {
1110 check_bundles_connected_to_outputs ();
1111 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1112 _session.set_dirty ();
1116 /* disconnect all existing ports so that we get a fresh start */
1117 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1118 _session.engine().disconnect (*i);
1126 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1128 bool changed = false;
1130 if (_output_maximum < ChanCount::INFINITE) {
1131 count = min (_output_maximum, count);
1132 if (count == n_outputs() && !clear) {
1137 /* XXX caller should hold io_lock, but generally doesn't */
1140 BLOCK_PROCESS_CALLBACK ();
1141 Glib::Mutex::Lock im (io_lock);
1142 changed = ensure_outputs_locked (count, clear, src);
1144 changed = ensure_outputs_locked (count, clear, src);
1148 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1149 setup_bundles_for_inputs_and_outputs ();
1156 IO::effective_gain () const
1158 if (_gain_control->automation_playback()) {
1159 return _gain_control->get_value();
1161 return _desired_gain;
1168 if (panners_legal) {
1169 if (!no_panner_reset) {
1170 _panner->reset (n_outputs().n_audio(), pans_required());
1173 panner_legal_c.disconnect ();
1174 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1179 IO::panners_became_legal ()
1181 _panner->reset (n_outputs().n_audio(), pans_required());
1182 _panner->load (); // automation
1183 panner_legal_c.disconnect ();
1188 IO::defer_pan_reset ()
1190 no_panner_reset = true;
1194 IO::allow_pan_reset ()
1196 no_panner_reset = false;
1202 IO::get_state (void)
1204 return state (true);
1208 IO::state (bool full_state)
1210 XMLNode* node = new XMLNode (state_node_name);
1213 vector<string>::iterator ci;
1215 LocaleGuard lg (X_("POSIX"));
1216 Glib::Mutex::Lock lm (io_lock);
1218 node->add_property("name", _name);
1219 id().print (buf, sizeof (buf));
1220 node->add_property("id", buf);
1223 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1224 i != _bundles_connected_to_inputs.end();
1228 XMLNode* n = new XMLNode ("InputBundle");
1229 n->add_property ("name", i->bundle->name ());
1230 node->add_child_nocopy (*n);
1234 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1235 i != _bundles_connected_to_outputs.end();
1239 XMLNode* n = new XMLNode ("OutputBundle");
1240 n->add_property ("name", i->bundle->name ());
1241 node->add_child_nocopy (*n);
1246 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1248 vector<string> connections;
1250 if (i->get_connections (connections)) {
1254 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1259 /* if its a connection to our own port,
1260 return only the port name, not the
1261 whole thing. this allows connections
1262 to be re-established even when our
1263 client name is different.
1266 str += _session.engine().make_port_name_relative (*ci);
1276 node->add_property ("inputs", str);
1280 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1282 vector<string> connections;
1284 if (i->get_connections (connections)) {
1288 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1293 str += _session.engine().make_port_name_relative (*ci);
1303 node->add_property ("outputs", str);
1305 node->add_child_nocopy (_panner->state (full_state));
1306 node->add_child_nocopy (_gain_control->get_state ());
1308 snprintf (buf, sizeof(buf), "%2.12f", gain());
1309 node->add_property ("gain", buf);
1311 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1315 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1316 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1318 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1320 node->add_property ("iolimits", buf);
1325 node->add_child_nocopy (get_automation_state());
1331 IO::set_state (const XMLNode& node)
1333 const XMLProperty* prop;
1334 XMLNodeConstIterator iter;
1335 LocaleGuard lg (X_("POSIX"));
1337 /* force use of non-localized representation of decimal point,
1338 since we use it a lot in XML files and so forth.
1341 if (node.name() != state_node_name) {
1342 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1346 if ((prop = node.property ("name")) != 0) {
1347 _name = prop->value();
1348 /* used to set panner name with this, but no more */
1351 if ((prop = node.property ("id")) != 0) {
1352 _id = prop->value ();
1360 if ((prop = node.property ("iolimits")) != 0) {
1361 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1362 &in_min, &in_max, &out_min, &out_max);
1364 /* Correct for the difference between the way we write things to session files and the
1365 way things are described by ChanCount; see comments in io.h about what the different
1366 ChanCount values mean. */
1369 _input_minimum = ChanCount::ZERO;
1371 _input_minimum = ChanCount (_default_type, in_min);
1375 _input_maximum = ChanCount::INFINITE;
1377 _input_maximum = ChanCount (_default_type, in_max);
1381 _output_minimum = ChanCount::ZERO;
1383 _output_minimum = ChanCount (_default_type, out_min);
1387 _output_maximum = ChanCount::INFINITE;
1389 _output_maximum = ChanCount (_default_type, out_max);
1393 if ((prop = node.property ("gain")) != 0) {
1394 set_gain (atof (prop->value().c_str()), this);
1395 _gain = _desired_gain;
1398 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1399 /* old school automation handling */
1402 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1404 if ((*iter)->name() == "Panner") {
1406 _panner = new Panner (_name, _session);
1408 _panner->set_state (**iter);
1411 if ((*iter)->name() == X_("Automation")) {
1413 set_automation_state (*(*iter), Parameter(GainAutomation));
1416 if ((*iter)->name() == X_("controllable")) {
1417 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1418 _gain_control->set_state (**iter);
1425 if (create_ports (node)) {
1431 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1434 if (panners_legal) {
1437 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1440 if (connecting_legal) {
1442 if (make_connections (node)) {
1448 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1451 if (!ports_legal || !connecting_legal) {
1452 pending_state_node = new XMLNode (node);
1459 IO::load_automation (string path)
1464 uint32_t linecnt = 0;
1466 LocaleGuard lg (X_("POSIX"));
1468 fullpath = Glib::build_filename(_session.automation_dir(), path);
1470 in.open (fullpath.c_str());
1473 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1475 in.open (fullpath.c_str());
1478 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1483 clear_automation ();
1485 while (in.getline (line, sizeof(line), '\n')) {
1490 if (++linecnt == 1) {
1491 if (memcmp (line, "version", 7) == 0) {
1492 if (sscanf (line, "version %f", &version) != 1) {
1493 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1497 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1504 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1505 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1511 _gain_control->list()->fast_simple_add (when, value);
1521 /* older (pre-1.0) versions of ardour used this */
1525 warning << _("dubious automation event found (and ignored)") << endmsg;
1533 IO::connecting_became_legal ()
1537 if (pending_state_node == 0) {
1538 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1543 connection_legal_c.disconnect ();
1545 ret = make_connections (*pending_state_node);
1548 delete pending_state_node;
1549 pending_state_node = 0;
1555 IO::ports_became_legal ()
1559 if (pending_state_node == 0) {
1560 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1565 port_legal_c.disconnect ();
1567 ret = create_ports (*pending_state_node);
1569 if (connecting_legal) {
1570 delete pending_state_node;
1571 pending_state_node = 0;
1577 boost::shared_ptr<Bundle>
1578 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1580 static const string digits = "0123456789";
1582 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1585 int bundle_number, mask;
1586 string possible_name;
1587 bool stereo = false;
1588 string::size_type last_non_digit_pos;
1590 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1593 // find numeric suffix of desired name
1596 last_non_digit_pos = desired_name.find_last_not_of(digits);
1598 if (last_non_digit_pos != string::npos) {
1600 s << desired_name.substr(last_non_digit_pos);
1604 // see if it's a stereo connection e.g. "in 3+4"
1606 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1607 int left_bundle_number = 0;
1608 string::size_type left_last_non_digit_pos;
1610 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1612 if (left_last_non_digit_pos != string::npos) {
1614 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1615 s >> left_bundle_number;
1617 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1628 // find highest set bit
1630 while ((mask <= bundle_number) && (mask <<= 1));
1632 // "wrap" bundle number into largest possible power of 2
1637 if (bundle_number & mask) {
1638 bundle_number &= ~mask;
1641 s << default_name << " " << bundle_number + 1;
1644 s << "+" << bundle_number + 2;
1647 possible_name = s.str();
1649 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1656 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1659 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1670 IO::create_ports (const XMLNode& node)
1672 XMLProperty const * prop;
1673 ChanCount num_inputs;
1674 ChanCount num_outputs;
1676 if ((prop = node.property ("input-connection")) != 0) {
1678 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1684 num_inputs = c->nchannels();
1686 } else if ((prop = node.property ("inputs")) != 0) {
1688 num_inputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1691 if ((prop = node.property ("output-connection")) != 0) {
1693 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1699 num_outputs = c->nchannels ();
1701 } else if ((prop = node.property ("outputs")) != 0) {
1703 num_outputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1706 no_panner_reset = true;
1708 if (ensure_io (num_inputs, num_outputs, true, this)) {
1709 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1713 no_panner_reset = false;
1715 set_deferred_state ();
1723 IO::make_connections (const XMLNode& node)
1726 const XMLProperty* prop;
1728 if ((prop = node.property ("input-connection")) != 0) {
1729 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1735 connect_input_ports_to_bundle (c, this);
1737 } else if ((prop = node.property ("inputs")) != 0) {
1738 if (set_inputs (prop->value())) {
1739 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1744 if ((prop = node.property ("output-connection")) != 0) {
1745 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1751 connect_output_ports_to_bundle (c, this);
1753 } else if ((prop = node.property ("outputs")) != 0) {
1754 if (set_outputs (prop->value())) {
1755 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1760 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1762 if ((*i)->name() == "InputBundle") {
1763 XMLProperty const * prop = (*i)->property ("name");
1765 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1767 connect_input_ports_to_bundle (b, this);
1771 } else if ((*i)->name() == "OutputBundle") {
1772 XMLProperty const * prop = (*i)->property ("name");
1774 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1776 connect_output_ports_to_bundle (b, this);
1786 IO::set_inputs (const string& str)
1788 vector<string> ports;
1793 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1797 // FIXME: audio-only
1798 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1802 string::size_type start, end, ostart;
1809 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1812 if ((end = str.find_first_of ('}', start)) == string::npos) {
1813 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1817 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1818 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1824 for (int x = 0; x < n; ++x) {
1825 connect_input (input (i), ports[x], this);
1837 IO::set_outputs (const string& str)
1839 vector<string> ports;
1844 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1848 // FIXME: audio-only
1849 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1853 string::size_type start, end, ostart;
1860 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1863 if ((end = str.find_first_of ('}', start)) == string::npos) {
1864 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1868 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1869 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1875 for (int x = 0; x < n; ++x) {
1876 connect_output (output (i), ports[x], this);
1888 IO::parse_io_string (const string& str, vector<string>& ports)
1890 string::size_type pos, opos;
1892 if (str.length() == 0) {
1901 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1902 ports.push_back (str.substr (opos, pos - opos));
1906 if (opos < str.length()) {
1907 ports.push_back (str.substr(opos));
1910 return ports.size();
1914 IO::parse_gain_string (const string& str, vector<string>& ports)
1916 string::size_type pos, opos;
1922 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1923 ports.push_back (str.substr (opos, pos - opos));
1927 if (opos < str.length()) {
1928 ports.push_back (str.substr(opos));
1931 return ports.size();
1935 IO::set_name (const string& requested_name)
1937 if (requested_name == _name) {
1943 if ( (rt = dynamic_cast<Route *>(this))) {
1944 name = Route::ensure_track_or_route_name(requested_name, _session);
1946 name = requested_name;
1950 /* replace all colons in the name. i wish we didn't have to do this */
1952 if (replace_all (name, ":", "-")) {
1953 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1956 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1957 string current_name = i->short_name();
1958 current_name.replace (current_name.find (_name), _name.length(), name);
1959 i->set_name (current_name);
1962 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1963 string current_name = i->short_name();
1964 current_name.replace (current_name.find (_name), _name.length(), name);
1965 i->set_name (current_name);
1968 bool const r = SessionObject::set_name(name);
1970 setup_bundles_for_inputs_and_outputs ();
1976 IO::set_input_minimum (ChanCount n)
1982 IO::set_input_maximum (ChanCount n)
1988 IO::set_output_minimum (ChanCount n)
1990 _output_minimum = n;
1994 IO::set_output_maximum (ChanCount n)
1996 _output_maximum = n;
2000 IO::set_port_latency (nframes_t nframes)
2002 Glib::Mutex::Lock lm (io_lock);
2004 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2005 i->set_latency (nframes);
2010 IO::output_latency () const
2012 nframes_t max_latency;
2017 /* io lock not taken - must be protected by other means */
2019 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2020 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2021 max_latency = latency;
2029 IO::input_latency () const
2031 nframes_t max_latency;
2036 /* io lock not taken - must be protected by other means */
2038 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2039 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2040 max_latency = latency;
2048 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2051 BLOCK_PROCESS_CALLBACK ();
2052 Glib::Mutex::Lock lm2 (io_lock);
2054 /* Connect to the bundle, not worrying about any connections
2055 that are already made. */
2057 ChanCount const channels = c->nchannels ();
2058 uint32_t cnt = channels.get (default_type());
2060 for (uint32_t n = 0; n < cnt; ++n) {
2061 const PortList& pl = c->channel_ports (n);
2063 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2065 if (!_inputs.port(n)->connected_to (*i)) {
2067 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2075 /* If this is a UserBundle, make a note of what we've done */
2077 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2080 /* See if we already know about this one */
2081 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2082 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2086 if (i == _bundles_connected_to_inputs.end()) {
2087 /* We don't, so make a note */
2088 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2093 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2098 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2101 BLOCK_PROCESS_CALLBACK ();
2102 Glib::Mutex::Lock lm2 (io_lock);
2104 /* Connect to the bundle, not worrying about any connections
2105 that are already made. */
2107 ChanCount const channels = c->nchannels ();
2108 uint32_t cnt = channels.get (default_type());
2110 for (uint32_t n = 0; n < cnt; ++n) {
2112 const PortList& pl = c->channel_ports (n);
2114 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2116 if (!_outputs.port(n)->connected_to (*i)) {
2118 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2125 /* If this is a UserBundle, make a note of what we've done */
2127 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2130 /* See if we already know about this one */
2131 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2132 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2136 if (i == _bundles_connected_to_outputs.end()) {
2137 /* We don't, so make a note */
2138 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2143 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2149 IO::disable_connecting ()
2151 connecting_legal = false;
2156 IO::enable_connecting ()
2158 connecting_legal = true;
2159 return ConnectingLegal ();
2163 IO::disable_ports ()
2165 ports_legal = false;
2173 return PortsLegal ();
2177 IO::disable_panners (void)
2179 panners_legal = false;
2184 IO::reset_panners ()
2186 panners_legal = true;
2187 return PannersLegal ();
2191 IO::bundle_configuration_will_change ()
2194 // connect_input_ports_to_bundle (_input_bundle, this);
2198 IO::bundle_configuration_has_changed ()
2201 // connect_input_ports_to_bundle (_input_bundle, this);
2205 IO::bundle_ports_will_change (int ignored)
2208 // connect_output_ports_to_bundle (_output_bundle, this);
2212 IO::bundle_ports_have_changed (int ignored)
2215 // connect_output_ports_to_bundle (_output_bundle, this);
2219 IO::GainControl::set_value (float val)
2221 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2222 if (val > 1.99526231f)
2226 _io.set_gain (val, this);
2228 Changed(); /* EMIT SIGNAL */
2232 IO::GainControl::get_value (void) const
2234 return AutomationControl::get_value();
2238 IO::setup_peak_meters()
2240 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2241 _meter->configure_io (max_streams, max_streams);
2245 Update the peak meters.
2247 The meter signal lock is taken to prevent modification of the
2248 Meter signal while updating the meters, taking the meter signal
2249 lock prior to taking the io_lock ensures that all IO will remain
2250 valid while metering.
2255 Glib::Mutex::Lock guard (m_meter_signal_lock);
2256 Meter(); /* EMIT SIGNAL */
2262 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2264 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2269 IO::clear_automation ()
2271 data().clear (); // clears gain automation
2272 _panner->clear_automation ();
2276 IO::set_parameter_automation_state (Parameter param, AutoState state)
2278 // XXX: would be nice to get rid of this special hack
2280 if (param.type() == GainAutomation) {
2282 bool changed = false;
2285 Glib::Mutex::Lock lm (control_lock());
2287 boost::shared_ptr<AutomationList> gain_auto
2288 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2290 if (state != gain_auto->automation_state()) {
2292 _last_automation_snapshot = 0;
2293 gain_auto->set_automation_state (state);
2296 // FIXME: shouldn't this use Curve?
2297 set_gain (gain_auto->eval (_session.transport_frame()), this);
2303 _session.set_dirty ();
2307 AutomatableControls::set_parameter_automation_state(param, state);
2312 IO::inc_gain (gain_t factor, void *src)
2314 if (_desired_gain == 0.0f)
2315 set_gain (0.000001f + (0.000001f * factor), src);
2317 set_gain (_desired_gain + (_desired_gain * factor), src);
2321 IO::set_gain (gain_t val, void *src)
2323 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2324 if (val > 1.99526231f)
2327 if (src != _gain_control.get()) {
2328 _gain_control->set_value(val);
2329 // bit twisty, this will come back and call us again
2330 // (this keeps control in sync with reality)
2335 Glib::Mutex::Lock dm (declick_lock);
2336 _desired_gain = val;
2339 if (_session.transport_stopped()) {
2343 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2344 _gain_control->list()->add (_session.transport_frame(), val);
2348 _session.set_dirty();
2352 IO::start_pan_touch (uint32_t which)
2354 if (which < _panner->size()) {
2355 (*_panner)[which]->pan_control()->start_touch();
2360 IO::end_pan_touch (uint32_t which)
2362 if (which < _panner->size()) {
2363 (*_panner)[which]->pan_control()->stop_touch();
2369 IO::automation_snapshot (nframes_t now, bool force)
2371 AutomatableControls::automation_snapshot (now, force);
2373 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2374 _panner->snapshot (now);
2377 _panner->snapshot (now);
2378 _last_automation_snapshot = now;
2382 IO::transport_stopped (nframes_t frame)
2384 _gain_control->list()->reposition_for_rt_add (frame);
2386 if (_gain_control->automation_state() != Off) {
2388 /* the src=0 condition is a special signal to not propagate
2389 automation gain changes into the mix group when locating.
2392 // FIXME: shouldn't this use Curve?
2393 set_gain (_gain_control->list()->eval (frame), 0);
2396 _panner->transport_stopped (frame);
2400 IO::build_legal_port_name (DataType type, bool in)
2402 const int name_size = jack_port_name_size();
2407 if (type == DataType::AUDIO) {
2408 suffix = _("audio");
2409 } else if (type == DataType::MIDI) {
2412 throw unknown_type();
2417 maxports = _input_maximum.get(type);
2419 suffix += _("_out");
2420 maxports = _output_maximum.get(type);
2423 if (maxports == 1) {
2424 // allow space for the slash + the suffix
2425 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2426 char buf[name_size+1];
2427 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2428 return string (buf);
2431 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2433 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2435 char buf1[name_size+1];
2436 char buf2[name_size+1];
2438 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2443 port_number = find_input_port_hole (buf1);
2445 port_number = find_output_port_hole (buf1);
2448 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2450 return string (buf2);
2454 IO::find_input_port_hole (const char* base)
2456 /* CALLER MUST HOLD IO LOCK */
2460 if (_inputs.empty()) {
2464 /* we only allow up to 4 characters for the port number
2467 for (n = 1; n < 9999; ++n) {
2468 char buf[jack_port_name_size()];
2469 PortSet::iterator i = _inputs.begin();
2471 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2473 for ( ; i != _inputs.end(); ++i) {
2474 if (i->short_name() == buf) {
2479 if (i == _inputs.end()) {
2487 IO::find_output_port_hole (const char* base)
2489 /* CALLER MUST HOLD IO LOCK */
2493 if (_outputs.empty()) {
2497 /* we only allow up to 4 characters for the port number
2500 for (n = 1; n < 9999; ++n) {
2501 char buf[jack_port_name_size()];
2502 PortSet::iterator i = _outputs.begin();
2504 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2506 for ( ; i != _outputs.end(); ++i) {
2507 if (i->short_name() == buf) {
2512 if (i == _outputs.end()) {
2521 IO::set_active (bool yn)
2524 active_changed(); /* EMIT SIGNAL */
2529 IO::audio_input(uint32_t n) const
2531 return dynamic_cast<AudioPort*>(input(n));
2535 IO::audio_output(uint32_t n) const
2537 return dynamic_cast<AudioPort*>(output(n));
2541 IO::midi_input(uint32_t n) const
2543 return dynamic_cast<MidiPort*>(input(n));
2547 IO::midi_output(uint32_t n) const
2549 return dynamic_cast<MidiPort*>(output(n));
2553 IO::set_phase_invert (bool yn, void *src)
2555 if (_phase_invert != yn) {
2557 // phase_invert_changed (src); /* EMIT SIGNAL */
2562 IO::set_denormal_protection (bool yn, void *src)
2564 if (_denormal_protection != yn) {
2565 _denormal_protection = yn;
2566 // denormal_protection_changed (src); /* EMIT SIGNAL */
2571 IO::update_port_total_latencies ()
2573 /* io_lock, not taken: function must be called from Session::process() calltree */
2575 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2576 _session.engine().update_total_latency (*i);
2579 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2580 _session.engine().update_total_latency (*i);
2586 * Setup bundles that describe our inputs and outputs.
2590 IO::setup_bundles_for_inputs_and_outputs ()
2594 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2595 _bundle_for_inputs->set_name (buf);
2596 uint32_t const ni = inputs().num_ports();
2597 _bundle_for_inputs->set_channels (ni);
2598 for (uint32_t i = 0; i < ni; ++i) {
2599 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2602 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2603 _bundle_for_outputs->set_name (buf);
2604 uint32_t const no = outputs().num_ports();
2605 _bundle_for_outputs->set_channels (no);
2606 for (uint32_t i = 0; i < no; ++i) {
2607 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2613 * Create and setup bundles that describe our inputs and outputs.
2617 IO::create_bundles_for_inputs_and_outputs ()
2619 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2620 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2621 setup_bundles_for_inputs_and_outputs ();
2624 /** Add a bundle to a list if is connected to our inputs.
2625 * @param b Bundle to check.
2626 * @param bundles List to add to.
2629 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2631 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2633 if (ab == 0 || ab->ports_are_outputs() == false) {
2637 if (ab->nchannels().get (default_type()) != n_inputs().n_total ()) {
2641 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2643 PortList const & pl = b->channel_ports (i);
2649 if (!input(i)->connected_to (pl[0])) {
2654 bundles->push_back (b);
2657 /** @return Bundles connected to our inputs */
2658 std::vector<boost::shared_ptr<Bundle> >
2659 IO::bundles_connected_to_inputs ()
2661 std::vector<boost::shared_ptr<Bundle> > bundles;
2664 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2665 bundles.push_back (i->bundle);
2669 _session.foreach_bundle (
2670 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2677 /** Add a bundle to a list if is connected to our outputs.
2678 * @param b Bundle to check.
2679 * @param bundles List to add to.
2682 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2684 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2685 if (ab == 0 || ab->ports_are_inputs() == false) {
2689 if (ab->nchannels ().get (default_type()) != n_outputs().n_total ()) {
2693 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2695 PortList const & pl = b->channel_ports (i);
2701 if (!output(i)->connected_to (pl[0])) {
2706 bundles->push_back (b);
2710 /* @return Bundles connected to our outputs */
2711 std::vector<boost::shared_ptr<Bundle> >
2712 IO::bundles_connected_to_outputs ()
2714 std::vector<boost::shared_ptr<Bundle> > bundles;
2717 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2718 bundles.push_back (i->bundle);
2722 _session.foreach_bundle (
2723 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2730 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2733 configuration_will_change = b->ConfigurationWillChange.connect (
2734 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2736 configuration_has_changed = b->ConfigurationHasChanged.connect (
2737 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2739 ports_will_change = b->PortsWillChange.connect (
2740 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2742 ports_have_changed = b->PortsHaveChanged.connect (
2743 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)