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>(
144 new GainControl(X_("gaincontrol"), *this, gl));
146 add_control(_gain_control);
148 apply_gain_automation = false;
151 // IO::Meter is emitted from another thread so the
152 // Meter signal must be protected.
153 Glib::Mutex::Lock guard (m_meter_signal_lock);
154 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
157 // Connect to our own PortCountChanged signal to connect output buffers
158 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
160 _session.add_controllable (_gain_control);
162 create_bundles_for_inputs_and_outputs ();
165 IO::IO (Session& s, const XMLNode& node, DataType dt)
166 : SessionObject(s, "unnamed io"),
167 AutomatableControls (s),
168 _output_buffers (new BufferSet()),
172 _meter = new PeakMeter (_session);
173 _public_ports = true; // XXX get this from node
176 no_panner_reset = false;
180 apply_gain_automation = false;
182 boost::shared_ptr<AutomationList> gl(
183 new AutomationList(Evoral::Parameter(GainAutomation)));
185 _gain_control = boost::shared_ptr<GainControl>(
186 new GainControl(X_("gaincontrol"), *this, gl));
188 add_control(_gain_control);
193 // IO::Meter is emitted from another thread so the
194 // Meter signal must be protected.
195 Glib::Mutex::Lock guard (m_meter_signal_lock);
196 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
199 // Connect to our own PortCountChanged signal to connect output buffers
200 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
202 _session.add_controllable (_gain_control);
204 create_bundles_for_inputs_and_outputs ();
209 Glib::Mutex::Lock guard (m_meter_signal_lock);
210 Glib::Mutex::Lock lm (io_lock);
212 BLOCK_PROCESS_CALLBACK ();
214 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
215 _session.engine().unregister_port (*i);
218 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
219 _session.engine().unregister_port (*i);
222 m_meter_connection.disconnect();
226 delete _output_buffers;
230 IO::silence (nframes_t nframes, nframes_t offset)
232 /* io_lock, not taken: function must be called from Session::process() calltree */
234 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
235 i->get_buffer().silence (nframes, offset);
239 /** Deliver bufs to the IO's output ports
241 * This function should automatically do whatever it necessary to correctly deliver bufs
242 * to the outputs, eg applying gain or pan or whatever else needs to be done.
245 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
247 // FIXME: type specific code doesn't actually need to be here, it will go away in time
249 /* ********** AUDIO ********** */
251 // Apply gain if gain automation isn't playing
252 if ( ! apply_gain_automation) {
254 gain_t dg = _gain; // desired gain
257 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
265 if (dg != _gain || dg != 1.0)
266 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
269 // Use the panner to distribute audio to output port buffers
270 if (_panner && !_panner->empty() && !_panner->bypassed()) {
271 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
273 const DataType type = DataType::AUDIO;
275 // Copy any audio 1:1 to outputs
277 BufferSet::iterator o = output_buffers().begin(type);
278 BufferSet::iterator i = bufs.begin(type);
279 BufferSet::iterator prev = i;
281 while (i != bufs.end(type) && o != output_buffers().end (type)) {
282 o->read_from(*i, nframes, offset);
288 /* extra outputs get a copy of the last buffer */
290 while (o != output_buffers().end(type)) {
291 o->read_from(*prev, nframes, offset);
296 /* ********** MIDI ********** */
298 // No MIDI, we're done here
299 if (bufs.count().n_midi() == 0) {
303 const DataType type = DataType::MIDI;
305 // Copy any MIDI 1:1 to outputs
306 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
307 BufferSet::iterator o = output_buffers().begin(type);
308 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
309 o->read_from(*i, nframes, offset);
314 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
316 assert(outs.available() >= n_inputs());
318 if (n_inputs() == ChanCount::ZERO)
321 outs.set_count(n_inputs());
323 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
325 BufferSet::iterator o = outs.begin(*t);
326 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
327 (*i).cycle_start (nframes, offset);
328 o->read_from(i->get_buffer(), nframes, offset);
335 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
336 nframes_t nframes, nframes_t offset)
338 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
340 collect_input (bufs, nframes, offset);
342 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
347 IO::check_bundles_connected_to_inputs ()
349 check_bundles (_bundles_connected_to_inputs, inputs());
353 IO::check_bundles_connected_to_outputs ()
355 check_bundles (_bundles_connected_to_outputs, outputs());
359 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
361 std::vector<UserBundleInfo> new_list;
363 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
365 ChanCount const N = i->bundle->nchannels ();
367 if (ports.num_ports (default_type()) < N.get (default_type())) {
372 uint32_t n = N.get (default_type());
374 for (uint32_t j = 0; j < n; ++j) {
375 /* Every port on bundle channel j must be connected to our input j */
376 PortList const pl = i->bundle->channel_ports (j);
377 for (uint32_t k = 0; k < pl.size(); ++k) {
378 if (ports.port(j)->connected_to (pl[k]) == false) {
390 new_list.push_back (*i);
392 i->configuration_will_change.disconnect ();
393 i->configuration_has_changed.disconnect ();
394 i->ports_will_change.disconnect ();
395 i->ports_have_changed.disconnect ();
404 IO::disconnect_input (Port* our_port, string other_port, void* src)
406 if (other_port.length() == 0 || our_port == 0) {
411 BLOCK_PROCESS_CALLBACK ();
414 Glib::Mutex::Lock lm (io_lock);
416 /* check that our_port is really one of ours */
418 if ( ! _inputs.contains(our_port)) {
422 /* disconnect it from the source */
424 if (_session.engine().disconnect (other_port, our_port->name())) {
425 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
429 check_bundles_connected_to_inputs ();
433 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
434 _session.set_dirty ();
440 IO::connect_input (Port* our_port, string other_port, void* src)
442 if (other_port.length() == 0 || our_port == 0) {
447 BLOCK_PROCESS_CALLBACK ();
450 Glib::Mutex::Lock lm (io_lock);
452 /* check that our_port is really one of ours */
454 if ( ! _inputs.contains(our_port) ) {
458 /* connect it to the source */
460 if (_session.engine().connect (other_port, our_port->name())) {
466 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
467 _session.set_dirty ();
472 IO::disconnect_output (Port* our_port, string other_port, void* src)
474 if (other_port.length() == 0 || our_port == 0) {
479 BLOCK_PROCESS_CALLBACK ();
482 Glib::Mutex::Lock lm (io_lock);
484 /* check that our_port is really one of ours */
486 if ( ! _outputs.contains(our_port) ) {
490 /* disconnect it from the destination */
492 if (_session.engine().disconnect (our_port->name(), other_port)) {
493 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
497 check_bundles_connected_to_outputs ();
501 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
502 _session.set_dirty ();
507 IO::connect_output (Port* our_port, string other_port, void* src)
509 if (other_port.length() == 0 || our_port == 0) {
514 BLOCK_PROCESS_CALLBACK ();
518 Glib::Mutex::Lock lm (io_lock);
520 /* check that our_port is really one of ours */
522 if ( ! _outputs.contains(our_port) ) {
526 /* connect it to the destination */
528 if (_session.engine().connect (our_port->name(), other_port)) {
534 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
535 _session.set_dirty ();
540 IO::set_input (Port* other_port, void* src)
542 /* this removes all but one ports, and connects that one port
543 to the specified source.
546 if (_input_minimum.n_total() > 1) {
547 /* sorry, you can't do this */
551 if (other_port == 0) {
552 if (_input_minimum == ChanCount::ZERO) {
553 return ensure_inputs (ChanCount::ZERO, false, true, src);
559 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
563 return connect_input (_inputs.port(0), other_port->name(), src);
567 IO::remove_output_port (Port* port, void* src)
569 IOChange change (NoChange);
572 BLOCK_PROCESS_CALLBACK ();
576 Glib::Mutex::Lock lm (io_lock);
578 if (n_outputs() <= _output_minimum) {
579 /* sorry, you can't do this */
583 if (_outputs.remove(port)) {
584 change = IOChange (change|ConfigurationChanged);
586 if (port->connected()) {
587 change = IOChange (change|ConnectionsChanged);
590 _session.engine().unregister_port (*port);
591 check_bundles_connected_to_outputs ();
593 setup_peak_meters ();
598 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
601 if (change == ConnectionsChanged) {
602 setup_bundles_for_inputs_and_outputs ();
605 if (change != NoChange) {
606 output_changed (change, src);
607 _session.set_dirty ();
614 /** Add an output port.
616 * @param destination Name of input port to connect new port to.
617 * @param src Source for emitted ConfigurationChanged signal.
618 * @param type Data type of port. Default value (NIL) will use this IO's default type.
621 IO::add_output_port (string destination, void* src, DataType type)
625 if (type == DataType::NIL)
626 type = _default_type;
629 BLOCK_PROCESS_CALLBACK ();
633 Glib::Mutex::Lock lm (io_lock);
635 if (n_outputs() >= _output_maximum) {
639 /* Create a new output port */
641 string portname = build_legal_port_name (type, false);
643 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
644 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
648 _outputs.add (our_port);
649 setup_peak_meters ();
653 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
656 if (destination.length()) {
657 if (_session.engine().connect (our_port->name(), destination)) {
662 // pan_changed (src); /* EMIT SIGNAL */
663 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
664 setup_bundles_for_inputs_and_outputs ();
665 _session.set_dirty ();
671 IO::remove_input_port (Port* port, void* src)
673 IOChange change (NoChange);
676 BLOCK_PROCESS_CALLBACK ();
680 Glib::Mutex::Lock lm (io_lock);
682 if (n_inputs() <= _input_minimum) {
683 /* sorry, you can't do this */
687 if (_inputs.remove(port)) {
688 change = IOChange (change|ConfigurationChanged);
690 if (port->connected()) {
691 change = IOChange (change|ConnectionsChanged);
694 _session.engine().unregister_port (*port);
695 check_bundles_connected_to_inputs ();
697 setup_peak_meters ();
702 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
705 if (change == ConfigurationChanged) {
706 setup_bundles_for_inputs_and_outputs ();
709 if (change != NoChange) {
710 input_changed (change, src);
711 _session.set_dirty ();
719 /** Add an input port.
721 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
722 * @param destination Name of input port to connect new port to.
723 * @param src Source for emitted ConfigurationChanged signal.
726 IO::add_input_port (string source, void* src, DataType type)
730 if (type == DataType::NIL)
731 type = _default_type;
734 BLOCK_PROCESS_CALLBACK ();
737 Glib::Mutex::Lock lm (io_lock);
739 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
743 /* Create a new input port */
745 string portname = build_legal_port_name (type, true);
747 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
748 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
752 _inputs.add (our_port);
753 setup_peak_meters ();
757 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
760 if (source.length()) {
762 if (_session.engine().connect (source, our_port->name())) {
767 // pan_changed (src); /* EMIT SIGNAL */
768 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
769 setup_bundles_for_inputs_and_outputs ();
770 _session.set_dirty ();
776 IO::disconnect_inputs (void* src)
779 BLOCK_PROCESS_CALLBACK ();
782 Glib::Mutex::Lock lm (io_lock);
784 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
785 _session.engine().disconnect (*i);
788 check_bundles_connected_to_inputs ();
792 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
798 IO::disconnect_outputs (void* src)
801 BLOCK_PROCESS_CALLBACK ();
804 Glib::Mutex::Lock lm (io_lock);
806 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
807 _session.engine().disconnect (*i);
810 check_bundles_connected_to_outputs ();
814 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
815 _session.set_dirty ();
821 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
823 Port* input_port = 0;
824 bool changed = false;
827 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
829 const size_t n = count.get(*t);
831 /* remove unused ports */
832 for (size_t i = n_inputs().get(*t); i > n; --i) {
833 input_port = _inputs.port(*t, i-1);
836 _inputs.remove(input_port);
837 _session.engine().unregister_port (*input_port);
842 /* create any necessary new ports */
843 while (n_inputs().get(*t) < n) {
845 string portname = build_legal_port_name (*t, true);
849 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
850 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
855 catch (AudioEngine::PortRegistrationFailure& err) {
856 setup_peak_meters ();
859 throw AudioEngine::PortRegistrationFailure();
862 _inputs.add (input_port);
868 check_bundles_connected_to_inputs ();
869 setup_peak_meters ();
871 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
872 _session.set_dirty ();
876 /* disconnect all existing ports so that we get a fresh start */
877 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
878 _session.engine().disconnect (*i);
885 /** Attach output_buffers to port buffers.
887 * Connected to IO's own PortCountChanged signal.
890 IO::attach_buffers(ChanCount ignored)
892 _output_buffers->attach_buffers(_outputs);
896 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
898 bool in_changed = false;
899 bool out_changed = false;
900 bool need_pan_reset = false;
902 in = min (_input_maximum, in);
904 out = min (_output_maximum, out);
906 if (in == n_inputs() && out == n_outputs() && !clear) {
911 BLOCK_PROCESS_CALLBACK ();
912 Glib::Mutex::Lock lm (io_lock);
916 if (n_outputs() != out) {
917 need_pan_reset = true;
920 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
922 const size_t nin = in.get(*t);
923 const size_t nout = out.get(*t);
925 Port* output_port = 0;
926 Port* input_port = 0;
928 /* remove unused output ports */
929 for (size_t i = n_outputs().get(*t); i > nout; --i) {
930 output_port = _outputs.port(*t, i-1);
933 _outputs.remove(output_port);
934 _session.engine().unregister_port (*output_port);
939 /* remove unused input ports */
940 for (size_t i = n_inputs().get(*t); i > nin; --i) {
941 input_port = _inputs.port(*t, i-1);
944 _inputs.remove(input_port);
945 _session.engine().unregister_port (*input_port);
950 /* create any necessary new input ports */
952 while (n_inputs().get(*t) < nin) {
954 string portname = build_legal_port_name (*t, true);
957 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
958 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
963 catch (AudioEngine::PortRegistrationFailure& err) {
964 setup_peak_meters ();
967 throw AudioEngine::PortRegistrationFailure();
974 /* create any necessary new output ports */
976 while (n_outputs().get(*t) < nout) {
978 string portname = build_legal_port_name (*t, false);
981 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
982 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
987 catch (AudioEngine::PortRegistrationFailure& err) {
988 setup_peak_meters ();
991 throw AudioEngine::PortRegistrationFailure ();
1001 /* disconnect all existing ports so that we get a fresh start */
1003 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1004 _session.engine().disconnect (*i);
1007 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1008 _session.engine().disconnect (*i);
1012 if (in_changed || out_changed) {
1013 setup_peak_meters ();
1019 check_bundles_connected_to_outputs ();
1020 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1024 check_bundles_connected_to_inputs ();
1025 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1028 if (in_changed || out_changed) {
1029 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1030 setup_bundles_for_inputs_and_outputs ();
1031 _session.set_dirty ();
1038 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1040 bool changed = false;
1042 count = min (_input_maximum, count);
1044 if (count == n_inputs() && !clear) {
1049 BLOCK_PROCESS_CALLBACK ();
1050 Glib::Mutex::Lock im (io_lock);
1051 changed = ensure_inputs_locked (count, clear, src);
1053 changed = ensure_inputs_locked (count, clear, src);
1057 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1058 setup_bundles_for_inputs_and_outputs ();
1059 _session.set_dirty ();
1065 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1067 Port* output_port = 0;
1068 bool changed = false;
1069 bool need_pan_reset = false;
1071 if (n_outputs() != count) {
1072 need_pan_reset = true;
1075 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1077 const size_t n = count.get(*t);
1079 /* remove unused ports */
1080 for (size_t i = n_outputs().get(*t); i > n; --i) {
1081 output_port = _outputs.port(*t, i-1);
1083 assert(output_port);
1084 _outputs.remove(output_port);
1085 _session.engine().unregister_port (*output_port);
1090 /* create any necessary new ports */
1091 while (n_outputs().get(*t) < n) {
1093 string portname = build_legal_port_name (*t, false);
1095 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1096 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1100 _outputs.add (output_port);
1102 setup_peak_meters ();
1104 if (need_pan_reset) {
1111 check_bundles_connected_to_outputs ();
1112 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1113 _session.set_dirty ();
1117 /* disconnect all existing ports so that we get a fresh start */
1118 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1119 _session.engine().disconnect (*i);
1127 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1129 bool changed = false;
1131 if (_output_maximum < ChanCount::INFINITE) {
1132 count = min (_output_maximum, count);
1133 if (count == n_outputs() && !clear) {
1138 /* XXX caller should hold io_lock, but generally doesn't */
1141 BLOCK_PROCESS_CALLBACK ();
1142 Glib::Mutex::Lock im (io_lock);
1143 changed = ensure_outputs_locked (count, clear, src);
1145 changed = ensure_outputs_locked (count, clear, src);
1149 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1150 setup_bundles_for_inputs_and_outputs ();
1157 IO::effective_gain () const
1159 if (_gain_control->automation_playback()) {
1160 return _gain_control->get_value();
1162 return _desired_gain;
1169 if (panners_legal) {
1170 if (!no_panner_reset) {
1171 _panner->reset (n_outputs().n_audio(), pans_required());
1174 panner_legal_c.disconnect ();
1175 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1180 IO::panners_became_legal ()
1182 _panner->reset (n_outputs().n_audio(), pans_required());
1183 _panner->load (); // automation
1184 panner_legal_c.disconnect ();
1189 IO::defer_pan_reset ()
1191 no_panner_reset = true;
1195 IO::allow_pan_reset ()
1197 no_panner_reset = false;
1203 IO::get_state (void)
1205 return state (true);
1209 IO::state (bool full_state)
1211 XMLNode* node = new XMLNode (state_node_name);
1214 vector<string>::iterator ci;
1216 LocaleGuard lg (X_("POSIX"));
1217 Glib::Mutex::Lock lm (io_lock);
1219 node->add_property("name", _name);
1220 id().print (buf, sizeof (buf));
1221 node->add_property("id", buf);
1224 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1225 i != _bundles_connected_to_inputs.end();
1229 XMLNode* n = new XMLNode ("InputBundle");
1230 n->add_property ("name", i->bundle->name ());
1231 node->add_child_nocopy (*n);
1235 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1236 i != _bundles_connected_to_outputs.end();
1240 XMLNode* n = new XMLNode ("OutputBundle");
1241 n->add_property ("name", i->bundle->name ());
1242 node->add_child_nocopy (*n);
1247 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1249 vector<string> connections;
1251 if (i->get_connections (connections)) {
1255 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1260 /* if its a connection to our own port,
1261 return only the port name, not the
1262 whole thing. this allows connections
1263 to be re-established even when our
1264 client name is different.
1267 str += _session.engine().make_port_name_relative (*ci);
1277 node->add_property ("inputs", str);
1281 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1283 vector<string> connections;
1285 if (i->get_connections (connections)) {
1289 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1294 str += _session.engine().make_port_name_relative (*ci);
1304 node->add_property ("outputs", str);
1306 node->add_child_nocopy (_panner->state (full_state));
1307 node->add_child_nocopy (_gain_control->get_state ());
1309 snprintf (buf, sizeof(buf), "%2.12f", gain());
1310 node->add_property ("gain", buf);
1312 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1316 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1317 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1319 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1321 node->add_property ("iolimits", buf);
1326 node->add_child_nocopy (get_automation_state());
1332 IO::set_state (const XMLNode& node)
1334 const XMLProperty* prop;
1335 XMLNodeConstIterator iter;
1336 LocaleGuard lg (X_("POSIX"));
1338 /* force use of non-localized representation of decimal point,
1339 since we use it a lot in XML files and so forth.
1342 if (node.name() != state_node_name) {
1343 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1347 if ((prop = node.property ("name")) != 0) {
1348 _name = prop->value();
1349 /* used to set panner name with this, but no more */
1352 if ((prop = node.property ("id")) != 0) {
1353 _id = prop->value ();
1361 if ((prop = node.property ("iolimits")) != 0) {
1362 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1363 &in_min, &in_max, &out_min, &out_max);
1365 /* Correct for the difference between the way we write things to session files and the
1366 way things are described by ChanCount; see comments in io.h about what the different
1367 ChanCount values mean. */
1370 _input_minimum = ChanCount::ZERO;
1372 _input_minimum = ChanCount (_default_type, in_min);
1376 _input_maximum = ChanCount::INFINITE;
1378 _input_maximum = ChanCount (_default_type, in_max);
1382 _output_minimum = ChanCount::ZERO;
1384 _output_minimum = ChanCount (_default_type, out_min);
1388 _output_maximum = ChanCount::INFINITE;
1390 _output_maximum = ChanCount (_default_type, out_max);
1394 if ((prop = node.property ("gain")) != 0) {
1395 set_gain (atof (prop->value().c_str()), this);
1396 _gain = _desired_gain;
1399 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1400 /* old school automation handling */
1403 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1405 if ((*iter)->name() == "Panner") {
1407 _panner = new Panner (_name, _session);
1409 _panner->set_state (**iter);
1412 if ((*iter)->name() == X_("Automation")) {
1414 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1417 if ((*iter)->name() == X_("controllable")) {
1418 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1419 _gain_control->set_state (**iter);
1426 if (create_ports (node)) {
1432 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1435 if (panners_legal) {
1438 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1441 if (connecting_legal) {
1443 if (make_connections (node)) {
1449 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1452 if (!ports_legal || !connecting_legal) {
1453 pending_state_node = new XMLNode (node);
1460 IO::load_automation (string path)
1465 uint32_t linecnt = 0;
1467 LocaleGuard lg (X_("POSIX"));
1469 fullpath = Glib::build_filename(_session.automation_dir(), path);
1471 in.open (fullpath.c_str());
1474 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1476 in.open (fullpath.c_str());
1479 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1484 clear_automation ();
1486 while (in.getline (line, sizeof(line), '\n')) {
1491 if (++linecnt == 1) {
1492 if (memcmp (line, "version", 7) == 0) {
1493 if (sscanf (line, "version %f", &version) != 1) {
1494 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1498 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1505 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1506 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1512 _gain_control->list()->fast_simple_add (when, value);
1522 /* older (pre-1.0) versions of ardour used this */
1526 warning << _("dubious automation event found (and ignored)") << endmsg;
1534 IO::connecting_became_legal ()
1538 if (pending_state_node == 0) {
1539 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1544 connection_legal_c.disconnect ();
1546 ret = make_connections (*pending_state_node);
1549 delete pending_state_node;
1550 pending_state_node = 0;
1556 IO::ports_became_legal ()
1560 if (pending_state_node == 0) {
1561 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1566 port_legal_c.disconnect ();
1568 ret = create_ports (*pending_state_node);
1570 if (connecting_legal) {
1571 delete pending_state_node;
1572 pending_state_node = 0;
1578 boost::shared_ptr<Bundle>
1579 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1581 static const string digits = "0123456789";
1583 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1586 int bundle_number, mask;
1587 string possible_name;
1588 bool stereo = false;
1589 string::size_type last_non_digit_pos;
1591 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1594 // find numeric suffix of desired name
1597 last_non_digit_pos = desired_name.find_last_not_of(digits);
1599 if (last_non_digit_pos != string::npos) {
1601 s << desired_name.substr(last_non_digit_pos);
1605 // see if it's a stereo connection e.g. "in 3+4"
1607 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1608 int left_bundle_number = 0;
1609 string::size_type left_last_non_digit_pos;
1611 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1613 if (left_last_non_digit_pos != string::npos) {
1615 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1616 s >> left_bundle_number;
1618 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1629 // find highest set bit
1631 while ((mask <= bundle_number) && (mask <<= 1));
1633 // "wrap" bundle number into largest possible power of 2
1638 if (bundle_number & mask) {
1639 bundle_number &= ~mask;
1642 s << default_name << " " << bundle_number + 1;
1645 s << "+" << bundle_number + 2;
1648 possible_name = s.str();
1650 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1657 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1660 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1671 IO::create_ports (const XMLNode& node)
1673 XMLProperty const * prop;
1674 ChanCount num_inputs;
1675 ChanCount num_outputs;
1677 if ((prop = node.property ("input-connection")) != 0) {
1679 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1685 num_inputs = c->nchannels();
1687 } else if ((prop = node.property ("inputs")) != 0) {
1689 num_inputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1692 if ((prop = node.property ("output-connection")) != 0) {
1694 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1700 num_outputs = c->nchannels ();
1702 } else if ((prop = node.property ("outputs")) != 0) {
1704 num_outputs.set (default_type(), count (prop->value().begin(), prop->value().end(), '{'));
1707 no_panner_reset = true;
1709 if (ensure_io (num_inputs, num_outputs, true, this)) {
1710 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1714 no_panner_reset = false;
1716 set_deferred_state ();
1724 IO::make_connections (const XMLNode& node)
1727 const XMLProperty* prop;
1729 if ((prop = node.property ("input-connection")) != 0) {
1730 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1736 connect_input_ports_to_bundle (c, this);
1738 } else if ((prop = node.property ("inputs")) != 0) {
1739 if (set_inputs (prop->value())) {
1740 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1745 if ((prop = node.property ("output-connection")) != 0) {
1746 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1752 connect_output_ports_to_bundle (c, this);
1754 } else if ((prop = node.property ("outputs")) != 0) {
1755 if (set_outputs (prop->value())) {
1756 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1761 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1763 if ((*i)->name() == "InputBundle") {
1764 XMLProperty const * prop = (*i)->property ("name");
1766 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1768 connect_input_ports_to_bundle (b, this);
1772 } else if ((*i)->name() == "OutputBundle") {
1773 XMLProperty const * prop = (*i)->property ("name");
1775 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1777 connect_output_ports_to_bundle (b, this);
1787 IO::set_inputs (const string& str)
1789 vector<string> ports;
1794 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1798 // FIXME: audio-only
1799 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1803 string::size_type start, end, ostart;
1810 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1813 if ((end = str.find_first_of ('}', start)) == string::npos) {
1814 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1818 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1819 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1825 for (int x = 0; x < n; ++x) {
1826 connect_input (input (i), ports[x], this);
1838 IO::set_outputs (const string& str)
1840 vector<string> ports;
1845 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1849 // FIXME: audio-only
1850 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1854 string::size_type start, end, ostart;
1861 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1864 if ((end = str.find_first_of ('}', start)) == string::npos) {
1865 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1869 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1870 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1876 for (int x = 0; x < n; ++x) {
1877 connect_output (output (i), ports[x], this);
1889 IO::parse_io_string (const string& str, vector<string>& ports)
1891 string::size_type pos, opos;
1893 if (str.length() == 0) {
1902 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1903 ports.push_back (str.substr (opos, pos - opos));
1907 if (opos < str.length()) {
1908 ports.push_back (str.substr(opos));
1911 return ports.size();
1915 IO::parse_gain_string (const string& str, vector<string>& ports)
1917 string::size_type pos, opos;
1923 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1924 ports.push_back (str.substr (opos, pos - opos));
1928 if (opos < str.length()) {
1929 ports.push_back (str.substr(opos));
1932 return ports.size();
1936 IO::set_name (const string& requested_name)
1938 if (requested_name == _name) {
1944 if ( (rt = dynamic_cast<Route *>(this))) {
1945 name = Route::ensure_track_or_route_name(requested_name, _session);
1947 name = requested_name;
1951 /* replace all colons in the name. i wish we didn't have to do this */
1953 if (replace_all (name, ":", "-")) {
1954 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1957 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1958 string current_name = i->short_name();
1959 current_name.replace (current_name.find (_name), _name.length(), name);
1960 i->set_name (current_name);
1963 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1964 string current_name = i->short_name();
1965 current_name.replace (current_name.find (_name), _name.length(), name);
1966 i->set_name (current_name);
1969 bool const r = SessionObject::set_name(name);
1971 setup_bundles_for_inputs_and_outputs ();
1977 IO::set_input_minimum (ChanCount n)
1983 IO::set_input_maximum (ChanCount n)
1989 IO::set_output_minimum (ChanCount n)
1991 _output_minimum = n;
1995 IO::set_output_maximum (ChanCount n)
1997 _output_maximum = n;
2001 IO::set_port_latency (nframes_t nframes)
2003 Glib::Mutex::Lock lm (io_lock);
2005 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2006 i->set_latency (nframes);
2011 IO::output_latency () const
2013 nframes_t max_latency;
2018 /* io lock not taken - must be protected by other means */
2020 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2021 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2022 max_latency = latency;
2030 IO::input_latency () const
2032 nframes_t max_latency;
2037 /* io lock not taken - must be protected by other means */
2039 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2040 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
2041 max_latency = latency;
2049 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2052 BLOCK_PROCESS_CALLBACK ();
2053 Glib::Mutex::Lock lm2 (io_lock);
2055 /* Connect to the bundle, not worrying about any connections
2056 that are already made. */
2058 ChanCount const channels = c->nchannels ();
2059 uint32_t cnt = channels.get (default_type());
2061 for (uint32_t n = 0; n < cnt; ++n) {
2062 const PortList& pl = c->channel_ports (n);
2064 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2066 if (!_inputs.port(n)->connected_to (*i)) {
2068 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2076 /* If this is a UserBundle, make a note of what we've done */
2078 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2081 /* See if we already know about this one */
2082 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2083 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2087 if (i == _bundles_connected_to_inputs.end()) {
2088 /* We don't, so make a note */
2089 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2094 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2099 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2102 BLOCK_PROCESS_CALLBACK ();
2103 Glib::Mutex::Lock lm2 (io_lock);
2105 /* Connect to the bundle, not worrying about any connections
2106 that are already made. */
2108 ChanCount const channels = c->nchannels ();
2109 uint32_t cnt = channels.get (default_type());
2111 for (uint32_t n = 0; n < cnt; ++n) {
2113 const PortList& pl = c->channel_ports (n);
2115 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2117 if (!_outputs.port(n)->connected_to (*i)) {
2119 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2126 /* If this is a UserBundle, make a note of what we've done */
2128 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2131 /* See if we already know about this one */
2132 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2133 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2137 if (i == _bundles_connected_to_outputs.end()) {
2138 /* We don't, so make a note */
2139 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2144 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2150 IO::disable_connecting ()
2152 connecting_legal = false;
2157 IO::enable_connecting ()
2159 connecting_legal = true;
2160 return ConnectingLegal ();
2164 IO::disable_ports ()
2166 ports_legal = false;
2174 return PortsLegal ();
2178 IO::disable_panners (void)
2180 panners_legal = false;
2185 IO::reset_panners ()
2187 panners_legal = true;
2188 return PannersLegal ();
2192 IO::bundle_configuration_will_change ()
2195 // connect_input_ports_to_bundle (_input_bundle, this);
2199 IO::bundle_configuration_has_changed ()
2202 // connect_input_ports_to_bundle (_input_bundle, this);
2206 IO::bundle_ports_will_change (int ignored)
2209 // connect_output_ports_to_bundle (_output_bundle, this);
2213 IO::bundle_ports_have_changed (int ignored)
2216 // connect_output_ports_to_bundle (_output_bundle, this);
2220 IO::GainControl::set_value (float val)
2222 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2223 if (val > 1.99526231f)
2227 _io.set_gain (val, this);
2229 Changed(); /* EMIT SIGNAL */
2233 IO::GainControl::get_value (void) const
2235 return AutomationControl::get_value();
2239 IO::setup_peak_meters()
2241 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2242 _meter->configure_io (max_streams, max_streams);
2246 Update the peak meters.
2248 The meter signal lock is taken to prevent modification of the
2249 Meter signal while updating the meters, taking the meter signal
2250 lock prior to taking the io_lock ensures that all IO will remain
2251 valid while metering.
2256 Glib::Mutex::Lock guard (m_meter_signal_lock);
2257 Meter(); /* EMIT SIGNAL */
2263 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2265 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2270 IO::clear_automation ()
2272 data().clear (); // clears gain automation
2273 _panner->clear_automation ();
2277 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2279 // XXX: would be nice to get rid of this special hack
2281 if (param.type() == GainAutomation) {
2283 bool changed = false;
2286 Glib::Mutex::Lock lm (control_lock());
2288 boost::shared_ptr<AutomationList> gain_auto
2289 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2291 if (state != gain_auto->automation_state()) {
2293 _last_automation_snapshot = 0;
2294 gain_auto->set_automation_state (state);
2297 // FIXME: shouldn't this use Curve?
2298 set_gain (gain_auto->eval (_session.transport_frame()), this);
2304 _session.set_dirty ();
2308 AutomatableControls::set_parameter_automation_state(param, state);
2313 IO::inc_gain (gain_t factor, void *src)
2315 if (_desired_gain == 0.0f)
2316 set_gain (0.000001f + (0.000001f * factor), src);
2318 set_gain (_desired_gain + (_desired_gain * factor), src);
2322 IO::set_gain (gain_t val, void *src)
2324 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2325 if (val > 1.99526231f)
2328 if (src != _gain_control.get()) {
2329 _gain_control->set_value(val);
2330 // bit twisty, this will come back and call us again
2331 // (this keeps control in sync with reality)
2336 Glib::Mutex::Lock dm (declick_lock);
2337 _desired_gain = val;
2340 if (_session.transport_stopped()) {
2344 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2345 _gain_control->list()->add (_session.transport_frame(), val);
2349 _session.set_dirty();
2353 IO::start_pan_touch (uint32_t which)
2355 if (which < _panner->size()) {
2356 (*_panner)[which]->pan_control()->start_touch();
2361 IO::end_pan_touch (uint32_t which)
2363 if (which < _panner->size()) {
2364 (*_panner)[which]->pan_control()->stop_touch();
2370 IO::automation_snapshot (nframes_t now, bool force)
2372 AutomatableControls::automation_snapshot (now, force);
2374 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2375 _panner->snapshot (now);
2378 _panner->snapshot (now);
2379 _last_automation_snapshot = now;
2383 IO::transport_stopped (nframes_t frame)
2385 _gain_control->list()->reposition_for_rt_add (frame);
2387 if (_gain_control->automation_state() != Off) {
2389 /* the src=0 condition is a special signal to not propagate
2390 automation gain changes into the mix group when locating.
2393 // FIXME: shouldn't this use Curve?
2394 set_gain (_gain_control->list()->eval (frame), 0);
2397 _panner->transport_stopped (frame);
2401 IO::build_legal_port_name (DataType type, bool in)
2403 const int name_size = jack_port_name_size();
2408 if (type == DataType::AUDIO) {
2409 suffix = _("audio");
2410 } else if (type == DataType::MIDI) {
2413 throw unknown_type();
2418 maxports = _input_maximum.get(type);
2420 suffix += _("_out");
2421 maxports = _output_maximum.get(type);
2424 if (maxports == 1) {
2425 // allow space for the slash + the suffix
2426 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2427 char buf[name_size+1];
2428 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2429 return string (buf);
2432 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2434 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2436 char buf1[name_size+1];
2437 char buf2[name_size+1];
2439 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2444 port_number = find_input_port_hole (buf1);
2446 port_number = find_output_port_hole (buf1);
2449 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2451 return string (buf2);
2455 IO::find_input_port_hole (const char* base)
2457 /* CALLER MUST HOLD IO LOCK */
2461 if (_inputs.empty()) {
2465 /* we only allow up to 4 characters for the port number
2468 for (n = 1; n < 9999; ++n) {
2469 char buf[jack_port_name_size()];
2470 PortSet::iterator i = _inputs.begin();
2472 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2474 for ( ; i != _inputs.end(); ++i) {
2475 if (i->short_name() == buf) {
2480 if (i == _inputs.end()) {
2488 IO::find_output_port_hole (const char* base)
2490 /* CALLER MUST HOLD IO LOCK */
2494 if (_outputs.empty()) {
2498 /* we only allow up to 4 characters for the port number
2501 for (n = 1; n < 9999; ++n) {
2502 char buf[jack_port_name_size()];
2503 PortSet::iterator i = _outputs.begin();
2505 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2507 for ( ; i != _outputs.end(); ++i) {
2508 if (i->short_name() == buf) {
2513 if (i == _outputs.end()) {
2522 IO::set_active (bool yn)
2525 active_changed(); /* EMIT SIGNAL */
2530 IO::audio_input(uint32_t n) const
2532 return dynamic_cast<AudioPort*>(input(n));
2536 IO::audio_output(uint32_t n) const
2538 return dynamic_cast<AudioPort*>(output(n));
2542 IO::midi_input(uint32_t n) const
2544 return dynamic_cast<MidiPort*>(input(n));
2548 IO::midi_output(uint32_t n) const
2550 return dynamic_cast<MidiPort*>(output(n));
2554 IO::set_phase_invert (bool yn, void *src)
2556 if (_phase_invert != yn) {
2558 // phase_invert_changed (src); /* EMIT SIGNAL */
2563 IO::set_denormal_protection (bool yn, void *src)
2565 if (_denormal_protection != yn) {
2566 _denormal_protection = yn;
2567 // denormal_protection_changed (src); /* EMIT SIGNAL */
2572 IO::update_port_total_latencies ()
2574 /* io_lock, not taken: function must be called from Session::process() calltree */
2576 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2577 _session.engine().update_total_latency (*i);
2580 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2581 _session.engine().update_total_latency (*i);
2587 * Setup bundles that describe our inputs and outputs.
2591 IO::setup_bundles_for_inputs_and_outputs ()
2595 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2596 _bundle_for_inputs->set_name (buf);
2597 uint32_t const ni = inputs().num_ports();
2598 _bundle_for_inputs->set_channels (ni);
2599 for (uint32_t i = 0; i < ni; ++i) {
2600 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2603 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2604 _bundle_for_outputs->set_name (buf);
2605 uint32_t const no = outputs().num_ports();
2606 _bundle_for_outputs->set_channels (no);
2607 for (uint32_t i = 0; i < no; ++i) {
2608 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2614 * Create and setup bundles that describe our inputs and outputs.
2618 IO::create_bundles_for_inputs_and_outputs ()
2620 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2621 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2622 setup_bundles_for_inputs_and_outputs ();
2625 /** Add a bundle to a list if is connected to our inputs.
2626 * @param b Bundle to check.
2627 * @param bundles List to add to.
2630 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2632 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2634 if (ab == 0 || ab->ports_are_outputs() == false) {
2638 if (ab->nchannels().get (default_type()) != n_inputs().n_total ()) {
2642 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2644 PortList const & pl = b->channel_ports (i);
2650 if (!input(i)->connected_to (pl[0])) {
2655 bundles->push_back (b);
2658 /** @return Bundles connected to our inputs */
2659 std::vector<boost::shared_ptr<Bundle> >
2660 IO::bundles_connected_to_inputs ()
2662 std::vector<boost::shared_ptr<Bundle> > bundles;
2665 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2666 bundles.push_back (i->bundle);
2670 _session.foreach_bundle (
2671 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2678 /** Add a bundle to a list if is connected to our outputs.
2679 * @param b Bundle to check.
2680 * @param bundles List to add to.
2683 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2685 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2686 if (ab == 0 || ab->ports_are_inputs() == false) {
2690 if (ab->nchannels ().get (default_type()) != n_outputs().n_total ()) {
2694 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2696 PortList const & pl = b->channel_ports (i);
2702 if (!output(i)->connected_to (pl[0])) {
2707 bundles->push_back (b);
2711 /* @return Bundles connected to our outputs */
2712 std::vector<boost::shared_ptr<Bundle> >
2713 IO::bundles_connected_to_outputs ()
2715 std::vector<boost::shared_ptr<Bundle> > bundles;
2718 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2719 bundles.push_back (i->bundle);
2723 _session.foreach_bundle (
2724 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2731 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2734 configuration_will_change = b->ConfigurationWillChange.connect (
2735 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2737 configuration_has_changed = b->ConfigurationHasChanged.connect (
2738 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2740 ports_will_change = b->PortsWillChange.connect (
2741 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2743 ports_have_changed = b->PortsHaveChanged.connect (
2744 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)
2749 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2751 /* io_lock, not taken: function must be called from Session::process() calltree */
2753 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2754 (*i).cycle_start (nframes, offset);