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;
78 sigc::signal<void,nframes_t> IO::CycleStart;
80 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
82 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
83 others can be imagined.
87 static gain_t direct_control_to_gain (double fract) {
88 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
89 /* this maxes at +6dB */
90 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
93 static double direct_gain_to_control (gain_t gain) {
94 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
95 if (gain == 0) return 0.0;
97 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
101 /** @param default_type The type of port that will be created by ensure_io
102 * and friends if no type is explicitly requested (to avoid breakage).
104 IO::IO (Session& s, const string& name,
105 int input_min, int input_max, int output_min, int output_max,
106 DataType default_type)
107 : SessionObject(s, name),
108 AutomatableControls (s),
109 _output_buffers (new BufferSet()),
111 _default_type (default_type),
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));
157 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
159 _session.add_controllable (_gain_control);
161 setup_bundles_for_inputs_and_outputs ();
164 IO::IO (Session& s, const XMLNode& node, DataType dt)
165 : SessionObject(s, "unnamed io"),
166 AutomatableControls (s),
167 _output_buffers (new BufferSet()),
171 _meter = new PeakMeter (_session);
174 no_panner_reset = false;
178 apply_gain_automation = false;
180 boost::shared_ptr<AutomationList> gl(
181 new AutomationList(Evoral::Parameter(GainAutomation)));
183 _gain_control = boost::shared_ptr<GainControl>(
184 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
186 add_control(_gain_control);
191 // IO::Meter is emitted from another thread so the
192 // Meter signal must be protected.
193 Glib::Mutex::Lock guard (m_meter_signal_lock);
194 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
198 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
200 _session.add_controllable (_gain_control);
202 setup_bundles_for_inputs_and_outputs ();
207 Glib::Mutex::Lock guard (m_meter_signal_lock);
208 Glib::Mutex::Lock lm (io_lock);
210 BLOCK_PROCESS_CALLBACK ();
212 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
213 _session.engine().unregister_port (*i);
216 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
217 _session.engine().unregister_port (*i);
220 m_meter_connection.disconnect();
227 IO::silence (nframes_t nframes)
229 /* io_lock, not taken: function must be called from Session::process() calltree */
231 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
232 i->get_buffer(nframes).silence (nframes);
236 /** Deliver bufs to the IO's output ports
238 * This function should automatically do whatever it necessary to correctly deliver bufs
239 * to the outputs, eg applying gain or pan or whatever else needs to be done.
242 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
244 // FIXME: type specific code doesn't actually need to be here, it will go away in time
246 /* ********** AUDIO ********** */
248 // Apply gain if gain automation isn't playing
249 if ( ! apply_gain_automation) {
251 gain_t dg = _gain; // desired gain
254 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
262 if (dg != _gain || dg != 1.0) {
263 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
268 /* do this so that any processing that comes after deliver_outputs()
269 can use the output buffers.
272 output_buffers().attach_buffers (_outputs, nframes, _output_offset);
274 // Use the panner to distribute audio to output port buffers
276 if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
278 /* blech .. we shouldn't be creating and tearing this down every process()
279 cycle. XXX fix me to not waste cycles and do memory allocation etc.
282 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes);
286 /* do a 1:1 copy of data to output ports */
288 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
289 copy_to_outputs (bufs, DataType::AUDIO, nframes);
291 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
292 copy_to_outputs (bufs, DataType::MIDI, nframes);
298 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
300 // Copy any buffers 1:1 to outputs
302 PortSet::iterator o = _outputs.begin(type);
303 BufferSet::iterator i = bufs.begin(type);
304 BufferSet::iterator prev = i;
306 while (i != bufs.end(type) && o != _outputs.end (type)) {
308 Buffer& port_buffer (o->get_buffer (nframes));
309 port_buffer.read_from (*i, nframes, _output_offset);
315 /* extra outputs get a copy of the last buffer */
317 while (o != _outputs.end(type)) {
318 Buffer& port_buffer (o->get_buffer (nframes));
319 port_buffer.read_from (*prev, nframes, _output_offset);
325 IO::collect_input (BufferSet& outs, nframes_t nframes)
327 assert(outs.available() >= n_inputs());
329 if (n_inputs() == ChanCount::ZERO)
332 outs.set_count(n_inputs());
334 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
336 BufferSet::iterator o = outs.begin(*t);
337 PortSet::iterator e = _inputs.end (*t);
338 for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
339 Buffer& b (i->get_buffer (nframes));
340 o->read_from (b, nframes);
347 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
349 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
350 collect_input (bufs, nframes);
351 _meter->run_in_place (bufs, start_frame, end_frame, nframes);
356 IO::check_bundles_connected_to_inputs ()
358 check_bundles (_bundles_connected_to_inputs, inputs());
362 IO::check_bundles_connected_to_outputs ()
364 check_bundles (_bundles_connected_to_outputs, outputs());
368 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
370 std::vector<UserBundleInfo> new_list;
372 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
374 uint32_t const N = i->bundle->nchannels ();
376 if (ports.num_ports (default_type()) < N) {
382 for (uint32_t j = 0; j < N; ++j) {
383 /* Every port on bundle channel j must be connected to our input j */
384 Bundle::PortList const pl = i->bundle->channel_ports (j);
385 for (uint32_t k = 0; k < pl.size(); ++k) {
386 if (ports.port(j)->connected_to (pl[k]) == false) {
398 new_list.push_back (*i);
400 i->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 (our_port->disconnect (other_port)) {
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 (our_port->connect (other_port)) {
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 (our_port->disconnect (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 (our_port->connect (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_bundle_for_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)) == 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 (our_port->connect (destination)) {
667 // pan_changed (src); /* EMIT SIGNAL */
668 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
669 setup_bundle_for_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_bundle_for_inputs ();
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 (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)) == 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 (our_port->connect (source)) {
772 // pan_changed (src); /* EMIT SIGNAL */
773 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
774 setup_bundle_for_inputs ();
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 i->disconnect_all ();
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 i->disconnect_all ();
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)) == 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 i->disconnect_all ();
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)) == 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)) == 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 i->disconnect_all ();
1002 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1003 i->disconnect_all ();
1007 if (in_changed || out_changed) {
1008 setup_peak_meters ();
1014 check_bundles_connected_to_outputs ();
1015 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1016 setup_bundle_for_outputs ();
1020 check_bundles_connected_to_inputs ();
1021 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1022 setup_bundle_for_inputs ();
1025 if (in_changed || out_changed) {
1026 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1027 _session.set_dirty ();
1034 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1036 bool changed = false;
1038 count = min (_input_maximum, count);
1040 if (count == n_inputs() && !clear) {
1045 BLOCK_PROCESS_CALLBACK ();
1046 Glib::Mutex::Lock im (io_lock);
1047 changed = ensure_inputs_locked (count, clear, src);
1049 changed = ensure_inputs_locked (count, clear, src);
1053 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1054 setup_bundle_for_inputs ();
1055 _session.set_dirty ();
1061 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1063 Port* output_port = 0;
1064 bool changed = false;
1065 bool need_pan_reset = false;
1067 if (n_outputs() != count) {
1068 need_pan_reset = true;
1071 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1073 const size_t n = count.get(*t);
1075 /* remove unused ports */
1076 for (size_t i = n_outputs().get(*t); i > n; --i) {
1077 output_port = _outputs.port(*t, i-1);
1079 assert(output_port);
1080 _outputs.remove(output_port);
1081 _session.engine().unregister_port (*output_port);
1086 /* create any necessary new ports */
1087 while (n_outputs().get(*t) < n) {
1089 string portname = build_legal_port_name (*t, false);
1091 if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
1092 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1096 _outputs.add (output_port);
1098 setup_peak_meters ();
1100 if (need_pan_reset) {
1107 check_bundles_connected_to_outputs ();
1108 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1109 _session.set_dirty ();
1113 /* disconnect all existing ports so that we get a fresh start */
1114 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1115 i->disconnect_all ();
1123 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1125 bool changed = false;
1127 if (_output_maximum < ChanCount::INFINITE) {
1128 count = min (_output_maximum, count);
1129 if (count == n_outputs() && !clear) {
1134 /* XXX caller should hold io_lock, but generally doesn't */
1137 BLOCK_PROCESS_CALLBACK ();
1138 Glib::Mutex::Lock im (io_lock);
1139 changed = ensure_outputs_locked (count, clear, src);
1141 changed = ensure_outputs_locked (count, clear, src);
1145 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1146 setup_bundle_for_outputs ();
1153 IO::effective_gain () const
1155 if (_gain_control->automation_playback()) {
1156 return _gain_control->get_value();
1158 return _desired_gain;
1165 if (panners_legal) {
1166 if (!no_panner_reset) {
1167 _panner->reset (n_outputs().n_audio(), pans_required());
1170 panner_legal_c.disconnect ();
1171 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1176 IO::panners_became_legal ()
1178 _panner->reset (n_outputs().n_audio(), pans_required());
1179 _panner->load (); // automation
1180 panner_legal_c.disconnect ();
1185 IO::defer_pan_reset ()
1187 no_panner_reset = true;
1191 IO::allow_pan_reset ()
1193 no_panner_reset = false;
1199 IO::get_state (void)
1201 return state (true);
1205 IO::state (bool full_state)
1207 XMLNode* node = new XMLNode (state_node_name);
1210 vector<string>::iterator ci;
1212 LocaleGuard lg (X_("POSIX"));
1213 Glib::Mutex::Lock lm (io_lock);
1215 node->add_property("name", _name);
1216 id().print (buf, sizeof (buf));
1217 node->add_property("id", buf);
1220 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1221 i != _bundles_connected_to_inputs.end();
1225 XMLNode* n = new XMLNode ("InputBundle");
1226 n->add_property ("name", i->bundle->name ());
1227 node->add_child_nocopy (*n);
1231 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1232 i != _bundles_connected_to_outputs.end();
1236 XMLNode* n = new XMLNode ("OutputBundle");
1237 n->add_property ("name", i->bundle->name ());
1238 node->add_child_nocopy (*n);
1243 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1245 vector<string> connections;
1247 if (i->get_connections (connections)) {
1251 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1256 /* if its a connection to our own port,
1257 return only the port name, not the
1258 whole thing. this allows connections
1259 to be re-established even when our
1260 client name is different.
1263 str += _session.engine().make_port_name_relative (*ci);
1273 node->add_property ("inputs", str);
1277 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1279 vector<string> connections;
1281 if (i->get_connections (connections)) {
1285 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1290 str += _session.engine().make_port_name_relative (*ci);
1300 node->add_property ("outputs", str);
1302 node->add_child_nocopy (_panner->state (full_state));
1303 node->add_child_nocopy (_gain_control->get_state ());
1305 snprintf (buf, sizeof(buf), "%2.12f", gain());
1306 node->add_property ("gain", buf);
1308 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1312 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1313 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1315 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1317 node->add_property ("iolimits", buf);
1322 node->add_child_nocopy (get_automation_state());
1328 IO::set_state (const XMLNode& node)
1330 const XMLProperty* prop;
1331 XMLNodeConstIterator iter;
1332 LocaleGuard lg (X_("POSIX"));
1334 /* force use of non-localized representation of decimal point,
1335 since we use it a lot in XML files and so forth.
1338 if (node.name() != state_node_name) {
1339 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1343 if ((prop = node.property ("name")) != 0) {
1344 _name = prop->value();
1345 /* used to set panner name with this, but no more */
1348 if ((prop = node.property ("id")) != 0) {
1349 _id = prop->value ();
1357 if ((prop = node.property ("iolimits")) != 0) {
1358 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1359 &in_min, &in_max, &out_min, &out_max);
1361 /* Correct for the difference between the way we write things to session files and the
1362 way things are described by ChanCount; see comments in io.h about what the different
1363 ChanCount values mean. */
1366 _input_minimum = ChanCount::ZERO;
1368 _input_minimum = ChanCount (_default_type, in_min);
1372 _input_maximum = ChanCount::INFINITE;
1374 _input_maximum = ChanCount (_default_type, in_max);
1378 _output_minimum = ChanCount::ZERO;
1380 _output_minimum = ChanCount (_default_type, out_min);
1384 _output_maximum = ChanCount::INFINITE;
1386 _output_maximum = ChanCount (_default_type, out_max);
1390 if ((prop = node.property ("gain")) != 0) {
1391 set_gain (atof (prop->value().c_str()), this);
1392 _gain = _desired_gain;
1395 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1396 /* old school automation handling */
1399 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1401 // Old school Panner.
1402 if ((*iter)->name() == "Panner") {
1404 _panner = new Panner (_name, _session);
1406 _panner->set_state (**iter);
1409 if ((*iter)->name() == "Processor") {
1410 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1412 _panner = new Panner (_name, _session);
1414 _panner->set_state (**iter);
1418 if ((*iter)->name() == X_("Automation")) {
1420 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1423 if ((*iter)->name() == X_("Controllable")) {
1424 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1425 _gain_control->set_state (**iter);
1432 if (create_ports (node)) {
1438 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1442 _panner = new Panner( _name, _session );
1443 if (panners_legal) {
1446 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1449 if (connecting_legal) {
1451 if (make_connections (node)) {
1457 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1460 if (!ports_legal || !connecting_legal) {
1461 pending_state_node = new XMLNode (node);
1468 IO::load_automation (string path)
1473 uint32_t linecnt = 0;
1475 LocaleGuard lg (X_("POSIX"));
1477 fullpath = Glib::build_filename(_session.automation_dir(), path);
1479 in.open (fullpath.c_str());
1482 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1484 in.open (fullpath.c_str());
1487 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1492 clear_automation ();
1494 while (in.getline (line, sizeof(line), '\n')) {
1499 if (++linecnt == 1) {
1500 if (memcmp (line, "version", 7) == 0) {
1501 if (sscanf (line, "version %f", &version) != 1) {
1502 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1506 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1513 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1514 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1520 _gain_control->list()->fast_simple_add (when, value);
1530 /* older (pre-1.0) versions of ardour used this */
1534 warning << _("dubious automation event found (and ignored)") << endmsg;
1542 IO::connecting_became_legal ()
1546 if (pending_state_node == 0) {
1547 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1552 connection_legal_c.disconnect ();
1554 ret = make_connections (*pending_state_node);
1557 delete pending_state_node;
1558 pending_state_node = 0;
1564 IO::ports_became_legal ()
1568 if (pending_state_node == 0) {
1569 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1574 port_legal_c.disconnect ();
1576 ret = create_ports (*pending_state_node);
1578 if (connecting_legal) {
1579 delete pending_state_node;
1580 pending_state_node = 0;
1586 boost::shared_ptr<Bundle>
1587 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1589 static const string digits = "0123456789";
1591 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1594 int bundle_number, mask;
1595 string possible_name;
1596 bool stereo = false;
1597 string::size_type last_non_digit_pos;
1599 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1602 // find numeric suffix of desired name
1605 last_non_digit_pos = desired_name.find_last_not_of(digits);
1607 if (last_non_digit_pos != string::npos) {
1609 s << desired_name.substr(last_non_digit_pos);
1613 // see if it's a stereo connection e.g. "in 3+4"
1615 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1616 int left_bundle_number = 0;
1617 string::size_type left_last_non_digit_pos;
1619 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1621 if (left_last_non_digit_pos != string::npos) {
1623 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1624 s >> left_bundle_number;
1626 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1637 // find highest set bit
1639 while ((mask <= bundle_number) && (mask <<= 1)) {}
1641 // "wrap" bundle number into largest possible power of 2
1646 if (bundle_number & mask) {
1647 bundle_number &= ~mask;
1650 s << default_name << " " << bundle_number + 1;
1653 s << "+" << bundle_number + 2;
1656 possible_name = s.str();
1658 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1665 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1668 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1679 IO::create_ports (const XMLNode& node)
1681 XMLProperty const * prop;
1682 uint32_t num_inputs = 0;
1683 uint32_t num_outputs = 0;
1685 if ((prop = node.property ("input-connection")) != 0) {
1687 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1690 num_inputs = c->nchannels ();
1695 } else if ((prop = node.property ("inputs")) != 0) {
1697 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1700 if ((prop = node.property ("output-connection")) != 0) {
1702 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1705 num_outputs = c->nchannels ();
1710 } else if ((prop = node.property ("outputs")) != 0) {
1712 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1715 no_panner_reset = true;
1717 if (ensure_io (ChanCount (_default_type, num_inputs),
1718 ChanCount (_default_type, num_outputs),
1721 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1725 no_panner_reset = false;
1727 set_deferred_state ();
1735 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 if (n_inputs().get(c->type()) == c->nchannels() && c->ports_are_outputs()) {
1747 connect_input_ports_to_bundle (c, this);
1750 } else if ((prop = node.property ("inputs")) != 0) {
1751 if (set_inputs (prop->value())) {
1752 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1757 if ((prop = node.property ("output-connection")) != 0) {
1758 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1764 if (n_outputs().get(c->type()) == c->nchannels() && c->ports_are_inputs()) {
1765 connect_output_ports_to_bundle (c, this);
1768 } else if ((prop = node.property ("outputs")) != 0) {
1769 if (set_outputs (prop->value())) {
1770 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1775 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1777 if ((*i)->name() == "InputBundle") {
1778 XMLProperty const * prop = (*i)->property ("name");
1780 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1782 connect_input_ports_to_bundle (b, this);
1786 } else if ((*i)->name() == "OutputBundle") {
1787 XMLProperty const * prop = (*i)->property ("name");
1789 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1791 connect_output_ports_to_bundle (b, this);
1801 IO::set_inputs (const string& str)
1803 vector<string> ports;
1808 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1812 // FIXME: audio-only
1813 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1817 string::size_type start, end, ostart;
1824 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1827 if ((end = str.find_first_of ('}', start)) == string::npos) {
1828 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1832 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1833 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1839 for (int x = 0; x < n; ++x) {
1840 connect_input (input (i), ports[x], this);
1852 IO::set_outputs (const string& str)
1854 vector<string> ports;
1859 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1863 // FIXME: audio-only
1864 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1868 string::size_type start, end, ostart;
1875 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1878 if ((end = str.find_first_of ('}', start)) == string::npos) {
1879 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1883 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1884 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1890 for (int x = 0; x < n; ++x) {
1891 connect_output (output (i), ports[x], this);
1903 IO::parse_io_string (const string& str, vector<string>& ports)
1905 string::size_type pos, opos;
1907 if (str.length() == 0) {
1916 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1917 ports.push_back (str.substr (opos, pos - opos));
1921 if (opos < str.length()) {
1922 ports.push_back (str.substr(opos));
1925 return ports.size();
1929 IO::parse_gain_string (const string& str, vector<string>& ports)
1931 string::size_type pos, opos;
1937 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1938 ports.push_back (str.substr (opos, pos - opos));
1942 if (opos < str.length()) {
1943 ports.push_back (str.substr(opos));
1946 return ports.size();
1950 IO::set_name (const string& requested_name)
1952 if (requested_name == _name) {
1958 if ( (rt = dynamic_cast<Route *>(this))) {
1959 name = Route::ensure_track_or_route_name(requested_name, _session);
1961 name = requested_name;
1965 /* replace all colons in the name. i wish we didn't have to do this */
1967 if (replace_all (name, ":", "-")) {
1968 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1971 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1972 string current_name = i->name();
1973 current_name.replace (current_name.find (_name), _name.length(), name);
1974 i->set_name (current_name);
1977 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1978 string current_name = i->name();
1979 current_name.replace (current_name.find (_name), _name.length(), name);
1980 i->set_name (current_name);
1983 bool const r = SessionObject::set_name(name);
1985 setup_bundles_for_inputs_and_outputs ();
1991 IO::set_input_minimum (ChanCount n)
1997 IO::set_input_maximum (ChanCount n)
2003 IO::set_output_minimum (ChanCount n)
2005 _output_minimum = n;
2009 IO::set_output_maximum (ChanCount n)
2011 _output_maximum = n;
2015 IO::set_port_latency (nframes_t nframes)
2017 Glib::Mutex::Lock lm (io_lock);
2019 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2020 i->set_latency (nframes);
2025 IO::output_latency () const
2027 nframes_t max_latency;
2032 /* io lock not taken - must be protected by other means */
2034 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2035 if ((latency = i->total_latency ()) > max_latency) {
2036 max_latency = latency;
2044 IO::input_latency () const
2046 nframes_t max_latency;
2051 /* io lock not taken - must be protected by other means */
2053 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2054 if ((latency = i->total_latency ()) > max_latency) {
2055 max_latency = latency;
2063 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2066 BLOCK_PROCESS_CALLBACK ();
2067 Glib::Mutex::Lock lm2 (io_lock);
2069 c->connect (_bundle_for_inputs, _session.engine());
2071 /* If this is a UserBundle, make a note of what we've done */
2073 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2076 /* See if we already know about this one */
2077 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2078 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2082 if (i == _bundles_connected_to_inputs.end()) {
2083 /* We don't, so make a note */
2084 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2089 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2094 IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2097 BLOCK_PROCESS_CALLBACK ();
2098 Glib::Mutex::Lock lm2 (io_lock);
2100 c->disconnect (_bundle_for_inputs, _session.engine());
2102 /* If this is a UserBundle, make a note of what we've done */
2104 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2107 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2108 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2112 if (i != _bundles_connected_to_inputs.end()) {
2113 _bundles_connected_to_inputs.erase (i);
2118 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2123 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2126 BLOCK_PROCESS_CALLBACK ();
2127 Glib::Mutex::Lock lm2 (io_lock);
2129 c->connect (_bundle_for_outputs, _session.engine());
2131 /* If this is a UserBundle, make a note of what we've done */
2133 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2136 /* See if we already know about this one */
2137 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2138 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2142 if (i == _bundles_connected_to_outputs.end()) {
2143 /* We don't, so make a note */
2144 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2149 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2155 IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2158 BLOCK_PROCESS_CALLBACK ();
2159 Glib::Mutex::Lock lm2 (io_lock);
2161 c->disconnect (_bundle_for_outputs, _session.engine());
2163 /* If this is a UserBundle, make a note of what we've done */
2165 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2168 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2169 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2173 if (i != _bundles_connected_to_outputs.end()) {
2174 _bundles_connected_to_outputs.erase (i);
2179 output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2185 IO::disable_connecting ()
2187 connecting_legal = false;
2192 IO::enable_connecting ()
2194 connecting_legal = true;
2195 return ConnectingLegal ();
2199 IO::disable_ports ()
2201 ports_legal = false;
2209 return PortsLegal ();
2213 IO::disable_panners (void)
2215 panners_legal = false;
2220 IO::reset_panners ()
2222 panners_legal = true;
2223 return PannersLegal ();
2227 IO::bundle_changed (Bundle::Change c)
2230 // connect_input_ports_to_bundle (_input_bundle, this);
2234 IO::GainControl::set_value (float val)
2236 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2237 if (val > 1.99526231f)
2240 _io->set_gain (val, this);
2242 AutomationControl::set_value(val);
2246 IO::GainControl::get_value (void) const
2248 return AutomationControl::get_value();
2252 IO::setup_peak_meters()
2254 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2255 _meter->configure_io (max_streams, max_streams);
2259 Update the peak meters.
2261 The meter signal lock is taken to prevent modification of the
2262 Meter signal while updating the meters, taking the meter signal
2263 lock prior to taking the io_lock ensures that all IO will remain
2264 valid while metering.
2269 Glib::Mutex::Lock guard (m_meter_signal_lock);
2270 Meter(); /* EMIT SIGNAL */
2276 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2278 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2283 IO::clear_automation ()
2285 data().clear (); // clears gain automation
2286 _panner->data().clear();
2290 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2292 // XXX: would be nice to get rid of this special hack
2294 if (param.type() == GainAutomation) {
2296 bool changed = false;
2299 Glib::Mutex::Lock lm (control_lock());
2301 boost::shared_ptr<AutomationList> gain_auto
2302 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2304 if (state != gain_auto->automation_state()) {
2306 _last_automation_snapshot = 0;
2307 gain_auto->set_automation_state (state);
2310 // FIXME: shouldn't this use Curve?
2311 set_gain (gain_auto->eval (_session.transport_frame()), this);
2317 _session.set_dirty ();
2321 AutomatableControls::set_parameter_automation_state(param, state);
2326 IO::inc_gain (gain_t factor, void *src)
2328 if (_desired_gain == 0.0f)
2329 set_gain (0.000001f + (0.000001f * factor), src);
2331 set_gain (_desired_gain + (_desired_gain * factor), src);
2335 IO::set_gain (gain_t val, void *src)
2337 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2338 if (val > 1.99526231f) {
2342 //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2344 if (src != _gain_control.get()) {
2345 _gain_control->set_value(val);
2346 // bit twisty, this will come back and call us again
2347 // (this keeps control in sync with reality)
2352 Glib::Mutex::Lock dm (declick_lock);
2353 _desired_gain = val;
2356 if (_session.transport_stopped()) {
2361 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2362 _gain_control->list()->add (_session.transport_frame(), val);
2367 _session.set_dirty();
2371 IO::start_pan_touch (uint32_t which)
2373 if (which < _panner->npanners()) {
2374 (*_panner).pan_control(which)->start_touch();
2379 IO::end_pan_touch (uint32_t which)
2381 if (which < _panner->npanners()) {
2382 (*_panner).pan_control(which)->stop_touch();
2388 IO::automation_snapshot (nframes_t now, bool force)
2390 AutomatableControls::automation_snapshot (now, force);
2391 // XXX: This seems to be wrong.
2392 // drobilla: shouldnt automation_snapshot for panner be called
2393 // "automagically" because its an Automatable now ?
2395 // we could dump this whole method then. <3
2397 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2398 _panner->automation_snapshot (now, force);
2401 _panner->automation_snapshot (now, force);
2402 _last_automation_snapshot = now;
2406 IO::transport_stopped (nframes_t frame)
2408 _gain_control->list()->reposition_for_rt_add (frame);
2410 if (_gain_control->automation_state() != Off) {
2412 /* the src=0 condition is a special signal to not propagate
2413 automation gain changes into the mix group when locating.
2416 // FIXME: shouldn't this use Curve?
2417 set_gain (_gain_control->list()->eval (frame), 0);
2420 _panner->transport_stopped (frame);
2424 IO::build_legal_port_name (DataType type, bool in)
2426 const int name_size = jack_port_name_size();
2431 if (type == DataType::AUDIO) {
2432 suffix = _("audio");
2433 } else if (type == DataType::MIDI) {
2436 throw unknown_type();
2441 maxports = _input_maximum.get(type);
2443 suffix += _("_out");
2444 maxports = _output_maximum.get(type);
2447 if (maxports == 1) {
2448 // allow space for the slash + the suffix
2449 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2450 char buf[name_size+1];
2451 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2452 return string (buf);
2455 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2457 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2459 char buf1[name_size+1];
2460 char buf2[name_size+1];
2462 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2467 port_number = find_input_port_hole (buf1);
2469 port_number = find_output_port_hole (buf1);
2472 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2474 return string (buf2);
2478 IO::find_input_port_hole (const char* base)
2480 /* CALLER MUST HOLD IO LOCK */
2484 if (_inputs.empty()) {
2488 /* we only allow up to 4 characters for the port number
2491 for (n = 1; n < 9999; ++n) {
2492 char buf[jack_port_name_size()];
2493 PortSet::iterator i = _inputs.begin();
2495 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2497 for ( ; i != _inputs.end(); ++i) {
2498 if (i->name() == buf) {
2503 if (i == _inputs.end()) {
2511 IO::find_output_port_hole (const char* base)
2513 /* CALLER MUST HOLD IO LOCK */
2517 if (_outputs.empty()) {
2521 /* we only allow up to 4 characters for the port number
2524 for (n = 1; n < 9999; ++n) {
2525 char buf[jack_port_name_size()];
2526 PortSet::iterator i = _outputs.begin();
2528 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2530 for ( ; i != _outputs.end(); ++i) {
2531 if (i->name() == buf) {
2536 if (i == _outputs.end()) {
2545 IO::set_active (bool yn)
2548 active_changed(); /* EMIT SIGNAL */
2552 IO::audio_input(uint32_t n) const
2554 return dynamic_cast<AudioPort*>(input(n));
2558 IO::audio_output(uint32_t n) const
2560 return dynamic_cast<AudioPort*>(output(n));
2564 IO::midi_input(uint32_t n) const
2566 return dynamic_cast<MidiPort*>(input(n));
2570 IO::midi_output(uint32_t n) const
2572 return dynamic_cast<MidiPort*>(output(n));
2576 IO::set_phase_invert (bool yn, void *src)
2578 if (_phase_invert != yn) {
2580 // phase_invert_changed (src); /* EMIT SIGNAL */
2585 IO::set_denormal_protection (bool yn, void *src)
2587 if (_denormal_protection != yn) {
2588 _denormal_protection = yn;
2589 // denormal_protection_changed (src); /* EMIT SIGNAL */
2594 IO::update_port_total_latencies ()
2596 /* io_lock, not taken: function must be called from Session::process() calltree */
2598 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2599 _session.engine().update_total_latency (*i);
2602 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2603 _session.engine().update_total_latency (*i);
2609 * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
2613 IO::setup_bundles_for_inputs_and_outputs ()
2615 setup_bundle_for_inputs ();
2616 setup_bundle_for_outputs ();
2621 IO::setup_bundle_for_inputs ()
2625 if (!_bundle_for_inputs) {
2626 _bundle_for_inputs.reset (new Bundle (true));
2629 _bundle_for_inputs->suspend_signals ();
2631 _bundle_for_inputs->set_type (default_type ());
2633 _bundle_for_inputs->remove_channels ();
2635 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2636 _bundle_for_inputs->set_name (buf);
2637 uint32_t const ni = inputs().num_ports();
2638 for (uint32_t i = 0; i < ni; ++i) {
2639 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2640 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2643 _bundle_for_inputs->resume_signals ();
2648 IO::setup_bundle_for_outputs ()
2652 if (!_bundle_for_outputs) {
2653 _bundle_for_outputs.reset (new Bundle (false));
2656 _bundle_for_outputs->suspend_signals ();
2658 _bundle_for_outputs->set_type (default_type ());
2660 _bundle_for_outputs->remove_channels ();
2662 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2663 _bundle_for_outputs->set_name (buf);
2664 uint32_t const no = outputs().num_ports();
2665 for (uint32_t i = 0; i < no; ++i) {
2666 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2667 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2670 _bundle_for_outputs->resume_signals ();
2674 /** @return Bundles connected to our inputs */
2676 IO::bundles_connected_to_inputs ()
2681 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2682 bundles.push_back (i->bundle);
2685 /* Session bundles */
2686 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2687 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2688 if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
2689 bundles.push_back (*i);
2694 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2695 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2696 if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
2697 bundles.push_back ((*i)->bundle_for_outputs());
2705 /* @return Bundles connected to our outputs */
2707 IO::bundles_connected_to_outputs ()
2712 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2713 bundles.push_back (i->bundle);
2716 /* Session bundles */
2717 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2718 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2719 if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
2720 bundles.push_back (*i);
2725 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2726 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2727 if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
2728 bundles.push_back ((*i)->bundle_for_inputs());
2736 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2739 changed = b->Changed.connect (
2740 sigc::mem_fun (*io, &IO::bundle_changed)
2745 IO::prepare_inputs (nframes_t nframes)
2747 /* io_lock, not taken: function must be called from Session::process() calltree */
2751 IO::flush_outputs (nframes_t nframes)
2753 /* io_lock, not taken: function must be called from Session::process() calltree */
2755 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2756 (*i).flush_buffers (nframes, _output_offset);
2761 IO::bundle_channel_name (uint32_t c, uint32_t n) const
2769 return c == 0 ? _("L") : _("R");
2771 snprintf (buf, sizeof(buf), _("%d"), (c + 1));
2779 IO::name_from_state (const XMLNode& node)
2781 const XMLProperty* prop;
2783 if ((prop = node.property ("name")) != 0) {
2784 return prop->value();
2791 IO::set_name_in_state (XMLNode& node, const string& new_name)
2793 const XMLProperty* prop;
2795 if ((prop = node.property ("name")) != 0) {
2796 node.add_property ("name", new_name);
2801 IO::cycle_start (nframes_t nframes)
2807 IO::increment_output_offset (nframes_t n)
2809 _output_offset += n;