2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
28 #include <glibmm/thread.h>
30 #include <pbd/xml++.h>
31 #include <pbd/replace_all.h>
32 #include <pbd/unknown_type.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/io.h>
36 #include <ardour/route.h>
37 #include <ardour/port.h>
38 #include <ardour/audio_port.h>
39 #include <ardour/midi_port.h>
40 #include <ardour/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/buffer_set.h>
44 #include <ardour/meter.h>
45 #include <ardour/amp.h>
46 #include <ardour/user_bundle.h>
53 A bug in OS X's cmath that causes isnan() and isinf() to be
54 "undeclared". the following works around that
57 #if defined(__APPLE__) && defined(__MACH__)
58 extern "C" int isnan (double);
59 extern "C" int isinf (double);
62 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
65 using namespace ARDOUR;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,ChanCount> IO::PortCountChanged;
77 sigc::signal<int> IO::PortsCreated;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
100 /** @param default_type The type of port that will be created by ensure_io
101 * and friends if no type is explicitly requested (to avoid breakage).
103 IO::IO (Session& s, const string& name,
104 int input_min, int input_max, int output_min, int output_max,
105 DataType default_type, bool public_ports)
106 : SessionObject(s, name),
107 AutomatableControls (s),
108 _output_buffers (new BufferSet()),
110 _default_type (default_type),
111 _public_ports (public_ports),
112 _input_minimum (ChanCount::ZERO),
113 _input_maximum (ChanCount::INFINITE),
114 _output_minimum (ChanCount::ZERO),
115 _output_maximum (ChanCount::INFINITE)
117 _panner = new Panner (name, _session);
118 _meter = new PeakMeter (_session);
121 _input_minimum = ChanCount(_default_type, input_min);
123 if (input_max >= 0) {
124 _input_maximum = ChanCount(_default_type, input_max);
126 if (output_min > 0) {
127 _output_minimum = ChanCount(_default_type, output_min);
129 if (output_max >= 0) {
130 _output_maximum = ChanCount(_default_type, output_max);
135 pending_state_node = 0;
136 no_panner_reset = false;
137 _phase_invert = false;
140 boost::shared_ptr<AutomationList> gl(
141 new AutomationList(Evoral::Parameter(GainAutomation)));
143 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
145 add_control(_gain_control);
147 apply_gain_automation = false;
150 // IO::Meter is emitted from another thread so the
151 // Meter signal must be protected.
152 Glib::Mutex::Lock guard (m_meter_signal_lock);
153 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
156 _session.add_controllable (_gain_control);
158 setup_bundles_for_inputs_and_outputs ();
161 IO::IO (Session& s, const XMLNode& node, DataType dt)
162 : SessionObject(s, "unnamed io"),
163 AutomatableControls (s),
164 _output_buffers (new BufferSet()),
168 _meter = new PeakMeter (_session);
169 _public_ports = true; // XXX get this from node
172 no_panner_reset = false;
176 apply_gain_automation = false;
178 boost::shared_ptr<AutomationList> gl(
179 new AutomationList(Evoral::Parameter(GainAutomation)));
181 _gain_control = boost::shared_ptr<GainControl>(
182 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
184 add_control(_gain_control);
189 // IO::Meter is emitted from another thread so the
190 // Meter signal must be protected.
191 Glib::Mutex::Lock guard (m_meter_signal_lock);
192 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
195 _session.add_controllable (_gain_control);
197 setup_bundles_for_inputs_and_outputs ();
202 Glib::Mutex::Lock guard (m_meter_signal_lock);
203 Glib::Mutex::Lock lm (io_lock);
205 BLOCK_PROCESS_CALLBACK ();
207 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
208 _session.engine().unregister_port (*i);
211 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
212 _session.engine().unregister_port (*i);
215 m_meter_connection.disconnect();
222 IO::silence (nframes_t nframes, nframes_t offset)
224 /* io_lock, not taken: function must be called from Session::process() calltree */
226 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
227 i->get_buffer(nframes,offset).silence (nframes, offset);
231 /** Deliver bufs to the IO's output ports
233 * This function should automatically do whatever it necessary to correctly deliver bufs
234 * to the outputs, eg applying gain or pan or whatever else needs to be done.
237 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
239 // FIXME: type specific code doesn't actually need to be here, it will go away in time
241 /* ********** AUDIO ********** */
243 // Apply gain if gain automation isn't playing
244 if ( ! apply_gain_automation) {
246 gain_t dg = _gain; // desired gain
249 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
257 if (dg != _gain || dg != 1.0) {
258 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
263 /* do this so that any processing that comes after deliver_outputs()
264 can use the output buffers.
267 output_buffers().attach_buffers (_outputs, nframes, offset);
269 // Use the panner to distribute audio to output port buffers
271 if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
273 /* blech .. we shouldn't be creating and tearing this down every process()
274 cycle. XXX fix me to not waste cycles and do memory allocation etc.
277 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
281 /* do a 1:1 copy of data to output ports */
283 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
284 copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
286 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
287 copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
293 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
295 // Copy any buffers 1:1 to outputs
297 PortSet::iterator o = _outputs.begin(type);
298 BufferSet::iterator i = bufs.begin(type);
299 BufferSet::iterator prev = i;
301 while (i != bufs.end(type) && o != _outputs.end (type)) {
303 Buffer& port_buffer (o->get_buffer (nframes, offset));
304 port_buffer.read_from (*i, nframes, offset);
311 /* extra outputs get a copy of the last buffer */
313 while (o != _outputs.end(type)) {
314 Buffer& port_buffer (o->get_buffer (nframes, offset));
315 port_buffer.read_from(*prev, nframes, offset);
321 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
323 assert(outs.available() >= n_inputs());
325 if (n_inputs() == ChanCount::ZERO)
328 outs.set_count(n_inputs());
330 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
332 BufferSet::iterator o = outs.begin(*t);
333 PortSet::iterator e = _inputs.end (*t);
334 for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
335 Buffer& b (i->get_buffer (nframes,offset));
336 o->read_from (b, nframes, offset);
343 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
344 nframes_t nframes, nframes_t offset)
346 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
348 collect_input (bufs, nframes, offset);
350 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
355 IO::check_bundles_connected_to_inputs ()
357 check_bundles (_bundles_connected_to_inputs, inputs());
361 IO::check_bundles_connected_to_outputs ()
363 check_bundles (_bundles_connected_to_outputs, outputs());
367 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
369 std::vector<UserBundleInfo> new_list;
371 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
373 uint32_t const N = i->bundle->nchannels ();
375 if (ports.num_ports (default_type()) < N) {
381 for (uint32_t j = 0; j < N; ++j) {
382 /* Every port on bundle channel j must be connected to our input j */
383 Bundle::PortList const pl = i->bundle->channel_ports (j);
384 for (uint32_t k = 0; k < pl.size(); ++k) {
385 if (ports.port(j)->connected_to (pl[k]) == false) {
397 new_list.push_back (*i);
399 i->changed.disconnect ();
408 IO::disconnect_input (Port* our_port, string other_port, void* src)
410 if (other_port.length() == 0 || our_port == 0) {
415 BLOCK_PROCESS_CALLBACK ();
418 Glib::Mutex::Lock lm (io_lock);
420 /* check that our_port is really one of ours */
422 if ( ! _inputs.contains(our_port)) {
426 /* disconnect it from the source */
428 if (_session.engine().disconnect (other_port, our_port->name())) {
429 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
433 check_bundles_connected_to_inputs ();
437 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
438 _session.set_dirty ();
444 IO::connect_input (Port* our_port, string other_port, void* src)
446 if (other_port.length() == 0 || our_port == 0) {
451 BLOCK_PROCESS_CALLBACK ();
454 Glib::Mutex::Lock lm (io_lock);
456 /* check that our_port is really one of ours */
458 if ( ! _inputs.contains(our_port) ) {
462 /* connect it to the source */
464 if (_session.engine().connect (other_port, our_port->name())) {
470 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
471 _session.set_dirty ();
476 IO::disconnect_output (Port* our_port, string other_port, void* src)
478 if (other_port.length() == 0 || our_port == 0) {
483 BLOCK_PROCESS_CALLBACK ();
486 Glib::Mutex::Lock lm (io_lock);
488 /* check that our_port is really one of ours */
490 if ( ! _outputs.contains(our_port) ) {
494 /* disconnect it from the destination */
496 if (_session.engine().disconnect (our_port->name(), other_port)) {
497 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
501 check_bundles_connected_to_outputs ();
505 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
506 _session.set_dirty ();
511 IO::connect_output (Port* our_port, string other_port, void* src)
513 if (other_port.length() == 0 || our_port == 0) {
518 BLOCK_PROCESS_CALLBACK ();
522 Glib::Mutex::Lock lm (io_lock);
524 /* check that our_port is really one of ours */
526 if ( ! _outputs.contains(our_port) ) {
530 /* connect it to the destination */
532 if (_session.engine().connect (our_port->name(), other_port)) {
538 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
539 _session.set_dirty ();
544 IO::set_input (Port* other_port, void* src)
546 /* this removes all but one ports, and connects that one port
547 to the specified source.
550 if (_input_minimum.n_total() > 1) {
551 /* sorry, you can't do this */
555 if (other_port == 0) {
556 if (_input_minimum == ChanCount::ZERO) {
557 return ensure_inputs (ChanCount::ZERO, false, true, src);
563 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
567 return connect_input (_inputs.port(0), other_port->name(), src);
571 IO::remove_output_port (Port* port, void* src)
573 IOChange change (NoChange);
576 BLOCK_PROCESS_CALLBACK ();
580 Glib::Mutex::Lock lm (io_lock);
582 if (n_outputs() <= _output_minimum) {
583 /* sorry, you can't do this */
587 if (_outputs.remove(port)) {
588 change = IOChange (change|ConfigurationChanged);
590 if (port->connected()) {
591 change = IOChange (change|ConnectionsChanged);
594 _session.engine().unregister_port (*port);
595 check_bundles_connected_to_outputs ();
597 setup_peak_meters ();
602 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
605 if (change == ConfigurationChanged) {
606 setup_bundle_for_outputs ();
609 if (change != NoChange) {
610 output_changed (change, src);
611 _session.set_dirty ();
618 /** Add an output port.
620 * @param destination Name of input port to connect new port to.
621 * @param src Source for emitted ConfigurationChanged signal.
622 * @param type Data type of port. Default value (NIL) will use this IO's default type.
625 IO::add_output_port (string destination, void* src, DataType type)
629 if (type == DataType::NIL)
630 type = _default_type;
633 BLOCK_PROCESS_CALLBACK ();
637 Glib::Mutex::Lock lm (io_lock);
639 if (n_outputs() >= _output_maximum) {
643 /* Create a new output port */
645 string portname = build_legal_port_name (type, false);
647 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
648 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
652 _outputs.add (our_port);
653 setup_peak_meters ();
657 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
660 if (destination.length()) {
661 if (_session.engine().connect (our_port->name(), destination)) {
666 // pan_changed (src); /* EMIT SIGNAL */
667 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
668 setup_bundle_for_outputs ();
669 _session.set_dirty ();
675 IO::remove_input_port (Port* port, void* src)
677 IOChange change (NoChange);
680 BLOCK_PROCESS_CALLBACK ();
684 Glib::Mutex::Lock lm (io_lock);
686 if (n_inputs() <= _input_minimum) {
687 /* sorry, you can't do this */
691 if (_inputs.remove(port)) {
692 change = IOChange (change|ConfigurationChanged);
694 if (port->connected()) {
695 change = IOChange (change|ConnectionsChanged);
698 _session.engine().unregister_port (*port);
699 check_bundles_connected_to_inputs ();
701 setup_peak_meters ();
706 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
709 if (change == ConfigurationChanged) {
710 setup_bundle_for_inputs ();
713 if (change != NoChange) {
714 input_changed (change, src);
715 _session.set_dirty ();
723 /** Add an input port.
725 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
726 * @param destination Name of input port to connect new port to.
727 * @param src Source for emitted ConfigurationChanged signal.
730 IO::add_input_port (string source, void* src, DataType type)
734 if (type == DataType::NIL)
735 type = _default_type;
738 BLOCK_PROCESS_CALLBACK ();
741 Glib::Mutex::Lock lm (io_lock);
743 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
747 /* Create a new input port */
749 string portname = build_legal_port_name (type, true);
751 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
752 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
756 _inputs.add (our_port);
757 setup_peak_meters ();
761 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
764 if (source.length()) {
766 if (_session.engine().connect (source, our_port->name())) {
771 // pan_changed (src); /* EMIT SIGNAL */
772 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
773 setup_bundle_for_inputs ();
774 _session.set_dirty ();
780 IO::disconnect_inputs (void* src)
783 BLOCK_PROCESS_CALLBACK ();
786 Glib::Mutex::Lock lm (io_lock);
788 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
789 _session.engine().disconnect (*i);
792 check_bundles_connected_to_inputs ();
796 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
802 IO::disconnect_outputs (void* src)
805 BLOCK_PROCESS_CALLBACK ();
808 Glib::Mutex::Lock lm (io_lock);
810 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
811 _session.engine().disconnect (*i);
814 check_bundles_connected_to_outputs ();
818 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
819 _session.set_dirty ();
825 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
827 Port* input_port = 0;
828 bool changed = false;
831 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
833 const size_t n = count.get(*t);
835 /* remove unused ports */
836 for (size_t i = n_inputs().get(*t); i > n; --i) {
837 input_port = _inputs.port(*t, i-1);
840 _inputs.remove(input_port);
841 _session.engine().unregister_port (*input_port);
846 /* create any necessary new ports */
847 while (n_inputs().get(*t) < n) {
849 string portname = build_legal_port_name (*t, true);
853 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
854 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
859 catch (AudioEngine::PortRegistrationFailure& err) {
860 setup_peak_meters ();
863 throw AudioEngine::PortRegistrationFailure();
866 _inputs.add (input_port);
872 check_bundles_connected_to_inputs ();
873 setup_peak_meters ();
875 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
876 _session.set_dirty ();
880 /* disconnect all existing ports so that we get a fresh start */
881 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
882 _session.engine().disconnect (*i);
890 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
892 bool in_changed = false;
893 bool out_changed = false;
894 bool need_pan_reset = false;
896 in = min (_input_maximum, in);
898 out = min (_output_maximum, out);
900 if (in == n_inputs() && out == n_outputs() && !clear) {
905 BLOCK_PROCESS_CALLBACK ();
906 Glib::Mutex::Lock lm (io_lock);
910 if (n_outputs() != out) {
911 need_pan_reset = true;
914 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
916 const size_t nin = in.get(*t);
917 const size_t nout = out.get(*t);
919 Port* output_port = 0;
920 Port* input_port = 0;
922 /* remove unused output ports */
923 for (size_t i = n_outputs().get(*t); i > nout; --i) {
924 output_port = _outputs.port(*t, i-1);
927 _outputs.remove(output_port);
928 _session.engine().unregister_port (*output_port);
933 /* remove unused input ports */
934 for (size_t i = n_inputs().get(*t); i > nin; --i) {
935 input_port = _inputs.port(*t, i-1);
938 _inputs.remove(input_port);
939 _session.engine().unregister_port (*input_port);
944 /* create any necessary new input ports */
946 while (n_inputs().get(*t) < nin) {
948 string portname = build_legal_port_name (*t, true);
951 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
952 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
957 catch (AudioEngine::PortRegistrationFailure& err) {
958 setup_peak_meters ();
961 throw AudioEngine::PortRegistrationFailure();
968 /* create any necessary new output ports */
970 while (n_outputs().get(*t) < nout) {
972 string portname = build_legal_port_name (*t, false);
975 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
976 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
981 catch (AudioEngine::PortRegistrationFailure& err) {
982 setup_peak_meters ();
985 throw AudioEngine::PortRegistrationFailure ();
995 /* disconnect all existing ports so that we get a fresh start */
997 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
998 _session.engine().disconnect (*i);
1001 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1002 _session.engine().disconnect (*i);
1006 if (in_changed || out_changed) {
1007 setup_peak_meters ();
1013 check_bundles_connected_to_outputs ();
1014 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1015 setup_bundle_for_outputs ();
1019 check_bundles_connected_to_inputs ();
1020 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1021 setup_bundle_for_inputs ();
1024 if (in_changed || out_changed) {
1025 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1026 _session.set_dirty ();
1033 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1035 bool changed = false;
1037 count = min (_input_maximum, count);
1039 if (count == n_inputs() && !clear) {
1044 BLOCK_PROCESS_CALLBACK ();
1045 Glib::Mutex::Lock im (io_lock);
1046 changed = ensure_inputs_locked (count, clear, src);
1048 changed = ensure_inputs_locked (count, clear, src);
1052 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1053 setup_bundle_for_inputs ();
1054 _session.set_dirty ();
1060 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1062 Port* output_port = 0;
1063 bool changed = false;
1064 bool need_pan_reset = false;
1066 if (n_outputs() != count) {
1067 need_pan_reset = true;
1070 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1072 const size_t n = count.get(*t);
1074 /* remove unused ports */
1075 for (size_t i = n_outputs().get(*t); i > n; --i) {
1076 output_port = _outputs.port(*t, i-1);
1078 assert(output_port);
1079 _outputs.remove(output_port);
1080 _session.engine().unregister_port (*output_port);
1085 /* create any necessary new ports */
1086 while (n_outputs().get(*t) < n) {
1088 string portname = build_legal_port_name (*t, false);
1090 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1091 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1095 _outputs.add (output_port);
1097 setup_peak_meters ();
1099 if (need_pan_reset) {
1106 check_bundles_connected_to_outputs ();
1107 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1108 _session.set_dirty ();
1112 /* disconnect all existing ports so that we get a fresh start */
1113 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1114 _session.engine().disconnect (*i);
1122 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1124 bool changed = false;
1126 if (_output_maximum < ChanCount::INFINITE) {
1127 count = min (_output_maximum, count);
1128 if (count == n_outputs() && !clear) {
1133 /* XXX caller should hold io_lock, but generally doesn't */
1136 BLOCK_PROCESS_CALLBACK ();
1137 Glib::Mutex::Lock im (io_lock);
1138 changed = ensure_outputs_locked (count, clear, src);
1140 changed = ensure_outputs_locked (count, clear, src);
1144 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1145 setup_bundle_for_outputs ();
1152 IO::effective_gain () const
1154 if (_gain_control->automation_playback()) {
1155 return _gain_control->get_value();
1157 return _desired_gain;
1164 if (panners_legal) {
1165 if (!no_panner_reset) {
1166 _panner->reset (n_outputs().n_audio(), pans_required());
1169 panner_legal_c.disconnect ();
1170 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1175 IO::panners_became_legal ()
1177 _panner->reset (n_outputs().n_audio(), pans_required());
1178 _panner->load (); // automation
1179 panner_legal_c.disconnect ();
1184 IO::defer_pan_reset ()
1186 no_panner_reset = true;
1190 IO::allow_pan_reset ()
1192 no_panner_reset = false;
1198 IO::get_state (void)
1200 return state (true);
1204 IO::state (bool full_state)
1206 XMLNode* node = new XMLNode (state_node_name);
1209 vector<string>::iterator ci;
1211 LocaleGuard lg (X_("POSIX"));
1212 Glib::Mutex::Lock lm (io_lock);
1214 node->add_property("name", _name);
1215 id().print (buf, sizeof (buf));
1216 node->add_property("id", buf);
1219 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1220 i != _bundles_connected_to_inputs.end();
1224 XMLNode* n = new XMLNode ("InputBundle");
1225 n->add_property ("name", i->bundle->name ());
1226 node->add_child_nocopy (*n);
1230 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1231 i != _bundles_connected_to_outputs.end();
1235 XMLNode* n = new XMLNode ("OutputBundle");
1236 n->add_property ("name", i->bundle->name ());
1237 node->add_child_nocopy (*n);
1242 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1244 vector<string> connections;
1246 if (i->get_connections (connections)) {
1250 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1255 /* if its a connection to our own port,
1256 return only the port name, not the
1257 whole thing. this allows connections
1258 to be re-established even when our
1259 client name is different.
1262 str += _session.engine().make_port_name_relative (*ci);
1272 node->add_property ("inputs", str);
1276 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1278 vector<string> connections;
1280 if (i->get_connections (connections)) {
1284 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1289 str += _session.engine().make_port_name_relative (*ci);
1299 node->add_property ("outputs", str);
1301 node->add_child_nocopy (_panner->state (full_state));
1302 node->add_child_nocopy (_gain_control->get_state ());
1304 snprintf (buf, sizeof(buf), "%2.12f", gain());
1305 node->add_property ("gain", buf);
1307 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1311 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1312 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1314 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1316 node->add_property ("iolimits", buf);
1321 node->add_child_nocopy (get_automation_state());
1327 IO::set_state (const XMLNode& node)
1329 const XMLProperty* prop;
1330 XMLNodeConstIterator iter;
1331 LocaleGuard lg (X_("POSIX"));
1333 /* force use of non-localized representation of decimal point,
1334 since we use it a lot in XML files and so forth.
1337 if (node.name() != state_node_name) {
1338 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1342 if ((prop = node.property ("name")) != 0) {
1343 _name = prop->value();
1344 /* used to set panner name with this, but no more */
1347 if ((prop = node.property ("id")) != 0) {
1348 _id = prop->value ();
1356 if ((prop = node.property ("iolimits")) != 0) {
1357 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1358 &in_min, &in_max, &out_min, &out_max);
1360 /* Correct for the difference between the way we write things to session files and the
1361 way things are described by ChanCount; see comments in io.h about what the different
1362 ChanCount values mean. */
1365 _input_minimum = ChanCount::ZERO;
1367 _input_minimum = ChanCount (_default_type, in_min);
1371 _input_maximum = ChanCount::INFINITE;
1373 _input_maximum = ChanCount (_default_type, in_max);
1377 _output_minimum = ChanCount::ZERO;
1379 _output_minimum = ChanCount (_default_type, out_min);
1383 _output_maximum = ChanCount::INFINITE;
1385 _output_maximum = ChanCount (_default_type, out_max);
1389 if ((prop = node.property ("gain")) != 0) {
1390 set_gain (atof (prop->value().c_str()), this);
1391 _gain = _desired_gain;
1394 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1395 /* old school automation handling */
1398 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1400 // Old school Panner.
1401 if ((*iter)->name() == "Panner") {
1403 _panner = new Panner (_name, _session);
1405 _panner->set_state (**iter);
1408 if ((*iter)->name() == "Processor") {
1409 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1411 _panner = new Panner (_name, _session);
1413 _panner->set_state (**iter);
1417 if ((*iter)->name() == X_("Automation")) {
1419 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1422 if ((*iter)->name() == X_("controllable")) {
1423 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1424 _gain_control->set_state (**iter);
1431 if (create_ports (node)) {
1437 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1441 _panner = new Panner( _name, _session );
1442 if (panners_legal) {
1445 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1448 if (connecting_legal) {
1450 if (make_connections (node)) {
1456 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1459 if (!ports_legal || !connecting_legal) {
1460 pending_state_node = new XMLNode (node);
1467 IO::load_automation (string path)
1472 uint32_t linecnt = 0;
1474 LocaleGuard lg (X_("POSIX"));
1476 fullpath = Glib::build_filename(_session.automation_dir(), path);
1478 in.open (fullpath.c_str());
1481 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1483 in.open (fullpath.c_str());
1486 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1491 clear_automation ();
1493 while (in.getline (line, sizeof(line), '\n')) {
1498 if (++linecnt == 1) {
1499 if (memcmp (line, "version", 7) == 0) {
1500 if (sscanf (line, "version %f", &version) != 1) {
1501 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1505 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1512 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1513 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1519 _gain_control->list()->fast_simple_add (when, value);
1529 /* older (pre-1.0) versions of ardour used this */
1533 warning << _("dubious automation event found (and ignored)") << endmsg;
1541 IO::connecting_became_legal ()
1545 if (pending_state_node == 0) {
1546 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1551 connection_legal_c.disconnect ();
1553 ret = make_connections (*pending_state_node);
1556 delete pending_state_node;
1557 pending_state_node = 0;
1563 IO::ports_became_legal ()
1567 if (pending_state_node == 0) {
1568 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1573 port_legal_c.disconnect ();
1575 ret = create_ports (*pending_state_node);
1577 if (connecting_legal) {
1578 delete pending_state_node;
1579 pending_state_node = 0;
1585 boost::shared_ptr<Bundle>
1586 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1588 static const string digits = "0123456789";
1590 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1593 int bundle_number, mask;
1594 string possible_name;
1595 bool stereo = false;
1596 string::size_type last_non_digit_pos;
1598 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1601 // find numeric suffix of desired name
1604 last_non_digit_pos = desired_name.find_last_not_of(digits);
1606 if (last_non_digit_pos != string::npos) {
1608 s << desired_name.substr(last_non_digit_pos);
1612 // see if it's a stereo connection e.g. "in 3+4"
1614 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1615 int left_bundle_number = 0;
1616 string::size_type left_last_non_digit_pos;
1618 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1620 if (left_last_non_digit_pos != string::npos) {
1622 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1623 s >> left_bundle_number;
1625 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1636 // find highest set bit
1638 while ((mask <= bundle_number) && (mask <<= 1));
1640 // "wrap" bundle number into largest possible power of 2
1645 if (bundle_number & mask) {
1646 bundle_number &= ~mask;
1649 s << default_name << " " << bundle_number + 1;
1652 s << "+" << bundle_number + 2;
1655 possible_name = s.str();
1657 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1664 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1667 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1678 IO::create_ports (const XMLNode& node)
1680 XMLProperty const * prop;
1681 uint32_t num_inputs = 0;
1682 uint32_t num_outputs = 0;
1684 if ((prop = node.property ("input-connection")) != 0) {
1686 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1692 num_inputs = c->nchannels();
1694 } else if ((prop = node.property ("inputs")) != 0) {
1696 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1699 if ((prop = node.property ("output-connection")) != 0) {
1701 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1707 num_outputs = c->nchannels ();
1709 } else if ((prop = node.property ("outputs")) != 0) {
1711 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1714 no_panner_reset = true;
1716 if (ensure_io (ChanCount (_default_type, num_inputs),
1717 ChanCount (_default_type, num_outputs),
1720 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1724 no_panner_reset = false;
1726 set_deferred_state ();
1734 IO::make_connections (const XMLNode& node)
1737 const XMLProperty* prop;
1739 if ((prop = node.property ("input-connection")) != 0) {
1740 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1746 connect_input_ports_to_bundle (c, this);
1748 } else if ((prop = node.property ("inputs")) != 0) {
1749 if (set_inputs (prop->value())) {
1750 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1755 if ((prop = node.property ("output-connection")) != 0) {
1756 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1762 connect_output_ports_to_bundle (c, this);
1764 } else if ((prop = node.property ("outputs")) != 0) {
1765 if (set_outputs (prop->value())) {
1766 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1771 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1773 if ((*i)->name() == "InputBundle") {
1774 XMLProperty const * prop = (*i)->property ("name");
1776 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1778 connect_input_ports_to_bundle (b, this);
1782 } else if ((*i)->name() == "OutputBundle") {
1783 XMLProperty const * prop = (*i)->property ("name");
1785 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1787 connect_output_ports_to_bundle (b, this);
1797 IO::set_inputs (const string& str)
1799 vector<string> ports;
1804 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1808 // FIXME: audio-only
1809 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1813 string::size_type start, end, ostart;
1820 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1823 if ((end = str.find_first_of ('}', start)) == string::npos) {
1824 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1828 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1829 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1835 for (int x = 0; x < n; ++x) {
1836 connect_input (input (i), ports[x], this);
1848 IO::set_outputs (const string& str)
1850 vector<string> ports;
1855 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1859 // FIXME: audio-only
1860 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1864 string::size_type start, end, ostart;
1871 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1874 if ((end = str.find_first_of ('}', start)) == string::npos) {
1875 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1879 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1880 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1886 for (int x = 0; x < n; ++x) {
1887 connect_output (output (i), ports[x], this);
1899 IO::parse_io_string (const string& str, vector<string>& ports)
1901 string::size_type pos, opos;
1903 if (str.length() == 0) {
1912 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1913 ports.push_back (str.substr (opos, pos - opos));
1917 if (opos < str.length()) {
1918 ports.push_back (str.substr(opos));
1921 return ports.size();
1925 IO::parse_gain_string (const string& str, vector<string>& ports)
1927 string::size_type pos, opos;
1933 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1934 ports.push_back (str.substr (opos, pos - opos));
1938 if (opos < str.length()) {
1939 ports.push_back (str.substr(opos));
1942 return ports.size();
1946 IO::set_name (const string& requested_name)
1948 if (requested_name == _name) {
1954 if ( (rt = dynamic_cast<Route *>(this))) {
1955 name = Route::ensure_track_or_route_name(requested_name, _session);
1957 name = requested_name;
1961 /* replace all colons in the name. i wish we didn't have to do this */
1963 if (replace_all (name, ":", "-")) {
1964 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1967 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1968 string current_name = i->name();
1969 current_name.replace (current_name.find (_name), _name.length(), name);
1970 i->set_name (current_name);
1973 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1974 string current_name = i->name();
1975 current_name.replace (current_name.find (_name), _name.length(), name);
1976 i->set_name (current_name);
1979 bool const r = SessionObject::set_name(name);
1981 setup_bundles_for_inputs_and_outputs ();
1987 IO::set_input_minimum (ChanCount n)
1993 IO::set_input_maximum (ChanCount n)
1999 IO::set_output_minimum (ChanCount n)
2001 _output_minimum = n;
2005 IO::set_output_maximum (ChanCount n)
2007 _output_maximum = n;
2011 IO::set_port_latency (nframes_t nframes)
2013 Glib::Mutex::Lock lm (io_lock);
2015 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2016 i->set_latency (nframes);
2021 IO::output_latency () const
2023 nframes_t max_latency;
2028 /* io lock not taken - must be protected by other means */
2030 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2031 if ((latency = i->total_latency ()) > max_latency) {
2032 max_latency = latency;
2040 IO::input_latency () const
2042 nframes_t max_latency;
2047 /* io lock not taken - must be protected by other means */
2049 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2050 if ((latency = i->total_latency ()) > max_latency) {
2051 max_latency = latency;
2059 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2062 BLOCK_PROCESS_CALLBACK ();
2063 Glib::Mutex::Lock lm2 (io_lock);
2065 c->connect (_bundle_for_inputs, _session.engine());
2067 /* If this is a UserBundle, make a note of what we've done */
2069 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2072 /* See if we already know about this one */
2073 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2074 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2078 if (i == _bundles_connected_to_inputs.end()) {
2079 /* We don't, so make a note */
2080 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2085 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2090 IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2093 BLOCK_PROCESS_CALLBACK ();
2094 Glib::Mutex::Lock lm2 (io_lock);
2096 c->disconnect (_bundle_for_inputs, _session.engine());
2098 /* If this is a UserBundle, make a note of what we've done */
2100 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2103 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2104 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2108 if (i != _bundles_connected_to_inputs.end()) {
2109 _bundles_connected_to_inputs.erase (i);
2114 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2119 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2122 BLOCK_PROCESS_CALLBACK ();
2123 Glib::Mutex::Lock lm2 (io_lock);
2125 c->connect (_bundle_for_outputs, _session.engine());
2127 /* If this is a UserBundle, make a note of what we've done */
2129 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2132 /* See if we already know about this one */
2133 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2134 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2138 if (i == _bundles_connected_to_outputs.end()) {
2139 /* We don't, so make a note */
2140 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2145 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2151 IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2154 BLOCK_PROCESS_CALLBACK ();
2155 Glib::Mutex::Lock lm2 (io_lock);
2157 c->disconnect (_bundle_for_outputs, _session.engine());
2159 /* If this is a UserBundle, make a note of what we've done */
2161 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2164 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2165 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2169 if (i != _bundles_connected_to_outputs.end()) {
2170 _bundles_connected_to_outputs.erase (i);
2175 output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2181 IO::disable_connecting ()
2183 connecting_legal = false;
2188 IO::enable_connecting ()
2190 connecting_legal = true;
2191 return ConnectingLegal ();
2195 IO::disable_ports ()
2197 ports_legal = false;
2205 return PortsLegal ();
2209 IO::disable_panners (void)
2211 panners_legal = false;
2216 IO::reset_panners ()
2218 panners_legal = true;
2219 return PannersLegal ();
2223 IO::bundle_changed (Bundle::Change c)
2226 // connect_input_ports_to_bundle (_input_bundle, this);
2230 IO::GainControl::set_value (float val)
2232 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2233 if (val > 1.99526231f)
2236 _io->set_gain (val, this);
2238 AutomationControl::set_value(val);
2242 IO::GainControl::get_value (void) const
2244 return AutomationControl::get_value();
2248 IO::setup_peak_meters()
2250 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2251 _meter->configure_io (max_streams, max_streams);
2255 Update the peak meters.
2257 The meter signal lock is taken to prevent modification of the
2258 Meter signal while updating the meters, taking the meter signal
2259 lock prior to taking the io_lock ensures that all IO will remain
2260 valid while metering.
2265 Glib::Mutex::Lock guard (m_meter_signal_lock);
2266 Meter(); /* EMIT SIGNAL */
2272 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2274 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2279 IO::clear_automation ()
2281 data().clear (); // clears gain automation
2282 _panner->data().clear();
2286 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2288 // XXX: would be nice to get rid of this special hack
2290 if (param.type() == GainAutomation) {
2292 bool changed = false;
2295 Glib::Mutex::Lock lm (control_lock());
2297 boost::shared_ptr<AutomationList> gain_auto
2298 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2300 if (state != gain_auto->automation_state()) {
2302 _last_automation_snapshot = 0;
2303 gain_auto->set_automation_state (state);
2306 // FIXME: shouldn't this use Curve?
2307 set_gain (gain_auto->eval (_session.transport_frame()), this);
2313 _session.set_dirty ();
2317 AutomatableControls::set_parameter_automation_state(param, state);
2322 IO::inc_gain (gain_t factor, void *src)
2324 if (_desired_gain == 0.0f)
2325 set_gain (0.000001f + (0.000001f * factor), src);
2327 set_gain (_desired_gain + (_desired_gain * factor), src);
2331 IO::set_gain (gain_t val, void *src)
2333 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2334 if (val > 1.99526231f) {
2338 cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2340 if (src != _gain_control.get()) {
2341 _gain_control->set_value(val);
2342 // bit twisty, this will come back and call us again
2343 // (this keeps control in sync with reality)
2348 Glib::Mutex::Lock dm (declick_lock);
2349 _desired_gain = val;
2352 if (_session.transport_stopped()) {
2357 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2358 _gain_control->list()->add (_session.transport_frame(), val);
2363 _session.set_dirty();
2367 IO::start_pan_touch (uint32_t which)
2369 if (which < _panner->npanners()) {
2370 (*_panner).pan_control(which)->start_touch();
2375 IO::end_pan_touch (uint32_t which)
2377 if (which < _panner->npanners()) {
2378 (*_panner).pan_control(which)->stop_touch();
2384 IO::automation_snapshot (nframes_t now, bool force)
2386 AutomatableControls::automation_snapshot (now, force);
2387 // XXX: This seems to be wrong.
2388 // drobilla: shouldnt automation_snapshot for panner be called
2389 // "automagically" because its an Automatable now ?
2391 // we could dump this whole method then. <3
2393 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2394 _panner->automation_snapshot (now, force);
2397 _panner->automation_snapshot (now, force);
2398 _last_automation_snapshot = now;
2402 IO::transport_stopped (nframes_t frame)
2404 _gain_control->list()->reposition_for_rt_add (frame);
2406 if (_gain_control->automation_state() != Off) {
2408 /* the src=0 condition is a special signal to not propagate
2409 automation gain changes into the mix group when locating.
2412 // FIXME: shouldn't this use Curve?
2413 set_gain (_gain_control->list()->eval (frame), 0);
2416 _panner->transport_stopped (frame);
2420 IO::build_legal_port_name (DataType type, bool in)
2422 const int name_size = jack_port_name_size();
2427 if (type == DataType::AUDIO) {
2428 suffix = _("audio");
2429 } else if (type == DataType::MIDI) {
2432 throw unknown_type();
2437 maxports = _input_maximum.get(type);
2439 suffix += _("_out");
2440 maxports = _output_maximum.get(type);
2443 if (maxports == 1) {
2444 // allow space for the slash + the suffix
2445 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2446 char buf[name_size+1];
2447 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2448 return string (buf);
2451 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2453 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2455 char buf1[name_size+1];
2456 char buf2[name_size+1];
2458 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2463 port_number = find_input_port_hole (buf1);
2465 port_number = find_output_port_hole (buf1);
2468 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2470 return string (buf2);
2474 IO::find_input_port_hole (const char* base)
2476 /* CALLER MUST HOLD IO LOCK */
2480 if (_inputs.empty()) {
2484 /* we only allow up to 4 characters for the port number
2487 for (n = 1; n < 9999; ++n) {
2488 char buf[jack_port_name_size()];
2489 PortSet::iterator i = _inputs.begin();
2491 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2493 for ( ; i != _inputs.end(); ++i) {
2494 if (i->name() == buf) {
2499 if (i == _inputs.end()) {
2507 IO::find_output_port_hole (const char* base)
2509 /* CALLER MUST HOLD IO LOCK */
2513 if (_outputs.empty()) {
2517 /* we only allow up to 4 characters for the port number
2520 for (n = 1; n < 9999; ++n) {
2521 char buf[jack_port_name_size()];
2522 PortSet::iterator i = _outputs.begin();
2524 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2526 for ( ; i != _outputs.end(); ++i) {
2527 if (i->name() == buf) {
2532 if (i == _outputs.end()) {
2541 IO::set_active (bool yn)
2544 active_changed(); /* EMIT SIGNAL */
2548 IO::audio_input(uint32_t n) const
2550 return dynamic_cast<AudioPort*>(input(n));
2554 IO::audio_output(uint32_t n) const
2556 return dynamic_cast<AudioPort*>(output(n));
2560 IO::midi_input(uint32_t n) const
2562 return dynamic_cast<MidiPort*>(input(n));
2566 IO::midi_output(uint32_t n) const
2568 return dynamic_cast<MidiPort*>(output(n));
2572 IO::set_phase_invert (bool yn, void *src)
2574 if (_phase_invert != yn) {
2576 // phase_invert_changed (src); /* EMIT SIGNAL */
2581 IO::set_denormal_protection (bool yn, void *src)
2583 if (_denormal_protection != yn) {
2584 _denormal_protection = yn;
2585 // denormal_protection_changed (src); /* EMIT SIGNAL */
2590 IO::update_port_total_latencies ()
2592 /* io_lock, not taken: function must be called from Session::process() calltree */
2594 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2595 _session.engine().update_total_latency (*i);
2598 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2599 _session.engine().update_total_latency (*i);
2605 * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
2609 IO::setup_bundles_for_inputs_and_outputs ()
2611 setup_bundle_for_inputs ();
2612 setup_bundle_for_outputs ();
2617 IO::setup_bundle_for_inputs ()
2621 if (!_bundle_for_inputs) {
2622 _bundle_for_inputs.reset (new Bundle (true));
2625 _bundle_for_inputs->suspend_signals ();
2627 _bundle_for_inputs->remove_channels ();
2629 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2630 _bundle_for_inputs->set_name (buf);
2631 uint32_t const ni = inputs().num_ports();
2632 for (uint32_t i = 0; i < ni; ++i) {
2633 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2634 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2637 _bundle_for_inputs->resume_signals ();
2642 IO::setup_bundle_for_outputs ()
2646 if (!_bundle_for_outputs) {
2647 _bundle_for_outputs.reset (new Bundle (false));
2650 _bundle_for_outputs->suspend_signals ();
2652 _bundle_for_outputs->remove_channels ();
2654 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2655 _bundle_for_outputs->set_name (buf);
2656 uint32_t const no = outputs().num_ports();
2657 for (uint32_t i = 0; i < no; ++i) {
2658 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2659 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2662 _bundle_for_outputs->resume_signals ();
2666 /** @return Bundles connected to our inputs */
2668 IO::bundles_connected_to_inputs ()
2673 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2674 bundles.push_back (i->bundle);
2677 /* Normal bundles */
2678 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2679 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2680 if ((*i)->ports_are_outputs() == false || (*i)->nchannels() != n_inputs().n_total()) {
2684 for (uint32_t j = 0; j < n_inputs().n_total(); ++j) {
2686 Bundle::PortList const& pl = (*i)->channel_ports (j);
2687 if (!pl.empty() && input(j)->connected_to (pl[0])) {
2688 bundles.push_back (*i);
2698 /* @return Bundles connected to our outputs */
2700 IO::bundles_connected_to_outputs ()
2705 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2706 bundles.push_back (i->bundle);
2710 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2711 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2712 if ((*i)->ports_are_inputs() == false || (*i)->nchannels() != n_outputs().n_total()) {
2716 for (uint32_t j = 0; j < n_outputs().n_total(); ++j) {
2718 Bundle::PortList const& pl = (*i)->channel_ports (j);
2720 if (!pl.empty() && output(j)->connected_to (pl[0])) {
2721 bundles.push_back (*i);
2730 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2733 changed = b->Changed.connect (
2734 sigc::mem_fun (*io, &IO::bundle_changed)
2739 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2741 /* io_lock, not taken: function must be called from Session::process() calltree */
2745 IO::flush_outputs (nframes_t nframes, nframes_t offset)
2747 /* io_lock, not taken: function must be called from Session::process() calltree */
2748 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2750 /* Only run cycle_start() on output ports, because
2751 inputs must be done in the correct processing order,
2752 which requires interleaving with route processing.
2755 (*i).flush_buffers (nframes, 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));