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/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/buffer_set.h>
44 #include <ardour/meter.h>
45 #include <ardour/amp.h>
46 #include <ardour/user_bundle.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(Evoral::Parameter(GainAutomation)));
143 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), 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 _session.add_controllable (_gain_control);
158 create_bundles_for_inputs_and_outputs ();
161 IO::IO (Session& s, const XMLNode& node, DataType dt)
162 : SessionObject(s, "unnamed io"),
163 AutomatableControls (s),
164 _output_buffers (new BufferSet()),
168 _meter = new PeakMeter (_session);
169 _public_ports = true; // XXX get this from node
172 no_panner_reset = false;
176 apply_gain_automation = false;
178 boost::shared_ptr<AutomationList> gl(
179 new AutomationList(Evoral::Parameter(GainAutomation)));
181 _gain_control = boost::shared_ptr<GainControl>(
182 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
184 add_control(_gain_control);
189 // IO::Meter is emitted from another thread so the
190 // Meter signal must be protected.
191 Glib::Mutex::Lock guard (m_meter_signal_lock);
192 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
195 _session.add_controllable (_gain_control);
197 create_bundles_for_inputs_and_outputs ();
202 Glib::Mutex::Lock guard (m_meter_signal_lock);
203 Glib::Mutex::Lock lm (io_lock);
205 BLOCK_PROCESS_CALLBACK ();
207 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
208 _session.engine().unregister_port (*i);
211 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
212 _session.engine().unregister_port (*i);
215 m_meter_connection.disconnect();
222 IO::silence (nframes_t nframes, nframes_t offset)
224 /* io_lock, not taken: function must be called from Session::process() calltree */
226 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
227 i->get_buffer(nframes,offset).silence (nframes, offset);
231 /** Deliver bufs to the IO's output ports
233 * This function should automatically do whatever it necessary to correctly deliver bufs
234 * to the outputs, eg applying gain or pan or whatever else needs to be done.
237 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
239 // FIXME: type specific code doesn't actually need to be here, it will go away in time
241 /* ********** AUDIO ********** */
243 // Apply gain if gain automation isn't playing
244 if ( ! apply_gain_automation) {
246 gain_t dg = _gain; // desired gain
249 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
257 if (dg != _gain || dg != 1.0) {
258 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
263 /* do this so that any processing that comes after deliver_outputs()
264 can use the output buffers.
267 output_buffers().attach_buffers (_outputs, nframes, offset);
269 // Use the panner to distribute audio to output port buffers
271 if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
273 /* blech .. we shouldn't be creating and tearing this down every process()
274 cycle. XXX fix me to not waste cycles and do memory allocation etc.
277 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
281 /* do a 1:1 copy of data to output ports */
283 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
284 copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
286 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
287 copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
293 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
295 // Copy any buffers 1:1 to outputs
297 PortSet::iterator o = _outputs.begin(type);
298 BufferSet::iterator i = bufs.begin(type);
299 BufferSet::iterator prev = i;
301 while (i != bufs.end(type) && o != _outputs.end (type)) {
303 Buffer& port_buffer (o->get_buffer (nframes, offset));
304 port_buffer.read_from (*i, nframes, offset);
311 /* extra outputs get a copy of the last buffer */
313 while (o != _outputs.end(type)) {
314 Buffer& port_buffer (o->get_buffer (nframes, offset));
315 port_buffer.read_from(*prev, nframes, offset);
321 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
323 assert(outs.available() >= n_inputs());
325 if (n_inputs() == ChanCount::ZERO)
328 outs.set_count(n_inputs());
330 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
332 BufferSet::iterator o = outs.begin(*t);
333 PortSet::iterator e = _inputs.end (*t);
334 for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
335 Buffer& b (i->get_buffer (nframes,offset));
336 o->read_from (b, nframes, offset);
343 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
344 nframes_t nframes, nframes_t offset)
346 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
348 collect_input (bufs, nframes, offset);
350 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
355 IO::check_bundles_connected_to_inputs ()
357 check_bundles (_bundles_connected_to_inputs, inputs());
361 IO::check_bundles_connected_to_outputs ()
363 check_bundles (_bundles_connected_to_outputs, outputs());
367 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
369 std::vector<UserBundleInfo> new_list;
371 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
373 uint32_t const N = i->bundle->nchannels ();
375 if (ports.num_ports (default_type()) < N) {
381 for (uint32_t j = 0; j < N; ++j) {
382 /* Every port on bundle channel j must be connected to our input j */
383 Bundle::PortList const pl = i->bundle->channel_ports (j);
384 for (uint32_t k = 0; k < pl.size(); ++k) {
385 if (ports.port(j)->connected_to (pl[k]) == false) {
397 new_list.push_back (*i);
399 i->configuration_changed.disconnect ();
400 i->ports_changed.disconnect ();
409 IO::disconnect_input (Port* our_port, string other_port, void* src)
411 if (other_port.length() == 0 || our_port == 0) {
416 BLOCK_PROCESS_CALLBACK ();
419 Glib::Mutex::Lock lm (io_lock);
421 /* check that our_port is really one of ours */
423 if ( ! _inputs.contains(our_port)) {
427 /* disconnect it from the source */
429 if (_session.engine().disconnect (other_port, our_port->name())) {
430 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
434 check_bundles_connected_to_inputs ();
438 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
439 _session.set_dirty ();
445 IO::connect_input (Port* our_port, string other_port, void* src)
447 if (other_port.length() == 0 || our_port == 0) {
452 BLOCK_PROCESS_CALLBACK ();
455 Glib::Mutex::Lock lm (io_lock);
457 /* check that our_port is really one of ours */
459 if ( ! _inputs.contains(our_port) ) {
463 /* connect it to the source */
465 if (_session.engine().connect (other_port, our_port->name())) {
471 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
472 _session.set_dirty ();
477 IO::disconnect_output (Port* our_port, string other_port, void* src)
479 if (other_port.length() == 0 || our_port == 0) {
484 BLOCK_PROCESS_CALLBACK ();
487 Glib::Mutex::Lock lm (io_lock);
489 /* check that our_port is really one of ours */
491 if ( ! _outputs.contains(our_port) ) {
495 /* disconnect it from the destination */
497 if (_session.engine().disconnect (our_port->name(), other_port)) {
498 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
502 check_bundles_connected_to_outputs ();
506 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
507 _session.set_dirty ();
512 IO::connect_output (Port* our_port, string other_port, void* src)
514 if (other_port.length() == 0 || our_port == 0) {
519 BLOCK_PROCESS_CALLBACK ();
523 Glib::Mutex::Lock lm (io_lock);
525 /* check that our_port is really one of ours */
527 if ( ! _outputs.contains(our_port) ) {
531 /* connect it to the destination */
533 if (_session.engine().connect (our_port->name(), other_port)) {
539 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
540 _session.set_dirty ();
545 IO::set_input (Port* other_port, void* src)
547 /* this removes all but one ports, and connects that one port
548 to the specified source.
551 if (_input_minimum.n_total() > 1) {
552 /* sorry, you can't do this */
556 if (other_port == 0) {
557 if (_input_minimum == ChanCount::ZERO) {
558 return ensure_inputs (ChanCount::ZERO, false, true, src);
564 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
568 return connect_input (_inputs.port(0), other_port->name(), src);
572 IO::remove_output_port (Port* port, void* src)
574 IOChange change (NoChange);
577 BLOCK_PROCESS_CALLBACK ();
581 Glib::Mutex::Lock lm (io_lock);
583 if (n_outputs() <= _output_minimum) {
584 /* sorry, you can't do this */
588 if (_outputs.remove(port)) {
589 change = IOChange (change|ConfigurationChanged);
591 if (port->connected()) {
592 change = IOChange (change|ConnectionsChanged);
595 _session.engine().unregister_port (*port);
596 check_bundles_connected_to_outputs ();
598 setup_peak_meters ();
603 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
606 if (change == ConfigurationChanged) {
607 setup_bundles_for_inputs_and_outputs ();
610 if (change != NoChange) {
611 output_changed (change, src);
612 _session.set_dirty ();
619 /** Add an output port.
621 * @param destination Name of input port to connect new port to.
622 * @param src Source for emitted ConfigurationChanged signal.
623 * @param type Data type of port. Default value (NIL) will use this IO's default type.
626 IO::add_output_port (string destination, void* src, DataType type)
630 if (type == DataType::NIL)
631 type = _default_type;
634 BLOCK_PROCESS_CALLBACK ();
638 Glib::Mutex::Lock lm (io_lock);
640 if (n_outputs() >= _output_maximum) {
644 /* Create a new output port */
646 string portname = build_legal_port_name (type, false);
648 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
649 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
653 _outputs.add (our_port);
654 setup_peak_meters ();
658 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
661 if (destination.length()) {
662 if (_session.engine().connect (our_port->name(), destination)) {
667 // pan_changed (src); /* EMIT SIGNAL */
668 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
669 setup_bundles_for_inputs_and_outputs ();
670 _session.set_dirty ();
676 IO::remove_input_port (Port* port, void* src)
678 IOChange change (NoChange);
681 BLOCK_PROCESS_CALLBACK ();
685 Glib::Mutex::Lock lm (io_lock);
687 if (n_inputs() <= _input_minimum) {
688 /* sorry, you can't do this */
692 if (_inputs.remove(port)) {
693 change = IOChange (change|ConfigurationChanged);
695 if (port->connected()) {
696 change = IOChange (change|ConnectionsChanged);
699 _session.engine().unregister_port (*port);
700 check_bundles_connected_to_inputs ();
702 setup_peak_meters ();
707 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
710 if (change == ConfigurationChanged) {
711 setup_bundles_for_inputs_and_outputs ();
714 if (change != NoChange) {
715 input_changed (change, src);
716 _session.set_dirty ();
724 /** Add an input port.
726 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
727 * @param destination Name of input port to connect new port to.
728 * @param src Source for emitted ConfigurationChanged signal.
731 IO::add_input_port (string source, void* src, DataType type)
735 if (type == DataType::NIL)
736 type = _default_type;
739 BLOCK_PROCESS_CALLBACK ();
742 Glib::Mutex::Lock lm (io_lock);
744 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
748 /* Create a new input port */
750 string portname = build_legal_port_name (type, true);
752 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
753 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
757 _inputs.add (our_port);
758 setup_peak_meters ();
762 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
765 if (source.length()) {
767 if (_session.engine().connect (source, our_port->name())) {
772 // pan_changed (src); /* EMIT SIGNAL */
773 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
774 setup_bundles_for_inputs_and_outputs ();
775 _session.set_dirty ();
781 IO::disconnect_inputs (void* src)
784 BLOCK_PROCESS_CALLBACK ();
787 Glib::Mutex::Lock lm (io_lock);
789 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
790 _session.engine().disconnect (*i);
793 check_bundles_connected_to_inputs ();
797 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
803 IO::disconnect_outputs (void* src)
806 BLOCK_PROCESS_CALLBACK ();
809 Glib::Mutex::Lock lm (io_lock);
811 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
812 _session.engine().disconnect (*i);
815 check_bundles_connected_to_outputs ();
819 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
820 _session.set_dirty ();
826 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
828 Port* input_port = 0;
829 bool changed = false;
832 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
834 const size_t n = count.get(*t);
836 /* remove unused ports */
837 for (size_t i = n_inputs().get(*t); i > n; --i) {
838 input_port = _inputs.port(*t, i-1);
841 _inputs.remove(input_port);
842 _session.engine().unregister_port (*input_port);
847 /* create any necessary new ports */
848 while (n_inputs().get(*t) < n) {
850 string portname = build_legal_port_name (*t, true);
854 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
855 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
860 catch (AudioEngine::PortRegistrationFailure& err) {
861 setup_peak_meters ();
864 throw AudioEngine::PortRegistrationFailure();
867 _inputs.add (input_port);
873 check_bundles_connected_to_inputs ();
874 setup_peak_meters ();
876 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
877 _session.set_dirty ();
881 /* disconnect all existing ports so that we get a fresh start */
882 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
883 _session.engine().disconnect (*i);
891 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
893 bool in_changed = false;
894 bool out_changed = false;
895 bool need_pan_reset = false;
897 in = min (_input_maximum, in);
899 out = min (_output_maximum, out);
901 if (in == n_inputs() && out == n_outputs() && !clear) {
906 BLOCK_PROCESS_CALLBACK ();
907 Glib::Mutex::Lock lm (io_lock);
911 if (n_outputs() != out) {
912 need_pan_reset = true;
915 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
917 const size_t nin = in.get(*t);
918 const size_t nout = out.get(*t);
920 Port* output_port = 0;
921 Port* input_port = 0;
923 /* remove unused output ports */
924 for (size_t i = n_outputs().get(*t); i > nout; --i) {
925 output_port = _outputs.port(*t, i-1);
928 _outputs.remove(output_port);
929 _session.engine().unregister_port (*output_port);
934 /* remove unused input ports */
935 for (size_t i = n_inputs().get(*t); i > nin; --i) {
936 input_port = _inputs.port(*t, i-1);
939 _inputs.remove(input_port);
940 _session.engine().unregister_port (*input_port);
945 /* create any necessary new input ports */
947 while (n_inputs().get(*t) < nin) {
949 string portname = build_legal_port_name (*t, true);
952 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
953 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
958 catch (AudioEngine::PortRegistrationFailure& err) {
959 setup_peak_meters ();
962 throw AudioEngine::PortRegistrationFailure();
969 /* create any necessary new output ports */
971 while (n_outputs().get(*t) < nout) {
973 string portname = build_legal_port_name (*t, false);
976 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
977 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
982 catch (AudioEngine::PortRegistrationFailure& err) {
983 setup_peak_meters ();
986 throw AudioEngine::PortRegistrationFailure ();
996 /* disconnect all existing ports so that we get a fresh start */
998 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
999 _session.engine().disconnect (*i);
1002 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1003 _session.engine().disconnect (*i);
1007 if (in_changed || out_changed) {
1008 setup_peak_meters ();
1014 check_bundles_connected_to_outputs ();
1015 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1019 check_bundles_connected_to_inputs ();
1020 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1023 if (in_changed || out_changed) {
1024 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1025 setup_bundles_for_inputs_and_outputs ();
1026 _session.set_dirty ();
1033 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1035 bool changed = false;
1037 count = min (_input_maximum, count);
1039 if (count == n_inputs() && !clear) {
1044 BLOCK_PROCESS_CALLBACK ();
1045 Glib::Mutex::Lock im (io_lock);
1046 changed = ensure_inputs_locked (count, clear, src);
1048 changed = ensure_inputs_locked (count, clear, src);
1052 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1053 setup_bundles_for_inputs_and_outputs ();
1054 _session.set_dirty ();
1060 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1062 Port* output_port = 0;
1063 bool changed = false;
1064 bool need_pan_reset = false;
1066 if (n_outputs() != count) {
1067 need_pan_reset = true;
1070 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1072 const size_t n = count.get(*t);
1074 /* remove unused ports */
1075 for (size_t i = n_outputs().get(*t); i > n; --i) {
1076 output_port = _outputs.port(*t, i-1);
1078 assert(output_port);
1079 _outputs.remove(output_port);
1080 _session.engine().unregister_port (*output_port);
1085 /* create any necessary new ports */
1086 while (n_outputs().get(*t) < n) {
1088 string portname = build_legal_port_name (*t, false);
1090 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1091 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1095 _outputs.add (output_port);
1097 setup_peak_meters ();
1099 if (need_pan_reset) {
1106 check_bundles_connected_to_outputs ();
1107 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1108 _session.set_dirty ();
1112 /* disconnect all existing ports so that we get a fresh start */
1113 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1114 _session.engine().disconnect (*i);
1122 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1124 bool changed = false;
1126 if (_output_maximum < ChanCount::INFINITE) {
1127 count = min (_output_maximum, count);
1128 if (count == n_outputs() && !clear) {
1133 /* XXX caller should hold io_lock, but generally doesn't */
1136 BLOCK_PROCESS_CALLBACK ();
1137 Glib::Mutex::Lock im (io_lock);
1138 changed = ensure_outputs_locked (count, clear, src);
1140 changed = ensure_outputs_locked (count, clear, src);
1144 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1145 setup_bundles_for_inputs_and_outputs ();
1152 IO::effective_gain () const
1154 if (_gain_control->automation_playback()) {
1155 return _gain_control->get_value();
1157 return _desired_gain;
1164 if (panners_legal) {
1165 if (!no_panner_reset) {
1166 _panner->reset (n_outputs().n_audio(), pans_required());
1169 panner_legal_c.disconnect ();
1170 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1175 IO::panners_became_legal ()
1177 _panner->reset (n_outputs().n_audio(), pans_required());
1178 _panner->load (); // automation
1179 panner_legal_c.disconnect ();
1184 IO::defer_pan_reset ()
1186 no_panner_reset = true;
1190 IO::allow_pan_reset ()
1192 no_panner_reset = false;
1198 IO::get_state (void)
1200 return state (true);
1204 IO::state (bool full_state)
1206 XMLNode* node = new XMLNode (state_node_name);
1209 vector<string>::iterator ci;
1211 LocaleGuard lg (X_("POSIX"));
1212 Glib::Mutex::Lock lm (io_lock);
1214 node->add_property("name", _name);
1215 id().print (buf, sizeof (buf));
1216 node->add_property("id", buf);
1219 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1220 i != _bundles_connected_to_inputs.end();
1224 XMLNode* n = new XMLNode ("InputBundle");
1225 n->add_property ("name", i->bundle->name ());
1226 node->add_child_nocopy (*n);
1230 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1231 i != _bundles_connected_to_outputs.end();
1235 XMLNode* n = new XMLNode ("OutputBundle");
1236 n->add_property ("name", i->bundle->name ());
1237 node->add_child_nocopy (*n);
1242 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1244 vector<string> connections;
1246 if (i->get_connections (connections)) {
1250 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1255 /* if its a connection to our own port,
1256 return only the port name, not the
1257 whole thing. this allows connections
1258 to be re-established even when our
1259 client name is different.
1262 str += _session.engine().make_port_name_relative (*ci);
1272 node->add_property ("inputs", str);
1276 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1278 vector<string> connections;
1280 if (i->get_connections (connections)) {
1284 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1289 str += _session.engine().make_port_name_relative (*ci);
1299 node->add_property ("outputs", str);
1301 node->add_child_nocopy (_panner->state (full_state));
1302 node->add_child_nocopy (_gain_control->get_state ());
1304 snprintf (buf, sizeof(buf), "%2.12f", gain());
1305 node->add_property ("gain", buf);
1307 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1311 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1312 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1314 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1316 node->add_property ("iolimits", buf);
1321 node->add_child_nocopy (get_automation_state());
1327 IO::set_state (const XMLNode& node)
1329 const XMLProperty* prop;
1330 XMLNodeConstIterator iter;
1331 LocaleGuard lg (X_("POSIX"));
1333 /* force use of non-localized representation of decimal point,
1334 since we use it a lot in XML files and so forth.
1337 if (node.name() != state_node_name) {
1338 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1342 if ((prop = node.property ("name")) != 0) {
1343 _name = prop->value();
1344 /* used to set panner name with this, but no more */
1347 if ((prop = node.property ("id")) != 0) {
1348 _id = prop->value ();
1356 if ((prop = node.property ("iolimits")) != 0) {
1357 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1358 &in_min, &in_max, &out_min, &out_max);
1360 /* Correct for the difference between the way we write things to session files and the
1361 way things are described by ChanCount; see comments in io.h about what the different
1362 ChanCount values mean. */
1365 _input_minimum = ChanCount::ZERO;
1367 _input_minimum = ChanCount (_default_type, in_min);
1371 _input_maximum = ChanCount::INFINITE;
1373 _input_maximum = ChanCount (_default_type, in_max);
1377 _output_minimum = ChanCount::ZERO;
1379 _output_minimum = ChanCount (_default_type, out_min);
1383 _output_maximum = ChanCount::INFINITE;
1385 _output_maximum = ChanCount (_default_type, out_max);
1389 if ((prop = node.property ("gain")) != 0) {
1390 set_gain (atof (prop->value().c_str()), this);
1391 _gain = _desired_gain;
1394 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1395 /* old school automation handling */
1398 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1400 // Old school Panner.
1401 if ((*iter)->name() == "Panner") {
1403 _panner = new Panner (_name, _session);
1405 _panner->set_state (**iter);
1408 if ((*iter)->name() == "Processor") {
1409 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1411 _panner = new Panner (_name, _session);
1413 _panner->set_state (**iter);
1417 if ((*iter)->name() == X_("Automation")) {
1419 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1422 if ((*iter)->name() == X_("controllable")) {
1423 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1424 _gain_control->set_state (**iter);
1431 if (create_ports (node)) {
1437 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1441 _panner = new Panner( _name, _session );
1442 if (panners_legal) {
1445 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1448 if (connecting_legal) {
1450 if (make_connections (node)) {
1456 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1459 if (!ports_legal || !connecting_legal) {
1460 pending_state_node = new XMLNode (node);
1467 IO::load_automation (string path)
1472 uint32_t linecnt = 0;
1474 LocaleGuard lg (X_("POSIX"));
1476 fullpath = Glib::build_filename(_session.automation_dir(), path);
1478 in.open (fullpath.c_str());
1481 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1483 in.open (fullpath.c_str());
1486 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1491 clear_automation ();
1493 while (in.getline (line, sizeof(line), '\n')) {
1498 if (++linecnt == 1) {
1499 if (memcmp (line, "version", 7) == 0) {
1500 if (sscanf (line, "version %f", &version) != 1) {
1501 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1505 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1512 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1513 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1519 _gain_control->list()->fast_simple_add (when, value);
1529 /* older (pre-1.0) versions of ardour used this */
1533 warning << _("dubious automation event found (and ignored)") << endmsg;
1541 IO::connecting_became_legal ()
1545 if (pending_state_node == 0) {
1546 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1551 connection_legal_c.disconnect ();
1553 ret = make_connections (*pending_state_node);
1556 delete pending_state_node;
1557 pending_state_node = 0;
1563 IO::ports_became_legal ()
1567 if (pending_state_node == 0) {
1568 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1573 port_legal_c.disconnect ();
1575 ret = create_ports (*pending_state_node);
1577 if (connecting_legal) {
1578 delete pending_state_node;
1579 pending_state_node = 0;
1585 boost::shared_ptr<Bundle>
1586 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1588 static const string digits = "0123456789";
1590 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1593 int bundle_number, mask;
1594 string possible_name;
1595 bool stereo = false;
1596 string::size_type last_non_digit_pos;
1598 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1601 // find numeric suffix of desired name
1604 last_non_digit_pos = desired_name.find_last_not_of(digits);
1606 if (last_non_digit_pos != string::npos) {
1608 s << desired_name.substr(last_non_digit_pos);
1612 // see if it's a stereo connection e.g. "in 3+4"
1614 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1615 int left_bundle_number = 0;
1616 string::size_type left_last_non_digit_pos;
1618 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1620 if (left_last_non_digit_pos != string::npos) {
1622 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1623 s >> left_bundle_number;
1625 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1636 // find highest set bit
1638 while ((mask <= bundle_number) && (mask <<= 1));
1640 // "wrap" bundle number into largest possible power of 2
1645 if (bundle_number & mask) {
1646 bundle_number &= ~mask;
1649 s << default_name << " " << bundle_number + 1;
1652 s << "+" << bundle_number + 2;
1655 possible_name = s.str();
1657 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1664 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1667 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1678 IO::create_ports (const XMLNode& node)
1680 XMLProperty const * prop;
1681 uint32_t num_inputs = 0;
1682 uint32_t num_outputs = 0;
1684 if ((prop = node.property ("input-connection")) != 0) {
1686 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1692 num_inputs = c->nchannels();
1694 } else if ((prop = node.property ("inputs")) != 0) {
1696 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1699 if ((prop = node.property ("output-connection")) != 0) {
1701 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1707 num_outputs = c->nchannels ();
1709 } else if ((prop = node.property ("outputs")) != 0) {
1711 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1714 no_panner_reset = true;
1716 if (ensure_io (ChanCount (_default_type, num_inputs),
1717 ChanCount (_default_type, num_outputs),
1720 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1724 no_panner_reset = false;
1726 set_deferred_state ();
1734 IO::make_connections (const XMLNode& node)
1737 const XMLProperty* prop;
1739 if ((prop = node.property ("input-connection")) != 0) {
1740 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1746 connect_input_ports_to_bundle (c, this);
1748 } else if ((prop = node.property ("inputs")) != 0) {
1749 if (set_inputs (prop->value())) {
1750 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1755 if ((prop = node.property ("output-connection")) != 0) {
1756 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1762 connect_output_ports_to_bundle (c, this);
1764 } else if ((prop = node.property ("outputs")) != 0) {
1765 if (set_outputs (prop->value())) {
1766 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1771 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1773 if ((*i)->name() == "InputBundle") {
1774 XMLProperty const * prop = (*i)->property ("name");
1776 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1778 connect_input_ports_to_bundle (b, this);
1782 } else if ((*i)->name() == "OutputBundle") {
1783 XMLProperty const * prop = (*i)->property ("name");
1785 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1787 connect_output_ports_to_bundle (b, this);
1797 IO::set_inputs (const string& str)
1799 vector<string> ports;
1804 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1808 // FIXME: audio-only
1809 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1813 string::size_type start, end, ostart;
1820 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1823 if ((end = str.find_first_of ('}', start)) == string::npos) {
1824 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1828 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1829 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1835 for (int x = 0; x < n; ++x) {
1836 connect_input (input (i), ports[x], this);
1848 IO::set_outputs (const string& str)
1850 vector<string> ports;
1855 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1859 // FIXME: audio-only
1860 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1864 string::size_type start, end, ostart;
1871 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1874 if ((end = str.find_first_of ('}', start)) == string::npos) {
1875 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1879 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1880 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1886 for (int x = 0; x < n; ++x) {
1887 connect_output (output (i), ports[x], this);
1899 IO::parse_io_string (const string& str, vector<string>& ports)
1901 string::size_type pos, opos;
1903 if (str.length() == 0) {
1912 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1913 ports.push_back (str.substr (opos, pos - opos));
1917 if (opos < str.length()) {
1918 ports.push_back (str.substr(opos));
1921 return ports.size();
1925 IO::parse_gain_string (const string& str, vector<string>& ports)
1927 string::size_type pos, opos;
1933 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1934 ports.push_back (str.substr (opos, pos - opos));
1938 if (opos < str.length()) {
1939 ports.push_back (str.substr(opos));
1942 return ports.size();
1946 IO::set_name (const string& requested_name)
1948 if (requested_name == _name) {
1954 if ( (rt = dynamic_cast<Route *>(this))) {
1955 name = Route::ensure_track_or_route_name(requested_name, _session);
1957 name = requested_name;
1961 /* replace all colons in the name. i wish we didn't have to do this */
1963 if (replace_all (name, ":", "-")) {
1964 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1967 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1968 string current_name = i->name();
1969 current_name.replace (current_name.find (_name), _name.length(), name);
1970 i->set_name (current_name);
1973 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1974 string current_name = i->name();
1975 current_name.replace (current_name.find (_name), _name.length(), name);
1976 i->set_name (current_name);
1979 bool const r = SessionObject::set_name(name);
1981 setup_bundles_for_inputs_and_outputs ();
1987 IO::set_input_minimum (ChanCount n)
1993 IO::set_input_maximum (ChanCount n)
1999 IO::set_output_minimum (ChanCount n)
2001 _output_minimum = n;
2005 IO::set_output_maximum (ChanCount n)
2007 _output_maximum = n;
2011 IO::set_port_latency (nframes_t nframes)
2013 Glib::Mutex::Lock lm (io_lock);
2015 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2016 i->set_latency (nframes);
2021 IO::output_latency () const
2023 nframes_t max_latency;
2028 /* io lock not taken - must be protected by other means */
2030 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2031 if ((latency = i->total_latency ()) > max_latency) {
2032 max_latency = latency;
2040 IO::input_latency () const
2042 nframes_t max_latency;
2047 /* io lock not taken - must be protected by other means */
2049 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2050 if ((latency = i->total_latency ()) > max_latency) {
2051 max_latency = latency;
2059 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2062 BLOCK_PROCESS_CALLBACK ();
2063 Glib::Mutex::Lock lm2 (io_lock);
2065 /* Connect to the bundle, not worrying about any connections
2066 that are already made. */
2068 uint32_t cnt = c->nchannels ();
2070 for (uint32_t n = 0; n < cnt; ++n) {
2071 const Bundle::PortList& pl = c->channel_ports (n);
2073 for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2075 if (!_inputs.port(n)->connected_to (*i)) {
2077 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2085 /* If this is a UserBundle, make a note of what we've done */
2087 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2090 /* See if we already know about this one */
2091 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2092 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2096 if (i == _bundles_connected_to_inputs.end()) {
2097 /* We don't, so make a note */
2098 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2103 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2108 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2111 BLOCK_PROCESS_CALLBACK ();
2112 Glib::Mutex::Lock lm2 (io_lock);
2114 /* Connect to the bundle, not worrying about any connections
2115 that are already made. */
2117 uint32_t cnt = c->nchannels ();
2119 for (uint32_t n = 0; n < cnt; ++n) {
2121 const Bundle::PortList& pl = c->channel_ports (n);
2123 for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2125 if (!_outputs.port(n)->connected_to (*i)) {
2127 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2134 /* If this is a UserBundle, make a note of what we've done */
2136 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2139 /* See if we already know about this one */
2140 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2141 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2145 if (i == _bundles_connected_to_outputs.end()) {
2146 /* We don't, so make a note */
2147 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2152 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2158 IO::disable_connecting ()
2160 connecting_legal = false;
2165 IO::enable_connecting ()
2167 connecting_legal = true;
2168 return ConnectingLegal ();
2172 IO::disable_ports ()
2174 ports_legal = false;
2182 return PortsLegal ();
2186 IO::disable_panners (void)
2188 panners_legal = false;
2193 IO::reset_panners ()
2195 panners_legal = true;
2196 return PannersLegal ();
2200 IO::bundle_configuration_changed ()
2203 // connect_input_ports_to_bundle (_input_bundle, this);
2207 IO::bundle_ports_changed (int ignored)
2210 // connect_output_ports_to_bundle (_output_bundle, this);
2214 IO::GainControl::set_value (float val)
2216 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2217 if (val > 1.99526231f)
2220 _io->set_gain (val, this);
2222 AutomationControl::set_value(val);
2226 IO::GainControl::get_value (void) const
2228 return AutomationControl::get_value();
2232 IO::setup_peak_meters()
2234 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2235 _meter->configure_io (max_streams, max_streams);
2239 Update the peak meters.
2241 The meter signal lock is taken to prevent modification of the
2242 Meter signal while updating the meters, taking the meter signal
2243 lock prior to taking the io_lock ensures that all IO will remain
2244 valid while metering.
2249 Glib::Mutex::Lock guard (m_meter_signal_lock);
2250 Meter(); /* EMIT SIGNAL */
2256 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2258 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2263 IO::clear_automation ()
2265 data().clear (); // clears gain automation
2266 _panner->data().clear();
2270 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2272 // XXX: would be nice to get rid of this special hack
2274 if (param.type() == GainAutomation) {
2276 bool changed = false;
2279 Glib::Mutex::Lock lm (control_lock());
2281 boost::shared_ptr<AutomationList> gain_auto
2282 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2284 if (state != gain_auto->automation_state()) {
2286 _last_automation_snapshot = 0;
2287 gain_auto->set_automation_state (state);
2290 // FIXME: shouldn't this use Curve?
2291 set_gain (gain_auto->eval (_session.transport_frame()), this);
2297 _session.set_dirty ();
2301 AutomatableControls::set_parameter_automation_state(param, state);
2306 IO::inc_gain (gain_t factor, void *src)
2308 if (_desired_gain == 0.0f)
2309 set_gain (0.000001f + (0.000001f * factor), src);
2311 set_gain (_desired_gain + (_desired_gain * factor), src);
2315 IO::set_gain (gain_t val, void *src)
2317 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2318 if (val > 1.99526231f) {
2322 cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2324 if (src != _gain_control.get()) {
2325 _gain_control->set_value(val);
2326 // bit twisty, this will come back and call us again
2327 // (this keeps control in sync with reality)
2332 Glib::Mutex::Lock dm (declick_lock);
2333 _desired_gain = val;
2336 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);
2347 _session.set_dirty();
2351 IO::start_pan_touch (uint32_t which)
2353 if (which < _panner->npanners()) {
2354 (*_panner).pan_control(which)->start_touch();
2359 IO::end_pan_touch (uint32_t which)
2361 if (which < _panner->npanners()) {
2362 (*_panner).pan_control(which)->stop_touch();
2368 IO::automation_snapshot (nframes_t now, bool force)
2370 AutomatableControls::automation_snapshot (now, force);
2371 // XXX: This seems to be wrong.
2372 // drobilla: shouldnt automation_snapshot for panner be called
2373 // "automagically" because its an Automatable now ?
2375 // we could dump this whole method then. <3
2377 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2378 _panner->automation_snapshot (now, force);
2381 _panner->automation_snapshot (now, force);
2382 _last_automation_snapshot = now;
2386 IO::transport_stopped (nframes_t frame)
2388 _gain_control->list()->reposition_for_rt_add (frame);
2390 if (_gain_control->automation_state() != Off) {
2392 /* the src=0 condition is a special signal to not propagate
2393 automation gain changes into the mix group when locating.
2396 // FIXME: shouldn't this use Curve?
2397 set_gain (_gain_control->list()->eval (frame), 0);
2400 _panner->transport_stopped (frame);
2404 IO::build_legal_port_name (DataType type, bool in)
2406 const int name_size = jack_port_name_size();
2411 if (type == DataType::AUDIO) {
2412 suffix = _("audio");
2413 } else if (type == DataType::MIDI) {
2416 throw unknown_type();
2421 maxports = _input_maximum.get(type);
2423 suffix += _("_out");
2424 maxports = _output_maximum.get(type);
2427 if (maxports == 1) {
2428 // allow space for the slash + the suffix
2429 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2430 char buf[name_size+1];
2431 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2432 return string (buf);
2435 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2437 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2439 char buf1[name_size+1];
2440 char buf2[name_size+1];
2442 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2447 port_number = find_input_port_hole (buf1);
2449 port_number = find_output_port_hole (buf1);
2452 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2454 return string (buf2);
2458 IO::find_input_port_hole (const char* base)
2460 /* CALLER MUST HOLD IO LOCK */
2464 if (_inputs.empty()) {
2468 /* we only allow up to 4 characters for the port number
2471 for (n = 1; n < 9999; ++n) {
2472 char buf[jack_port_name_size()];
2473 PortSet::iterator i = _inputs.begin();
2475 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2477 for ( ; i != _inputs.end(); ++i) {
2478 if (i->name() == buf) {
2483 if (i == _inputs.end()) {
2491 IO::find_output_port_hole (const char* base)
2493 /* CALLER MUST HOLD IO LOCK */
2497 if (_outputs.empty()) {
2501 /* we only allow up to 4 characters for the port number
2504 for (n = 1; n < 9999; ++n) {
2505 char buf[jack_port_name_size()];
2506 PortSet::iterator i = _outputs.begin();
2508 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2510 for ( ; i != _outputs.end(); ++i) {
2511 if (i->name() == buf) {
2516 if (i == _outputs.end()) {
2525 IO::set_active (bool yn)
2528 active_changed(); /* EMIT SIGNAL */
2532 IO::audio_input(uint32_t n) const
2534 return dynamic_cast<AudioPort*>(input(n));
2538 IO::audio_output(uint32_t n) const
2540 return dynamic_cast<AudioPort*>(output(n));
2544 IO::midi_input(uint32_t n) const
2546 return dynamic_cast<MidiPort*>(input(n));
2550 IO::midi_output(uint32_t n) const
2552 return dynamic_cast<MidiPort*>(output(n));
2556 IO::set_phase_invert (bool yn, void *src)
2558 if (_phase_invert != yn) {
2560 // phase_invert_changed (src); /* EMIT SIGNAL */
2565 IO::set_denormal_protection (bool yn, void *src)
2567 if (_denormal_protection != yn) {
2568 _denormal_protection = yn;
2569 // denormal_protection_changed (src); /* EMIT SIGNAL */
2574 IO::update_port_total_latencies ()
2576 /* io_lock, not taken: function must be called from Session::process() calltree */
2578 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2579 _session.engine().update_total_latency (*i);
2582 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2583 _session.engine().update_total_latency (*i);
2589 * Setup bundles that describe our inputs and outputs.
2593 IO::setup_bundles_for_inputs_and_outputs ()
2597 _bundle_for_inputs->remove_channels ();
2598 _bundle_for_outputs->remove_channels ();
2600 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2601 _bundle_for_inputs->set_name (buf);
2602 uint32_t const ni = inputs().num_ports();
2603 for (uint32_t i = 0; i < ni; ++i) {
2604 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2605 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2608 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2609 _bundle_for_outputs->set_name (buf);
2610 uint32_t const no = outputs().num_ports();
2611 for (uint32_t i = 0; i < no; ++i) {
2612 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2613 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2619 * Create and setup bundles that describe our inputs and outputs.
2623 IO::create_bundles_for_inputs_and_outputs ()
2625 _bundle_for_inputs = boost::shared_ptr<Bundle> (new Bundle (true));
2626 _bundle_for_outputs = boost::shared_ptr<Bundle> (new Bundle (false));
2627 setup_bundles_for_inputs_and_outputs ();
2630 /** @return Bundles connected to our inputs */
2632 IO::bundles_connected_to_inputs ()
2637 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2638 bundles.push_back (i->bundle);
2641 /* Normal bundles */
2642 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2643 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2644 if ((*i)->ports_are_outputs() == false || (*i)->nchannels() != n_inputs().n_total()) {
2648 for (uint32_t j = 0; j < n_inputs().n_total(); ++j) {
2650 Bundle::PortList const& pl = (*i)->channel_ports (j);
2651 if (!pl.empty() && input(j)->connected_to (pl[0])) {
2652 bundles.push_back (*i);
2662 /* @return Bundles connected to our outputs */
2664 IO::bundles_connected_to_outputs ()
2669 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2670 bundles.push_back (i->bundle);
2674 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2675 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2676 if ((*i)->ports_are_inputs() == false || (*i)->nchannels() != n_outputs().n_total()) {
2680 for (uint32_t j = 0; j < n_outputs().n_total(); ++j) {
2682 Bundle::PortList const& pl = (*i)->channel_ports (j);
2684 if (!pl.empty() && output(j)->connected_to (pl[0])) {
2685 bundles.push_back (*i);
2694 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2697 configuration_changed = b->ConfigurationChanged.connect (
2698 sigc::mem_fun (*io, &IO::bundle_configuration_changed)
2700 ports_changed = b->PortsChanged.connect (
2701 sigc::mem_fun (*io, &IO::bundle_ports_changed)
2706 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2708 /* io_lock, not taken: function must be called from Session::process() calltree */
2712 IO::flush_outputs (nframes_t nframes, nframes_t offset)
2714 /* io_lock, not taken: function must be called from Session::process() calltree */
2715 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2717 /* Only run cycle_start() on output ports, because
2718 inputs must be done in the correct processing order,
2719 which requires interleaving with route processing.
2722 (*i).flush_buffers (nframes, offset);
2728 IO::bundle_channel_name (uint32_t c, uint32_t n) const
2736 return c == 0 ? _("L") : _("R");
2738 snprintf (buf, sizeof(buf), _("%d"), (c + 1));