2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
28 #include <glibmm/thread.h>
30 #include <pbd/xml++.h>
31 #include <pbd/replace_all.h>
32 #include <pbd/unknown_type.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/io.h>
36 #include <ardour/route.h>
37 #include <ardour/port.h>
38 #include <ardour/audio_port.h>
39 #include <ardour/midi_port.h>
40 #include <ardour/auto_bundle.h>
41 #include <ardour/session.h>
42 #include <ardour/cycle_timer.h>
43 #include <ardour/panner.h>
44 #include <ardour/buffer_set.h>
45 #include <ardour/meter.h>
46 #include <ardour/amp.h>
53 A bug in OS X's cmath that causes isnan() and isinf() to be
54 "undeclared". the following works around that
57 #if defined(__APPLE__) && defined(__MACH__)
58 extern "C" int isnan (double);
59 extern "C" int isinf (double);
62 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
65 using namespace ARDOUR;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,ChanCount> IO::PortCountChanged;
77 sigc::signal<int> IO::PortsCreated;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
100 /** @param default_type The type of port that will be created by ensure_io
101 * and friends if no type is explicitly requested (to avoid breakage).
103 IO::IO (Session& s, const string& name,
104 int input_min, int input_max, int output_min, int output_max,
105 DataType default_type, bool public_ports)
106 : SessionObject(s, name),
107 AutomatableControls (s),
108 _output_buffers (new BufferSet()),
110 _default_type (default_type),
111 _public_ports (public_ports),
112 _input_minimum (ChanCount::ZERO),
113 _input_maximum (ChanCount::INFINITE),
114 _output_minimum (ChanCount::ZERO),
115 _output_maximum (ChanCount::INFINITE)
117 _panner = new Panner (name, _session);
118 _meter = new PeakMeter (_session);
121 _input_minimum = ChanCount(_default_type, input_min);
123 if (input_max >= 0) {
124 _input_maximum = ChanCount(_default_type, input_max);
126 if (output_min > 0) {
127 _output_minimum = ChanCount(_default_type, output_min);
129 if (output_max >= 0) {
130 _output_maximum = ChanCount(_default_type, output_max);
135 pending_state_node = 0;
136 no_panner_reset = false;
137 _phase_invert = false;
140 boost::shared_ptr<AutomationList> gl(
141 new AutomationList(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 // Connect to our own PortCountChanged signal to connect output buffers
157 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
159 _session.add_controllable (_gain_control);
161 create_bundles_for_inputs_and_outputs ();
164 IO::IO (Session& s, const XMLNode& node, DataType dt)
165 : SessionObject(s, "unnamed io"),
166 AutomatableControls (s),
167 _output_buffers (new BufferSet()),
171 _meter = new PeakMeter (_session);
172 _public_ports = true; // XXX get this from node
175 no_panner_reset = false;
179 apply_gain_automation = false;
181 boost::shared_ptr<AutomationList> gl(
182 new AutomationList(Evoral::Parameter(GainAutomation)));
184 _gain_control = boost::shared_ptr<GainControl>(
185 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
187 add_control(_gain_control);
192 // IO::Meter is emitted from another thread so the
193 // Meter signal must be protected.
194 Glib::Mutex::Lock guard (m_meter_signal_lock);
195 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
198 // Connect to our own PortCountChanged signal to connect output buffers
199 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
201 _session.add_controllable (_gain_control);
203 create_bundles_for_inputs_and_outputs ();
208 Glib::Mutex::Lock guard (m_meter_signal_lock);
209 Glib::Mutex::Lock lm (io_lock);
211 BLOCK_PROCESS_CALLBACK ();
213 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
214 _session.engine().unregister_port (*i);
217 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
218 _session.engine().unregister_port (*i);
221 m_meter_connection.disconnect();
225 delete _output_buffers;
229 IO::silence (nframes_t nframes, nframes_t offset)
231 /* io_lock, not taken: function must be called from Session::process() calltree */
233 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
234 i->get_buffer().silence (nframes, offset);
238 /** Deliver bufs to the IO's output ports
240 * This function should automatically do whatever it necessary to correctly deliver bufs
241 * to the outputs, eg applying gain or pan or whatever else needs to be done.
244 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
246 // FIXME: type specific code doesn't actually need to be here, it will go away in time
248 /* ********** AUDIO ********** */
250 // Apply gain if gain automation isn't playing
251 if ( ! apply_gain_automation) {
253 gain_t dg = _gain; // desired gain
256 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
264 if (dg != _gain || dg != 1.0)
265 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
268 // Use the panner to distribute audio to output port buffers
269 if( _panner && _panner->npanners() && !_panner->bypassed()) {
270 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
272 const DataType type = DataType::AUDIO;
274 // Copy any audio 1:1 to outputs
276 BufferSet::iterator o = output_buffers().begin(type);
277 BufferSet::iterator i = bufs.begin(type);
278 BufferSet::iterator prev = i;
280 while (i != bufs.end(type) && o != output_buffers().end (type)) {
281 o->read_from(*i, nframes, offset);
287 /* extra outputs get a copy of the last buffer */
289 while (o != output_buffers().end(type)) {
290 o->read_from(*prev, nframes, offset);
295 /* ********** MIDI ********** */
297 // No MIDI, we're done here
298 if (bufs.count().n_midi() == 0) {
302 const DataType type = DataType::MIDI;
304 // Copy any MIDI 1:1 to outputs
305 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
306 BufferSet::iterator o = output_buffers().begin(type);
307 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
308 o->read_from(*i, nframes, offset);
313 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
315 assert(outs.available() >= n_inputs());
317 if (n_inputs() == ChanCount::ZERO)
320 outs.set_count(n_inputs());
322 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
324 BufferSet::iterator o = outs.begin(*t);
325 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
326 (*i).cycle_start (nframes, offset);
327 o->read_from(i->get_buffer(), nframes, offset);
334 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
335 nframes_t nframes, nframes_t offset)
337 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
339 collect_input (bufs, nframes, offset);
341 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
346 IO::check_bundles_connected_to_inputs ()
348 check_bundles (_bundles_connected_to_inputs, inputs());
352 IO::check_bundles_connected_to_outputs ()
354 check_bundles (_bundles_connected_to_outputs, outputs());
358 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
360 std::vector<UserBundleInfo> new_list;
362 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
364 ChanCount const N = i->bundle->nchannels ();
366 if (ports.num_ports (default_type()) < N.get (default_type())) {
371 uint32_t n = N.get (default_type());
373 for (uint32_t j = 0; j < n; ++j) {
374 /* Every port on bundle channel j must be connected to our input j */
375 PortList const pl = i->bundle->channel_ports (j);
376 for (uint32_t k = 0; k < pl.size(); ++k) {
377 if (ports.port(j)->connected_to (pl[k]) == false) {
389 new_list.push_back (*i);
391 i->configuration_will_change.disconnect ();
392 i->configuration_has_changed.disconnect ();
393 i->ports_will_change.disconnect ();
394 i->ports_have_changed.disconnect ();
403 IO::disconnect_input (Port* our_port, string other_port, void* src)
405 if (other_port.length() == 0 || our_port == 0) {
410 BLOCK_PROCESS_CALLBACK ();
413 Glib::Mutex::Lock lm (io_lock);
415 /* check that our_port is really one of ours */
417 if ( ! _inputs.contains(our_port)) {
421 /* disconnect it from the source */
423 if (_session.engine().disconnect (other_port, our_port->name())) {
424 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
428 check_bundles_connected_to_inputs ();
432 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
433 _session.set_dirty ();
439 IO::connect_input (Port* our_port, string other_port, void* src)
441 if (other_port.length() == 0 || our_port == 0) {
446 BLOCK_PROCESS_CALLBACK ();
449 Glib::Mutex::Lock lm (io_lock);
451 /* check that our_port is really one of ours */
453 if ( ! _inputs.contains(our_port) ) {
457 /* connect it to the source */
459 if (_session.engine().connect (other_port, our_port->name())) {
465 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
466 _session.set_dirty ();
471 IO::disconnect_output (Port* our_port, string other_port, void* src)
473 if (other_port.length() == 0 || our_port == 0) {
478 BLOCK_PROCESS_CALLBACK ();
481 Glib::Mutex::Lock lm (io_lock);
483 /* check that our_port is really one of ours */
485 if ( ! _outputs.contains(our_port) ) {
489 /* disconnect it from the destination */
491 if (_session.engine().disconnect (our_port->name(), other_port)) {
492 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
496 check_bundles_connected_to_outputs ();
500 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
501 _session.set_dirty ();
506 IO::connect_output (Port* our_port, string other_port, void* src)
508 if (other_port.length() == 0 || our_port == 0) {
513 BLOCK_PROCESS_CALLBACK ();
517 Glib::Mutex::Lock lm (io_lock);
519 /* check that our_port is really one of ours */
521 if ( ! _outputs.contains(our_port) ) {
525 /* connect it to the destination */
527 if (_session.engine().connect (our_port->name(), other_port)) {
533 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
534 _session.set_dirty ();
539 IO::set_input (Port* other_port, void* src)
541 /* this removes all but one ports, and connects that one port
542 to the specified source.
545 if (_input_minimum.n_total() > 1) {
546 /* sorry, you can't do this */
550 if (other_port == 0) {
551 if (_input_minimum == ChanCount::ZERO) {
552 return ensure_inputs (ChanCount::ZERO, false, true, src);
558 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
562 return connect_input (_inputs.port(0), other_port->name(), src);
566 IO::remove_output_port (Port* port, void* src)
568 IOChange change (NoChange);
571 BLOCK_PROCESS_CALLBACK ();
575 Glib::Mutex::Lock lm (io_lock);
577 if (n_outputs() <= _output_minimum) {
578 /* sorry, you can't do this */
582 if (_outputs.remove(port)) {
583 change = IOChange (change|ConfigurationChanged);
585 if (port->connected()) {
586 change = IOChange (change|ConnectionsChanged);
589 _session.engine().unregister_port (*port);
590 check_bundles_connected_to_outputs ();
592 setup_peak_meters ();
597 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
600 if (change == ConnectionsChanged) {
601 setup_bundles_for_inputs_and_outputs ();
604 if (change != NoChange) {
605 output_changed (change, src);
606 _session.set_dirty ();
613 /** Add an output port.
615 * @param destination Name of input port to connect new port to.
616 * @param src Source for emitted ConfigurationChanged signal.
617 * @param type Data type of port. Default value (NIL) will use this IO's default type.
620 IO::add_output_port (string destination, void* src, DataType type)
624 if (type == DataType::NIL)
625 type = _default_type;
628 BLOCK_PROCESS_CALLBACK ();
632 Glib::Mutex::Lock lm (io_lock);
634 if (n_outputs() >= _output_maximum) {
638 /* Create a new output port */
640 string portname = build_legal_port_name (type, false);
642 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
643 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
647 _outputs.add (our_port);
648 setup_peak_meters ();
652 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
655 if (destination.length()) {
656 if (_session.engine().connect (our_port->name(), destination)) {
661 // pan_changed (src); /* EMIT SIGNAL */
662 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
663 setup_bundles_for_inputs_and_outputs ();
664 _session.set_dirty ();
670 IO::remove_input_port (Port* port, void* src)
672 IOChange change (NoChange);
675 BLOCK_PROCESS_CALLBACK ();
679 Glib::Mutex::Lock lm (io_lock);
681 if (n_inputs() <= _input_minimum) {
682 /* sorry, you can't do this */
686 if (_inputs.remove(port)) {
687 change = IOChange (change|ConfigurationChanged);
689 if (port->connected()) {
690 change = IOChange (change|ConnectionsChanged);
693 _session.engine().unregister_port (*port);
694 check_bundles_connected_to_inputs ();
696 setup_peak_meters ();
701 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
704 if (change == ConfigurationChanged) {
705 setup_bundles_for_inputs_and_outputs ();
708 if (change != NoChange) {
709 input_changed (change, src);
710 _session.set_dirty ();
718 /** Add an input port.
720 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
721 * @param destination Name of input port to connect new port to.
722 * @param src Source for emitted ConfigurationChanged signal.
725 IO::add_input_port (string source, void* src, DataType type)
729 if (type == DataType::NIL)
730 type = _default_type;
733 BLOCK_PROCESS_CALLBACK ();
736 Glib::Mutex::Lock lm (io_lock);
738 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
742 /* Create a new input port */
744 string portname = build_legal_port_name (type, true);
746 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
747 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
751 _inputs.add (our_port);
752 setup_peak_meters ();
756 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
759 if (source.length()) {
761 if (_session.engine().connect (source, our_port->name())) {
766 // pan_changed (src); /* EMIT SIGNAL */
767 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
768 setup_bundles_for_inputs_and_outputs ();
769 _session.set_dirty ();
775 IO::disconnect_inputs (void* src)
778 BLOCK_PROCESS_CALLBACK ();
781 Glib::Mutex::Lock lm (io_lock);
783 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
784 _session.engine().disconnect (*i);
787 check_bundles_connected_to_inputs ();
791 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
797 IO::disconnect_outputs (void* src)
800 BLOCK_PROCESS_CALLBACK ();
803 Glib::Mutex::Lock lm (io_lock);
805 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
806 _session.engine().disconnect (*i);
809 check_bundles_connected_to_outputs ();
813 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
814 _session.set_dirty ();
820 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
822 Port* input_port = 0;
823 bool changed = false;
826 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
828 const size_t n = count.get(*t);
830 /* remove unused ports */
831 for (size_t i = n_inputs().get(*t); i > n; --i) {
832 input_port = _inputs.port(*t, i-1);
835 _inputs.remove(input_port);
836 _session.engine().unregister_port (*input_port);
841 /* create any necessary new ports */
842 while (n_inputs().get(*t) < n) {
844 string portname = build_legal_port_name (*t, true);
848 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
849 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
854 catch (AudioEngine::PortRegistrationFailure& err) {
855 setup_peak_meters ();
858 throw AudioEngine::PortRegistrationFailure();
861 _inputs.add (input_port);
867 check_bundles_connected_to_inputs ();
868 setup_peak_meters ();
870 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
871 _session.set_dirty ();
875 /* disconnect all existing ports so that we get a fresh start */
876 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
877 _session.engine().disconnect (*i);
884 /** Attach output_buffers to port buffers.
886 * Connected to IO's own PortCountChanged signal.
889 IO::attach_buffers(ChanCount ignored)
891 _output_buffers->attach_buffers(_outputs);
895 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
897 bool in_changed = false;
898 bool out_changed = false;
899 bool need_pan_reset = false;
901 in = min (_input_maximum, in);
903 out = min (_output_maximum, out);
905 if (in == n_inputs() && out == n_outputs() && !clear) {
910 BLOCK_PROCESS_CALLBACK ();
911 Glib::Mutex::Lock lm (io_lock);
915 if (n_outputs() != out) {
916 need_pan_reset = true;
919 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
921 const size_t nin = in.get(*t);
922 const size_t nout = out.get(*t);
924 Port* output_port = 0;
925 Port* input_port = 0;
927 /* remove unused output ports */
928 for (size_t i = n_outputs().get(*t); i > nout; --i) {
929 output_port = _outputs.port(*t, i-1);
932 _outputs.remove(output_port);
933 _session.engine().unregister_port (*output_port);
938 /* remove unused input ports */
939 for (size_t i = n_inputs().get(*t); i > nin; --i) {
940 input_port = _inputs.port(*t, i-1);
943 _inputs.remove(input_port);
944 _session.engine().unregister_port (*input_port);
949 /* create any necessary new input ports */
951 while (n_inputs().get(*t) < nin) {
953 string portname = build_legal_port_name (*t, true);
956 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
957 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
962 catch (AudioEngine::PortRegistrationFailure& err) {
963 setup_peak_meters ();
966 throw AudioEngine::PortRegistrationFailure();
973 /* create any necessary new output ports */
975 while (n_outputs().get(*t) < nout) {
977 string portname = build_legal_port_name (*t, false);
980 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
981 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
986 catch (AudioEngine::PortRegistrationFailure& err) {
987 setup_peak_meters ();
990 throw AudioEngine::PortRegistrationFailure ();
1000 /* disconnect all existing ports so that we get a fresh start */
1002 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1003 _session.engine().disconnect (*i);
1006 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1007 _session.engine().disconnect (*i);
1011 if (in_changed || out_changed) {
1012 setup_peak_meters ();
1018 check_bundles_connected_to_outputs ();
1019 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1023 check_bundles_connected_to_inputs ();
1024 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1027 if (in_changed || out_changed) {
1028 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1029 setup_bundles_for_inputs_and_outputs ();
1030 _session.set_dirty ();
1037 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1039 bool changed = false;
1041 count = min (_input_maximum, count);
1043 if (count == n_inputs() && !clear) {
1048 BLOCK_PROCESS_CALLBACK ();
1049 Glib::Mutex::Lock im (io_lock);
1050 changed = ensure_inputs_locked (count, clear, src);
1052 changed = ensure_inputs_locked (count, clear, src);
1056 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1057 setup_bundles_for_inputs_and_outputs ();
1058 _session.set_dirty ();
1064 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1066 Port* output_port = 0;
1067 bool changed = false;
1068 bool need_pan_reset = false;
1070 if (n_outputs() != count) {
1071 need_pan_reset = true;
1074 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1076 const size_t n = count.get(*t);
1078 /* remove unused ports */
1079 for (size_t i = n_outputs().get(*t); i > n; --i) {
1080 output_port = _outputs.port(*t, i-1);
1082 assert(output_port);
1083 _outputs.remove(output_port);
1084 _session.engine().unregister_port (*output_port);
1089 /* create any necessary new ports */
1090 while (n_outputs().get(*t) < n) {
1092 string portname = build_legal_port_name (*t, false);
1094 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1095 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1099 _outputs.add (output_port);
1101 setup_peak_meters ();
1103 if (need_pan_reset) {
1110 check_bundles_connected_to_outputs ();
1111 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1112 _session.set_dirty ();
1116 /* disconnect all existing ports so that we get a fresh start */
1117 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1118 _session.engine().disconnect (*i);
1126 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1128 bool changed = false;
1130 if (_output_maximum < ChanCount::INFINITE) {
1131 count = min (_output_maximum, count);
1132 if (count == n_outputs() && !clear) {
1137 /* XXX caller should hold io_lock, but generally doesn't */
1140 BLOCK_PROCESS_CALLBACK ();
1141 Glib::Mutex::Lock im (io_lock);
1142 changed = ensure_outputs_locked (count, clear, src);
1144 changed = ensure_outputs_locked (count, clear, src);
1148 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1149 setup_bundles_for_inputs_and_outputs ();
1156 IO::effective_gain () const
1158 if (_gain_control->automation_playback()) {
1159 return _gain_control->get_value();
1161 return _desired_gain;
1168 if (panners_legal) {
1169 if (!no_panner_reset) {
1170 _panner->reset (n_outputs().n_audio(), pans_required());
1173 panner_legal_c.disconnect ();
1174 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1179 IO::panners_became_legal ()
1181 _panner->reset (n_outputs().n_audio(), pans_required());
1182 _panner->load (); // automation
1183 panner_legal_c.disconnect ();
1188 IO::defer_pan_reset ()
1190 no_panner_reset = true;
1194 IO::allow_pan_reset ()
1196 no_panner_reset = false;
1202 IO::get_state (void)
1204 return state (true);
1208 IO::state (bool full_state)
1210 XMLNode* node = new XMLNode (state_node_name);
1213 vector<string>::iterator ci;
1215 LocaleGuard lg (X_("POSIX"));
1216 Glib::Mutex::Lock lm (io_lock);
1218 node->add_property("name", _name);
1219 id().print (buf, sizeof (buf));
1220 node->add_property("id", buf);
1223 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1224 i != _bundles_connected_to_inputs.end();
1228 XMLNode* n = new XMLNode ("InputBundle");
1229 n->add_property ("name", i->bundle->name ());
1230 node->add_child_nocopy (*n);
1234 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1235 i != _bundles_connected_to_outputs.end();
1239 XMLNode* n = new XMLNode ("OutputBundle");
1240 n->add_property ("name", i->bundle->name ());
1241 node->add_child_nocopy (*n);
1246 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1248 vector<string> connections;
1250 if (i->get_connections (connections)) {
1254 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1259 /* if its a connection to our own port,
1260 return only the port name, not the
1261 whole thing. this allows connections
1262 to be re-established even when our
1263 client name is different.
1266 str += _session.engine().make_port_name_relative (*ci);
1276 node->add_property ("inputs", str);
1280 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1282 vector<string> connections;
1284 if (i->get_connections (connections)) {
1288 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1293 str += _session.engine().make_port_name_relative (*ci);
1303 node->add_property ("outputs", str);
1305 node->add_child_nocopy (_panner->state (full_state));
1306 node->add_child_nocopy (_gain_control->get_state ());
1308 snprintf (buf, sizeof(buf), "%2.12f", gain());
1309 node->add_property ("gain", buf);
1311 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1315 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1316 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1318 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1320 node->add_property ("iolimits", buf);
1325 node->add_child_nocopy (get_automation_state());
1331 IO::set_state (const XMLNode& node)
1333 const XMLProperty* prop;
1334 XMLNodeConstIterator iter;
1335 LocaleGuard lg (X_("POSIX"));
1337 /* force use of non-localized representation of decimal point,
1338 since we use it a lot in XML files and so forth.
1341 if (node.name() != state_node_name) {
1342 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1346 if ((prop = node.property ("name")) != 0) {
1347 _name = prop->value();
1348 /* used to set panner name with this, but no more */
1351 if ((prop = node.property ("id")) != 0) {
1352 _id = prop->value ();
1360 if ((prop = node.property ("iolimits")) != 0) {
1361 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1362 &in_min, &in_max, &out_min, &out_max);
1364 /* Correct for the difference between the way we write things to session files and the
1365 way things are described by ChanCount; see comments in io.h about what the different
1366 ChanCount values mean. */
1369 _input_minimum = ChanCount::ZERO;
1371 _input_minimum = ChanCount (_default_type, in_min);
1375 _input_maximum = ChanCount::INFINITE;
1377 _input_maximum = ChanCount (_default_type, in_max);
1381 _output_minimum = ChanCount::ZERO;
1383 _output_minimum = ChanCount (_default_type, out_min);
1387 _output_maximum = ChanCount::INFINITE;
1389 _output_maximum = ChanCount (_default_type, out_max);
1393 if ((prop = node.property ("gain")) != 0) {
1394 set_gain (atof (prop->value().c_str()), this);
1395 _gain = _desired_gain;
1398 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1399 /* old school automation handling */
1402 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1404 // Old school Panner.
1405 if ((*iter)->name() == "Panner") {
1407 _panner = new Panner (_name, _session);
1409 _panner->set_state (**iter);
1412 if ((*iter)->name() == "Processor") {
1413 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1415 _panner = new Panner (_name, _session);
1417 _panner->set_state (**iter);
1421 if ((*iter)->name() == X_("Automation")) {
1423 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1426 if ((*iter)->name() == X_("controllable")) {
1427 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1428 _gain_control->set_state (**iter);
1435 if (create_ports (node)) {
1441 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1445 _panner = new Panner( _name, _session );
1446 if (panners_legal) {
1449 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1452 if (connecting_legal) {
1454 if (make_connections (node)) {
1460 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1463 if (!ports_legal || !connecting_legal) {
1464 pending_state_node = new XMLNode (node);
1471 IO::load_automation (string path)
1476 uint32_t linecnt = 0;
1478 LocaleGuard lg (X_("POSIX"));
1480 fullpath = Glib::build_filename(_session.automation_dir(), path);
1482 in.open (fullpath.c_str());
1485 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1487 in.open (fullpath.c_str());
1490 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1495 clear_automation ();
1497 while (in.getline (line, sizeof(line), '\n')) {
1502 if (++linecnt == 1) {
1503 if (memcmp (line, "version", 7) == 0) {
1504 if (sscanf (line, "version %f", &version) != 1) {
1505 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1509 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1516 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1517 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1523 _gain_control->list()->fast_simple_add (when, value);
1533 /* older (pre-1.0) versions of ardour used this */
1537 warning << _("dubious automation event found (and ignored)") << endmsg;
1545 IO::connecting_became_legal ()
1549 if (pending_state_node == 0) {
1550 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1555 connection_legal_c.disconnect ();
1557 ret = make_connections (*pending_state_node);
1560 delete pending_state_node;
1561 pending_state_node = 0;
1567 IO::ports_became_legal ()
1571 if (pending_state_node == 0) {
1572 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1577 port_legal_c.disconnect ();
1579 ret = create_ports (*pending_state_node);
1581 if (connecting_legal) {
1582 delete pending_state_node;
1583 pending_state_node = 0;
1589 boost::shared_ptr<Bundle>
1590 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1592 static const string digits = "0123456789";
1594 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1597 int bundle_number, mask;
1598 string possible_name;
1599 bool stereo = false;
1600 string::size_type last_non_digit_pos;
1602 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1605 // find numeric suffix of desired name
1608 last_non_digit_pos = desired_name.find_last_not_of(digits);
1610 if (last_non_digit_pos != string::npos) {
1612 s << desired_name.substr(last_non_digit_pos);
1616 // see if it's a stereo connection e.g. "in 3+4"
1618 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1619 int left_bundle_number = 0;
1620 string::size_type left_last_non_digit_pos;
1622 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1624 if (left_last_non_digit_pos != string::npos) {
1626 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1627 s >> left_bundle_number;
1629 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1640 // find highest set bit
1642 while ((mask <= bundle_number) && (mask <<= 1));
1644 // "wrap" bundle number into largest possible power of 2
1649 if (bundle_number & mask) {
1650 bundle_number &= ~mask;
1653 s << default_name << " " << bundle_number + 1;
1656 s << "+" << bundle_number + 2;
1659 possible_name = s.str();
1661 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1668 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1671 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1682 IO::create_ports (const XMLNode& node)
1684 XMLProperty const * prop;
1685 ChanCount num_inputs;
1686 ChanCount num_outputs;
1688 if ((prop = node.property ("input-connection")) != 0) {
1690 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1696 num_inputs = c->nchannels();
1698 } else if ((prop = node.property ("inputs")) != 0) {
1700 num_inputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1703 if ((prop = node.property ("output-connection")) != 0) {
1705 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1711 num_outputs = c->nchannels ();
1713 } else if ((prop = node.property ("outputs")) != 0) {
1715 num_outputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1718 no_panner_reset = true;
1720 if (ensure_io (num_inputs, num_outputs, true, this)) {
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)
1738 const XMLProperty* prop;
1740 if ((prop = node.property ("input-connection")) != 0) {
1741 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1747 connect_input_ports_to_bundle (c, this);
1749 } else if ((prop = node.property ("inputs")) != 0) {
1750 if (set_inputs (prop->value())) {
1751 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1756 if ((prop = node.property ("output-connection")) != 0) {
1757 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1763 connect_output_ports_to_bundle (c, this);
1765 } else if ((prop = node.property ("outputs")) != 0) {
1766 if (set_outputs (prop->value())) {
1767 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1772 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1774 if ((*i)->name() == "InputBundle") {
1775 XMLProperty const * prop = (*i)->property ("name");
1777 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1779 connect_input_ports_to_bundle (b, this);
1783 } else if ((*i)->name() == "OutputBundle") {
1784 XMLProperty const * prop = (*i)->property ("name");
1786 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1788 connect_output_ports_to_bundle (b, this);
1798 IO::set_inputs (const string& str)
1800 vector<string> ports;
1805 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1809 // FIXME: audio-only
1810 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1814 string::size_type start, end, ostart;
1821 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1824 if ((end = str.find_first_of ('}', start)) == string::npos) {
1825 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1829 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1830 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1836 for (int x = 0; x < n; ++x) {
1837 connect_input (input (i), ports[x], this);
1849 IO::set_outputs (const string& str)
1851 vector<string> ports;
1856 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1860 // FIXME: audio-only
1861 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1865 string::size_type start, end, ostart;
1872 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1875 if ((end = str.find_first_of ('}', start)) == string::npos) {
1876 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1880 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1881 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1887 for (int x = 0; x < n; ++x) {
1888 connect_output (output (i), ports[x], this);
1900 IO::parse_io_string (const string& str, vector<string>& ports)
1902 string::size_type pos, opos;
1904 if (str.length() == 0) {
1913 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1914 ports.push_back (str.substr (opos, pos - opos));
1918 if (opos < str.length()) {
1919 ports.push_back (str.substr(opos));
1922 return ports.size();
1926 IO::parse_gain_string (const string& str, vector<string>& ports)
1928 string::size_type pos, opos;
1934 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1935 ports.push_back (str.substr (opos, pos - opos));
1939 if (opos < str.length()) {
1940 ports.push_back (str.substr(opos));
1943 return ports.size();
1947 IO::set_name (const string& requested_name)
1949 if (requested_name == _name) {
1955 if ( (rt = dynamic_cast<Route *>(this))) {
1956 name = Route::ensure_track_or_route_name(requested_name, _session);
1958 name = requested_name;
1962 /* replace all colons in the name. i wish we didn't have to do this */
1964 if (replace_all (name, ":", "-")) {
1965 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1968 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1969 string current_name = i->short_name();
1970 current_name.replace (current_name.find (_name), _name.length(), name);
1971 i->set_name (current_name);
1974 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1975 string current_name = i->short_name();
1976 current_name.replace (current_name.find (_name), _name.length(), name);
1977 i->set_name (current_name);
1980 bool const r = SessionObject::set_name(name);
1982 setup_bundles_for_inputs_and_outputs ();
1988 IO::set_input_minimum (ChanCount n)
1994 IO::set_input_maximum (ChanCount n)
2000 IO::set_output_minimum (ChanCount n)
2002 _output_minimum = n;
2006 IO::set_output_maximum (ChanCount n)
2008 _output_maximum = n;
2012 IO::set_port_latency (nframes_t nframes)
2014 Glib::Mutex::Lock lm (io_lock);
2016 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2017 i->set_latency (nframes);
2022 IO::output_latency () const
2024 nframes_t max_latency;
2029 /* io lock not taken - must be protected by other means */
2031 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2032 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2033 max_latency = latency;
2041 IO::input_latency () const
2043 nframes_t max_latency;
2048 /* io lock not taken - must be protected by other means */
2050 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2051 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2052 max_latency = latency;
2060 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2063 BLOCK_PROCESS_CALLBACK ();
2064 Glib::Mutex::Lock lm2 (io_lock);
2066 /* Connect to the bundle, not worrying about any connections
2067 that are already made. */
2069 ChanCount const channels = c->nchannels ();
2070 uint32_t cnt = channels.get (default_type());
2072 for (uint32_t n = 0; n < cnt; ++n) {
2073 const PortList& pl = c->channel_ports (n);
2075 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2077 if (!_inputs.port(n)->connected_to (*i)) {
2079 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2087 /* If this is a UserBundle, make a note of what we've done */
2089 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2092 /* See if we already know about this one */
2093 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2094 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2098 if (i == _bundles_connected_to_inputs.end()) {
2099 /* We don't, so make a note */
2100 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2105 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2110 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2113 BLOCK_PROCESS_CALLBACK ();
2114 Glib::Mutex::Lock lm2 (io_lock);
2116 /* Connect to the bundle, not worrying about any connections
2117 that are already made. */
2119 ChanCount const channels = c->nchannels ();
2120 uint32_t cnt = channels.get (default_type());
2122 for (uint32_t n = 0; n < cnt; ++n) {
2124 const PortList& pl = c->channel_ports (n);
2126 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2128 if (!_outputs.port(n)->connected_to (*i)) {
2130 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2137 /* If this is a UserBundle, make a note of what we've done */
2139 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2142 /* See if we already know about this one */
2143 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2144 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2148 if (i == _bundles_connected_to_outputs.end()) {
2149 /* We don't, so make a note */
2150 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2155 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2161 IO::disable_connecting ()
2163 connecting_legal = false;
2168 IO::enable_connecting ()
2170 connecting_legal = true;
2171 return ConnectingLegal ();
2175 IO::disable_ports ()
2177 ports_legal = false;
2185 return PortsLegal ();
2189 IO::disable_panners (void)
2191 panners_legal = false;
2196 IO::reset_panners ()
2198 panners_legal = true;
2199 return PannersLegal ();
2203 IO::bundle_configuration_will_change ()
2206 // connect_input_ports_to_bundle (_input_bundle, this);
2210 IO::bundle_configuration_has_changed ()
2213 // connect_input_ports_to_bundle (_input_bundle, this);
2217 IO::bundle_ports_will_change (int ignored)
2220 // connect_output_ports_to_bundle (_output_bundle, this);
2224 IO::bundle_ports_have_changed (int ignored)
2227 // connect_output_ports_to_bundle (_output_bundle, this);
2231 IO::GainControl::set_value (float val)
2233 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2234 if (val > 1.99526231f)
2237 _io->set_gain (val, this);
2239 AutomationControl::set_value(val);
2243 IO::GainControl::get_value (void) const
2245 return AutomationControl::get_value();
2249 IO::setup_peak_meters()
2251 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2252 _meter->configure_io (max_streams, max_streams);
2256 Update the peak meters.
2258 The meter signal lock is taken to prevent modification of the
2259 Meter signal while updating the meters, taking the meter signal
2260 lock prior to taking the io_lock ensures that all IO will remain
2261 valid while metering.
2266 Glib::Mutex::Lock guard (m_meter_signal_lock);
2267 Meter(); /* EMIT SIGNAL */
2273 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2275 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2280 IO::clear_automation ()
2282 data().clear (); // clears gain automation
2283 _panner->data().clear();
2287 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2289 // XXX: would be nice to get rid of this special hack
2291 if (param.type() == GainAutomation) {
2293 bool changed = false;
2296 Glib::Mutex::Lock lm (control_lock());
2298 boost::shared_ptr<AutomationList> gain_auto
2299 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2301 if (state != gain_auto->automation_state()) {
2303 _last_automation_snapshot = 0;
2304 gain_auto->set_automation_state (state);
2307 // FIXME: shouldn't this use Curve?
2308 set_gain (gain_auto->eval (_session.transport_frame()), this);
2314 _session.set_dirty ();
2318 AutomatableControls::set_parameter_automation_state(param, state);
2323 IO::inc_gain (gain_t factor, void *src)
2325 if (_desired_gain == 0.0f)
2326 set_gain (0.000001f + (0.000001f * factor), src);
2328 set_gain (_desired_gain + (_desired_gain * factor), src);
2332 IO::set_gain (gain_t val, void *src)
2334 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2335 if (val > 1.99526231f)
2338 if (src != _gain_control.get()) {
2339 _gain_control->set_value(val);
2340 // bit twisty, this will come back and call us again
2341 // (this keeps control in sync with reality)
2346 Glib::Mutex::Lock dm (declick_lock);
2347 _desired_gain = val;
2350 if (_session.transport_stopped()) {
2355 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2356 _gain_control->list()->add (_session.transport_frame(), val);
2361 _session.set_dirty();
2365 IO::start_pan_touch (uint32_t which)
2367 if (which < _panner->npanners()) {
2368 (*_panner).pan_control(which)->start_touch();
2373 IO::end_pan_touch (uint32_t which)
2375 if (which < _panner->npanners()) {
2376 (*_panner).pan_control(which)->stop_touch();
2382 IO::automation_snapshot (nframes_t now, bool force)
2384 AutomatableControls::automation_snapshot (now, force);
2385 // XXX: This seems to be wrong.
2386 // drobilla: shouldnt automation_snapshot for panner be called
2387 // "automagically" because its an Automatable now ?
2389 // we could dump this whole method then. <3
2391 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2392 _panner->automation_snapshot (now, force);
2395 _panner->automation_snapshot (now, force);
2396 _last_automation_snapshot = now;
2400 IO::transport_stopped (nframes_t frame)
2402 _gain_control->list()->reposition_for_rt_add (frame);
2404 if (_gain_control->automation_state() != Off) {
2406 /* the src=0 condition is a special signal to not propagate
2407 automation gain changes into the mix group when locating.
2410 // FIXME: shouldn't this use Curve?
2411 set_gain (_gain_control->list()->eval (frame), 0);
2414 _panner->transport_stopped (frame);
2418 IO::build_legal_port_name (DataType type, bool in)
2420 const int name_size = jack_port_name_size();
2425 if (type == DataType::AUDIO) {
2426 suffix = _("audio");
2427 } else if (type == DataType::MIDI) {
2430 throw unknown_type();
2435 maxports = _input_maximum.get(type);
2437 suffix += _("_out");
2438 maxports = _output_maximum.get(type);
2441 if (maxports == 1) {
2442 // allow space for the slash + the suffix
2443 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2444 char buf[name_size+1];
2445 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2446 return string (buf);
2449 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2451 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2453 char buf1[name_size+1];
2454 char buf2[name_size+1];
2456 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2461 port_number = find_input_port_hole (buf1);
2463 port_number = find_output_port_hole (buf1);
2466 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2468 return string (buf2);
2472 IO::find_input_port_hole (const char* base)
2474 /* CALLER MUST HOLD IO LOCK */
2478 if (_inputs.empty()) {
2482 /* we only allow up to 4 characters for the port number
2485 for (n = 1; n < 9999; ++n) {
2486 char buf[jack_port_name_size()];
2487 PortSet::iterator i = _inputs.begin();
2489 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2491 for ( ; i != _inputs.end(); ++i) {
2492 if (i->short_name() == buf) {
2497 if (i == _inputs.end()) {
2505 IO::find_output_port_hole (const char* base)
2507 /* CALLER MUST HOLD IO LOCK */
2511 if (_outputs.empty()) {
2515 /* we only allow up to 4 characters for the port number
2518 for (n = 1; n < 9999; ++n) {
2519 char buf[jack_port_name_size()];
2520 PortSet::iterator i = _outputs.begin();
2522 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2524 for ( ; i != _outputs.end(); ++i) {
2525 if (i->short_name() == buf) {
2530 if (i == _outputs.end()) {
2539 IO::set_active (bool yn)
2542 active_changed(); /* EMIT SIGNAL */
2547 IO::audio_input(uint32_t n) const
2549 return dynamic_cast<AudioPort*>(input(n));
2553 IO::audio_output(uint32_t n) const
2555 return dynamic_cast<AudioPort*>(output(n));
2559 IO::midi_input(uint32_t n) const
2561 return dynamic_cast<MidiPort*>(input(n));
2565 IO::midi_output(uint32_t n) const
2567 return dynamic_cast<MidiPort*>(output(n));
2571 IO::set_phase_invert (bool yn, void *src)
2573 if (_phase_invert != yn) {
2575 // phase_invert_changed (src); /* EMIT SIGNAL */
2580 IO::set_denormal_protection (bool yn, void *src)
2582 if (_denormal_protection != yn) {
2583 _denormal_protection = yn;
2584 // denormal_protection_changed (src); /* EMIT SIGNAL */
2589 IO::update_port_total_latencies ()
2591 /* io_lock, not taken: function must be called from Session::process() calltree */
2593 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2594 _session.engine().update_total_latency (*i);
2597 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2598 _session.engine().update_total_latency (*i);
2604 * Setup bundles that describe our inputs and outputs.
2608 IO::setup_bundles_for_inputs_and_outputs ()
2612 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2613 _bundle_for_inputs->set_name (buf);
2614 uint32_t const ni = inputs().num_ports();
2615 _bundle_for_inputs->set_channels (ni);
2616 for (uint32_t i = 0; i < ni; ++i) {
2617 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2620 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2621 _bundle_for_outputs->set_name (buf);
2622 uint32_t const no = outputs().num_ports();
2623 _bundle_for_outputs->set_channels (no);
2624 for (uint32_t i = 0; i < no; ++i) {
2625 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2631 * Create and setup bundles that describe our inputs and outputs.
2635 IO::create_bundles_for_inputs_and_outputs ()
2637 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2638 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2639 setup_bundles_for_inputs_and_outputs ();
2642 /** Add a bundle to a list if is connected to our inputs.
2643 * @param b Bundle to check.
2644 * @param bundles List to add to.
2647 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2649 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2651 if (ab == 0 || ab->ports_are_outputs() == false) {
2655 if (ab->nchannels().get (default_type()) != n_inputs().n_total ()) {
2659 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2661 PortList const & pl = b->channel_ports (i);
2667 if (!input(i)->connected_to (pl[0])) {
2672 bundles->push_back (b);
2675 /** @return Bundles connected to our inputs */
2676 std::vector<boost::shared_ptr<Bundle> >
2677 IO::bundles_connected_to_inputs ()
2679 std::vector<boost::shared_ptr<Bundle> > bundles;
2682 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2683 bundles.push_back (i->bundle);
2687 _session.foreach_bundle (
2688 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2695 /** Add a bundle to a list if is connected to our outputs.
2696 * @param b Bundle to check.
2697 * @param bundles List to add to.
2700 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2702 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2703 if (ab == 0 || ab->ports_are_inputs() == false) {
2707 if (ab->nchannels ().get (default_type()) != n_outputs().n_total ()) {
2711 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2713 PortList const & pl = b->channel_ports (i);
2719 if (!output(i)->connected_to (pl[0])) {
2724 bundles->push_back (b);
2728 /* @return Bundles connected to our outputs */
2729 std::vector<boost::shared_ptr<Bundle> >
2730 IO::bundles_connected_to_outputs ()
2732 std::vector<boost::shared_ptr<Bundle> > bundles;
2735 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2736 bundles.push_back (i->bundle);
2740 _session.foreach_bundle (
2741 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2748 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2751 configuration_will_change = b->ConfigurationWillChange.connect (
2752 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2754 configuration_has_changed = b->ConfigurationHasChanged.connect (
2755 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2757 ports_will_change = b->PortsWillChange.connect (
2758 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2760 ports_have_changed = b->PortsHaveChanged.connect (
2761 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)
2766 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2768 /* io_lock, not taken: function must be called from Session::process() calltree */
2770 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2771 (*i).cycle_start (nframes, offset);