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)
106 : SessionObject(s, name),
107 AutomatableControls (s),
108 _output_buffers (new BufferSet()),
110 _default_type (default_type),
111 _input_minimum (ChanCount::ZERO),
112 _input_maximum (ChanCount::INFINITE),
113 _output_minimum (ChanCount::ZERO),
114 _output_maximum (ChanCount::INFINITE)
116 _panner = new Panner (name, _session);
117 _meter = new PeakMeter (_session);
120 _input_minimum = ChanCount(_default_type, input_min);
122 if (input_max >= 0) {
123 _input_maximum = ChanCount(_default_type, input_max);
125 if (output_min > 0) {
126 _output_minimum = ChanCount(_default_type, output_min);
128 if (output_max >= 0) {
129 _output_maximum = ChanCount(_default_type, output_max);
134 pending_state_node = 0;
135 no_panner_reset = false;
136 _phase_invert = false;
139 boost::shared_ptr<AutomationList> gl(
140 new AutomationList(Evoral::Parameter(GainAutomation)));
142 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
144 add_control(_gain_control);
146 apply_gain_automation = false;
149 // IO::Meter is emitted from another thread so the
150 // Meter signal must be protected.
151 Glib::Mutex::Lock guard (m_meter_signal_lock);
152 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
155 _session.add_controllable (_gain_control);
157 setup_bundles_for_inputs_and_outputs ();
160 IO::IO (Session& s, const XMLNode& node, DataType dt)
161 : SessionObject(s, "unnamed io"),
162 AutomatableControls (s),
163 _output_buffers (new BufferSet()),
167 _meter = new PeakMeter (_session);
170 no_panner_reset = false;
174 apply_gain_automation = false;
176 boost::shared_ptr<AutomationList> gl(
177 new AutomationList(Evoral::Parameter(GainAutomation)));
179 _gain_control = boost::shared_ptr<GainControl>(
180 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
182 add_control(_gain_control);
187 // IO::Meter is emitted from another thread so the
188 // Meter signal must be protected.
189 Glib::Mutex::Lock guard (m_meter_signal_lock);
190 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
193 _session.add_controllable (_gain_control);
195 setup_bundles_for_inputs_and_outputs ();
200 Glib::Mutex::Lock guard (m_meter_signal_lock);
201 Glib::Mutex::Lock lm (io_lock);
203 BLOCK_PROCESS_CALLBACK ();
205 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
206 _session.engine().unregister_port (*i);
209 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
210 _session.engine().unregister_port (*i);
213 m_meter_connection.disconnect();
220 IO::silence (nframes_t nframes, nframes_t offset)
222 /* io_lock, not taken: function must be called from Session::process() calltree */
224 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
225 i->get_buffer(nframes,offset).silence (nframes, offset);
229 /** Deliver bufs to the IO's output ports
231 * This function should automatically do whatever it necessary to correctly deliver bufs
232 * to the outputs, eg applying gain or pan or whatever else needs to be done.
235 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
237 // FIXME: type specific code doesn't actually need to be here, it will go away in time
239 /* ********** AUDIO ********** */
241 // Apply gain if gain automation isn't playing
242 if ( ! apply_gain_automation) {
244 gain_t dg = _gain; // desired gain
247 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
255 if (dg != _gain || dg != 1.0) {
256 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
261 /* do this so that any processing that comes after deliver_outputs()
262 can use the output buffers.
265 output_buffers().attach_buffers (_outputs, nframes, offset);
267 // Use the panner to distribute audio to output port buffers
269 if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
271 /* blech .. we shouldn't be creating and tearing this down every process()
272 cycle. XXX fix me to not waste cycles and do memory allocation etc.
275 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
279 /* do a 1:1 copy of data to output ports */
281 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
282 copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
284 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
285 copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
291 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
293 // Copy any buffers 1:1 to outputs
295 PortSet::iterator o = _outputs.begin(type);
296 BufferSet::iterator i = bufs.begin(type);
297 BufferSet::iterator prev = i;
299 while (i != bufs.end(type) && o != _outputs.end (type)) {
301 Buffer& port_buffer (o->get_buffer (nframes, offset));
302 port_buffer.read_from (*i, nframes, offset);
309 /* extra outputs get a copy of the last buffer */
311 while (o != _outputs.end(type)) {
312 Buffer& port_buffer (o->get_buffer (nframes, offset));
313 port_buffer.read_from(*prev, nframes, offset);
319 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
321 assert(outs.available() >= n_inputs());
323 if (n_inputs() == ChanCount::ZERO)
326 outs.set_count(n_inputs());
328 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
330 BufferSet::iterator o = outs.begin(*t);
331 PortSet::iterator e = _inputs.end (*t);
332 for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
333 Buffer& b (i->get_buffer (nframes,offset));
334 o->read_from (b, nframes, offset);
341 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
342 nframes_t nframes, nframes_t offset)
344 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
346 collect_input (bufs, nframes, offset);
348 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
353 IO::check_bundles_connected_to_inputs ()
355 check_bundles (_bundles_connected_to_inputs, inputs());
359 IO::check_bundles_connected_to_outputs ()
361 check_bundles (_bundles_connected_to_outputs, outputs());
365 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
367 std::vector<UserBundleInfo> new_list;
369 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
371 uint32_t const N = i->bundle->nchannels ();
373 if (ports.num_ports (default_type()) < N) {
379 for (uint32_t j = 0; j < N; ++j) {
380 /* Every port on bundle channel j must be connected to our input j */
381 Bundle::PortList const pl = i->bundle->channel_ports (j);
382 for (uint32_t k = 0; k < pl.size(); ++k) {
383 if (ports.port(j)->connected_to (pl[k]) == false) {
395 new_list.push_back (*i);
397 i->changed.disconnect ();
406 IO::disconnect_input (Port* our_port, string other_port, void* src)
408 if (other_port.length() == 0 || our_port == 0) {
413 BLOCK_PROCESS_CALLBACK ();
416 Glib::Mutex::Lock lm (io_lock);
418 /* check that our_port is really one of ours */
420 if ( ! _inputs.contains(our_port)) {
424 /* disconnect it from the source */
426 if (our_port->disconnect (other_port)) {
427 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
431 check_bundles_connected_to_inputs ();
435 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
436 _session.set_dirty ();
442 IO::connect_input (Port* our_port, string other_port, void* src)
444 if (other_port.length() == 0 || our_port == 0) {
449 BLOCK_PROCESS_CALLBACK ();
452 Glib::Mutex::Lock lm (io_lock);
454 /* check that our_port is really one of ours */
456 if ( ! _inputs.contains(our_port) ) {
460 /* connect it to the source */
462 if (our_port->connect (other_port)) {
468 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
469 _session.set_dirty ();
474 IO::disconnect_output (Port* our_port, string other_port, void* src)
476 if (other_port.length() == 0 || our_port == 0) {
481 BLOCK_PROCESS_CALLBACK ();
484 Glib::Mutex::Lock lm (io_lock);
486 /* check that our_port is really one of ours */
488 if ( ! _outputs.contains(our_port) ) {
492 /* disconnect it from the destination */
494 if (our_port->disconnect (other_port)) {
495 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
499 check_bundles_connected_to_outputs ();
503 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
504 _session.set_dirty ();
509 IO::connect_output (Port* our_port, string other_port, void* src)
511 if (other_port.length() == 0 || our_port == 0) {
516 BLOCK_PROCESS_CALLBACK ();
520 Glib::Mutex::Lock lm (io_lock);
522 /* check that our_port is really one of ours */
524 if ( ! _outputs.contains(our_port) ) {
528 /* connect it to the destination */
530 if (our_port->connect (other_port)) {
536 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
537 _session.set_dirty ();
542 IO::set_input (Port* other_port, void* src)
544 /* this removes all but one ports, and connects that one port
545 to the specified source.
548 if (_input_minimum.n_total() > 1) {
549 /* sorry, you can't do this */
553 if (other_port == 0) {
554 if (_input_minimum == ChanCount::ZERO) {
555 return ensure_inputs (ChanCount::ZERO, false, true, src);
561 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
565 return connect_input (_inputs.port(0), other_port->name(), src);
569 IO::remove_output_port (Port* port, void* src)
571 IOChange change (NoChange);
574 BLOCK_PROCESS_CALLBACK ();
578 Glib::Mutex::Lock lm (io_lock);
580 if (n_outputs() <= _output_minimum) {
581 /* sorry, you can't do this */
585 if (_outputs.remove(port)) {
586 change = IOChange (change|ConfigurationChanged);
588 if (port->connected()) {
589 change = IOChange (change|ConnectionsChanged);
592 _session.engine().unregister_port (*port);
593 check_bundles_connected_to_outputs ();
595 setup_peak_meters ();
600 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
603 if (change == ConfigurationChanged) {
604 setup_bundle_for_outputs ();
607 if (change != NoChange) {
608 output_changed (change, src);
609 _session.set_dirty ();
616 /** Add an output port.
618 * @param destination Name of input port to connect new port to.
619 * @param src Source for emitted ConfigurationChanged signal.
620 * @param type Data type of port. Default value (NIL) will use this IO's default type.
623 IO::add_output_port (string destination, void* src, DataType type)
627 if (type == DataType::NIL)
628 type = _default_type;
631 BLOCK_PROCESS_CALLBACK ();
635 Glib::Mutex::Lock lm (io_lock);
637 if (n_outputs() >= _output_maximum) {
641 /* Create a new output port */
643 string portname = build_legal_port_name (type, false);
645 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
646 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
650 _outputs.add (our_port);
651 setup_peak_meters ();
655 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
658 if (destination.length()) {
659 if (our_port->connect (destination)) {
664 // pan_changed (src); /* EMIT SIGNAL */
665 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
666 setup_bundle_for_outputs ();
667 _session.set_dirty ();
673 IO::remove_input_port (Port* port, void* src)
675 IOChange change (NoChange);
678 BLOCK_PROCESS_CALLBACK ();
682 Glib::Mutex::Lock lm (io_lock);
684 if (n_inputs() <= _input_minimum) {
685 /* sorry, you can't do this */
689 if (_inputs.remove(port)) {
690 change = IOChange (change|ConfigurationChanged);
692 if (port->connected()) {
693 change = IOChange (change|ConnectionsChanged);
696 _session.engine().unregister_port (*port);
697 check_bundles_connected_to_inputs ();
699 setup_peak_meters ();
704 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
707 if (change == ConfigurationChanged) {
708 setup_bundle_for_inputs ();
711 if (change != NoChange) {
712 input_changed (change, src);
713 _session.set_dirty ();
721 /** Add an input port.
723 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
724 * @param destination Name of input port to connect new port to.
725 * @param src Source for emitted ConfigurationChanged signal.
728 IO::add_input_port (string source, void* src, DataType type)
732 if (type == DataType::NIL)
733 type = _default_type;
736 BLOCK_PROCESS_CALLBACK ();
739 Glib::Mutex::Lock lm (io_lock);
741 if (n_inputs().get (type) >= _input_maximum.get (type)) {
745 /* Create a new input port */
747 string portname = build_legal_port_name (type, true);
749 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
750 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
754 _inputs.add (our_port);
755 setup_peak_meters ();
759 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
762 if (source.length()) {
764 if (our_port->connect (source)) {
769 // pan_changed (src); /* EMIT SIGNAL */
770 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
771 setup_bundle_for_inputs ();
772 _session.set_dirty ();
778 IO::disconnect_inputs (void* src)
781 BLOCK_PROCESS_CALLBACK ();
784 Glib::Mutex::Lock lm (io_lock);
786 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
787 i->disconnect_all ();
790 check_bundles_connected_to_inputs ();
794 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
800 IO::disconnect_outputs (void* src)
803 BLOCK_PROCESS_CALLBACK ();
806 Glib::Mutex::Lock lm (io_lock);
808 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
809 i->disconnect_all ();
812 check_bundles_connected_to_outputs ();
816 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
817 _session.set_dirty ();
823 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
825 Port* input_port = 0;
826 bool changed = false;
829 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
831 const size_t n = count.get(*t);
833 /* remove unused ports */
834 for (size_t i = n_inputs().get(*t); i > n; --i) {
835 input_port = _inputs.port(*t, i-1);
838 _inputs.remove(input_port);
839 _session.engine().unregister_port (*input_port);
844 /* create any necessary new ports */
845 while (n_inputs().get(*t) < n) {
847 string portname = build_legal_port_name (*t, true);
851 if ((input_port = _session.engine().register_input_port (*t, portname)) == 0) {
852 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
857 catch (AudioEngine::PortRegistrationFailure& err) {
858 setup_peak_meters ();
861 throw AudioEngine::PortRegistrationFailure();
864 _inputs.add (input_port);
870 check_bundles_connected_to_inputs ();
871 setup_peak_meters ();
873 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
874 _session.set_dirty ();
878 /* disconnect all existing ports so that we get a fresh start */
879 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
880 i->disconnect_all ();
888 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
890 bool in_changed = false;
891 bool out_changed = false;
892 bool need_pan_reset = false;
894 in = min (_input_maximum, in);
896 out = min (_output_maximum, out);
898 if (in == n_inputs() && out == n_outputs() && !clear) {
903 BLOCK_PROCESS_CALLBACK ();
904 Glib::Mutex::Lock lm (io_lock);
908 if (n_outputs() != out) {
909 need_pan_reset = true;
912 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
914 const size_t nin = in.get(*t);
915 const size_t nout = out.get(*t);
917 Port* output_port = 0;
918 Port* input_port = 0;
920 /* remove unused output ports */
921 for (size_t i = n_outputs().get(*t); i > nout; --i) {
922 output_port = _outputs.port(*t, i-1);
925 _outputs.remove(output_port);
926 _session.engine().unregister_port (*output_port);
931 /* remove unused input ports */
932 for (size_t i = n_inputs().get(*t); i > nin; --i) {
933 input_port = _inputs.port(*t, i-1);
936 _inputs.remove(input_port);
937 _session.engine().unregister_port (*input_port);
942 /* create any necessary new input ports */
944 while (n_inputs().get(*t) < nin) {
946 string portname = build_legal_port_name (*t, true);
949 if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
950 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
955 catch (AudioEngine::PortRegistrationFailure& err) {
956 setup_peak_meters ();
959 throw AudioEngine::PortRegistrationFailure();
966 /* create any necessary new output ports */
968 while (n_outputs().get(*t) < nout) {
970 string portname = build_legal_port_name (*t, false);
973 if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
974 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
979 catch (AudioEngine::PortRegistrationFailure& err) {
980 setup_peak_meters ();
983 throw AudioEngine::PortRegistrationFailure ();
993 /* disconnect all existing ports so that we get a fresh start */
995 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
996 i->disconnect_all ();
999 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1000 i->disconnect_all ();
1004 if (in_changed || out_changed) {
1005 setup_peak_meters ();
1011 check_bundles_connected_to_outputs ();
1012 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1013 setup_bundle_for_outputs ();
1017 check_bundles_connected_to_inputs ();
1018 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1019 setup_bundle_for_inputs ();
1022 if (in_changed || out_changed) {
1023 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1024 _session.set_dirty ();
1031 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1033 bool changed = false;
1035 count = min (_input_maximum, count);
1037 if (count == n_inputs() && !clear) {
1042 BLOCK_PROCESS_CALLBACK ();
1043 Glib::Mutex::Lock im (io_lock);
1044 changed = ensure_inputs_locked (count, clear, src);
1046 changed = ensure_inputs_locked (count, clear, src);
1050 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1051 setup_bundle_for_inputs ();
1052 _session.set_dirty ();
1058 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1060 Port* output_port = 0;
1061 bool changed = false;
1062 bool need_pan_reset = false;
1064 if (n_outputs() != count) {
1065 need_pan_reset = true;
1068 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1070 const size_t n = count.get(*t);
1072 /* remove unused ports */
1073 for (size_t i = n_outputs().get(*t); i > n; --i) {
1074 output_port = _outputs.port(*t, i-1);
1076 assert(output_port);
1077 _outputs.remove(output_port);
1078 _session.engine().unregister_port (*output_port);
1083 /* create any necessary new ports */
1084 while (n_outputs().get(*t) < n) {
1086 string portname = build_legal_port_name (*t, false);
1088 if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
1089 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1093 _outputs.add (output_port);
1095 setup_peak_meters ();
1097 if (need_pan_reset) {
1104 check_bundles_connected_to_outputs ();
1105 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1106 _session.set_dirty ();
1110 /* disconnect all existing ports so that we get a fresh start */
1111 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1112 i->disconnect_all ();
1120 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1122 bool changed = false;
1124 if (_output_maximum < ChanCount::INFINITE) {
1125 count = min (_output_maximum, count);
1126 if (count == n_outputs() && !clear) {
1131 /* XXX caller should hold io_lock, but generally doesn't */
1134 BLOCK_PROCESS_CALLBACK ();
1135 Glib::Mutex::Lock im (io_lock);
1136 changed = ensure_outputs_locked (count, clear, src);
1138 changed = ensure_outputs_locked (count, clear, src);
1142 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1143 setup_bundle_for_outputs ();
1150 IO::effective_gain () const
1152 if (_gain_control->automation_playback()) {
1153 return _gain_control->get_value();
1155 return _desired_gain;
1162 if (panners_legal) {
1163 if (!no_panner_reset) {
1164 _panner->reset (n_outputs().n_audio(), pans_required());
1167 panner_legal_c.disconnect ();
1168 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1173 IO::panners_became_legal ()
1175 _panner->reset (n_outputs().n_audio(), pans_required());
1176 _panner->load (); // automation
1177 panner_legal_c.disconnect ();
1182 IO::defer_pan_reset ()
1184 no_panner_reset = true;
1188 IO::allow_pan_reset ()
1190 no_panner_reset = false;
1196 IO::get_state (void)
1198 return state (true);
1202 IO::state (bool full_state)
1204 XMLNode* node = new XMLNode (state_node_name);
1207 vector<string>::iterator ci;
1209 LocaleGuard lg (X_("POSIX"));
1210 Glib::Mutex::Lock lm (io_lock);
1212 node->add_property("name", _name);
1213 id().print (buf, sizeof (buf));
1214 node->add_property("id", buf);
1217 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1218 i != _bundles_connected_to_inputs.end();
1222 XMLNode* n = new XMLNode ("InputBundle");
1223 n->add_property ("name", i->bundle->name ());
1224 node->add_child_nocopy (*n);
1228 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1229 i != _bundles_connected_to_outputs.end();
1233 XMLNode* n = new XMLNode ("OutputBundle");
1234 n->add_property ("name", i->bundle->name ());
1235 node->add_child_nocopy (*n);
1240 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1242 vector<string> connections;
1244 if (i->get_connections (connections)) {
1248 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1253 /* if its a connection to our own port,
1254 return only the port name, not the
1255 whole thing. this allows connections
1256 to be re-established even when our
1257 client name is different.
1260 str += _session.engine().make_port_name_relative (*ci);
1270 node->add_property ("inputs", str);
1274 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1276 vector<string> connections;
1278 if (i->get_connections (connections)) {
1282 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1287 str += _session.engine().make_port_name_relative (*ci);
1297 node->add_property ("outputs", str);
1299 node->add_child_nocopy (_panner->state (full_state));
1300 node->add_child_nocopy (_gain_control->get_state ());
1302 snprintf (buf, sizeof(buf), "%2.12f", gain());
1303 node->add_property ("gain", buf);
1305 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1309 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1310 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1312 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1314 node->add_property ("iolimits", buf);
1319 node->add_child_nocopy (get_automation_state());
1325 IO::set_state (const XMLNode& node)
1327 const XMLProperty* prop;
1328 XMLNodeConstIterator iter;
1329 LocaleGuard lg (X_("POSIX"));
1331 /* force use of non-localized representation of decimal point,
1332 since we use it a lot in XML files and so forth.
1335 if (node.name() != state_node_name) {
1336 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1340 if ((prop = node.property ("name")) != 0) {
1341 _name = prop->value();
1342 /* used to set panner name with this, but no more */
1345 if ((prop = node.property ("id")) != 0) {
1346 _id = prop->value ();
1354 if ((prop = node.property ("iolimits")) != 0) {
1355 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1356 &in_min, &in_max, &out_min, &out_max);
1358 /* Correct for the difference between the way we write things to session files and the
1359 way things are described by ChanCount; see comments in io.h about what the different
1360 ChanCount values mean. */
1363 _input_minimum = ChanCount::ZERO;
1365 _input_minimum = ChanCount (_default_type, in_min);
1369 _input_maximum = ChanCount::INFINITE;
1371 _input_maximum = ChanCount (_default_type, in_max);
1375 _output_minimum = ChanCount::ZERO;
1377 _output_minimum = ChanCount (_default_type, out_min);
1381 _output_maximum = ChanCount::INFINITE;
1383 _output_maximum = ChanCount (_default_type, out_max);
1387 if ((prop = node.property ("gain")) != 0) {
1388 set_gain (atof (prop->value().c_str()), this);
1389 _gain = _desired_gain;
1392 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1393 /* old school automation handling */
1396 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1398 // Old school Panner.
1399 if ((*iter)->name() == "Panner") {
1401 _panner = new Panner (_name, _session);
1403 _panner->set_state (**iter);
1406 if ((*iter)->name() == "Processor") {
1407 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1409 _panner = new Panner (_name, _session);
1411 _panner->set_state (**iter);
1415 if ((*iter)->name() == X_("Automation")) {
1417 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1420 if ((*iter)->name() == X_("Controllable")) {
1421 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1422 _gain_control->set_state (**iter);
1429 if (create_ports (node)) {
1435 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1439 _panner = new Panner( _name, _session );
1440 if (panners_legal) {
1443 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1446 if (connecting_legal) {
1448 if (make_connections (node)) {
1454 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1457 if (!ports_legal || !connecting_legal) {
1458 pending_state_node = new XMLNode (node);
1465 IO::load_automation (string path)
1470 uint32_t linecnt = 0;
1472 LocaleGuard lg (X_("POSIX"));
1474 fullpath = Glib::build_filename(_session.automation_dir(), path);
1476 in.open (fullpath.c_str());
1479 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1481 in.open (fullpath.c_str());
1484 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1489 clear_automation ();
1491 while (in.getline (line, sizeof(line), '\n')) {
1496 if (++linecnt == 1) {
1497 if (memcmp (line, "version", 7) == 0) {
1498 if (sscanf (line, "version %f", &version) != 1) {
1499 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1503 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1510 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1511 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1517 _gain_control->list()->fast_simple_add (when, value);
1527 /* older (pre-1.0) versions of ardour used this */
1531 warning << _("dubious automation event found (and ignored)") << endmsg;
1539 IO::connecting_became_legal ()
1543 if (pending_state_node == 0) {
1544 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1549 connection_legal_c.disconnect ();
1551 ret = make_connections (*pending_state_node);
1554 delete pending_state_node;
1555 pending_state_node = 0;
1561 IO::ports_became_legal ()
1565 if (pending_state_node == 0) {
1566 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1571 port_legal_c.disconnect ();
1573 ret = create_ports (*pending_state_node);
1575 if (connecting_legal) {
1576 delete pending_state_node;
1577 pending_state_node = 0;
1583 boost::shared_ptr<Bundle>
1584 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1586 static const string digits = "0123456789";
1588 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1591 int bundle_number, mask;
1592 string possible_name;
1593 bool stereo = false;
1594 string::size_type last_non_digit_pos;
1596 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1599 // find numeric suffix of desired name
1602 last_non_digit_pos = desired_name.find_last_not_of(digits);
1604 if (last_non_digit_pos != string::npos) {
1606 s << desired_name.substr(last_non_digit_pos);
1610 // see if it's a stereo connection e.g. "in 3+4"
1612 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1613 int left_bundle_number = 0;
1614 string::size_type left_last_non_digit_pos;
1616 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1618 if (left_last_non_digit_pos != string::npos) {
1620 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1621 s >> left_bundle_number;
1623 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1634 // find highest set bit
1636 while ((mask <= bundle_number) && (mask <<= 1)) {}
1638 // "wrap" bundle number into largest possible power of 2
1643 if (bundle_number & mask) {
1644 bundle_number &= ~mask;
1647 s << default_name << " " << bundle_number + 1;
1650 s << "+" << bundle_number + 2;
1653 possible_name = s.str();
1655 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1662 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1665 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1676 IO::create_ports (const XMLNode& node)
1678 XMLProperty const * prop;
1679 uint32_t num_inputs = 0;
1680 uint32_t num_outputs = 0;
1682 if ((prop = node.property ("input-connection")) != 0) {
1684 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1687 num_inputs = c->nchannels ();
1692 } else if ((prop = node.property ("inputs")) != 0) {
1694 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1697 if ((prop = node.property ("output-connection")) != 0) {
1699 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1702 num_outputs = c->nchannels ();
1707 } else if ((prop = node.property ("outputs")) != 0) {
1709 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1712 no_panner_reset = true;
1714 if (ensure_io (ChanCount (_default_type, num_inputs),
1715 ChanCount (_default_type, num_outputs),
1718 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1722 no_panner_reset = false;
1724 set_deferred_state ();
1732 IO::make_connections (const XMLNode& node)
1734 const XMLProperty* prop;
1736 if ((prop = node.property ("input-connection")) != 0) {
1737 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1743 if (n_inputs().get(c->type()) == c->nchannels() && c->ports_are_outputs()) {
1744 connect_input_ports_to_bundle (c, this);
1747 } else if ((prop = node.property ("inputs")) != 0) {
1748 if (set_inputs (prop->value())) {
1749 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1754 if ((prop = node.property ("output-connection")) != 0) {
1755 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1761 if (n_outputs().get(c->type()) == c->nchannels() && c->ports_are_inputs()) {
1762 connect_output_ports_to_bundle (c, this);
1765 } else if ((prop = node.property ("outputs")) != 0) {
1766 if (set_outputs (prop->value())) {
1767 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1772 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1774 if ((*i)->name() == "InputBundle") {
1775 XMLProperty const * prop = (*i)->property ("name");
1777 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1779 connect_input_ports_to_bundle (b, this);
1783 } else if ((*i)->name() == "OutputBundle") {
1784 XMLProperty const * prop = (*i)->property ("name");
1786 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1788 connect_output_ports_to_bundle (b, this);
1798 IO::set_inputs (const string& str)
1800 vector<string> ports;
1805 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1809 // FIXME: audio-only
1810 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1814 string::size_type start, end, ostart;
1821 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1824 if ((end = str.find_first_of ('}', start)) == string::npos) {
1825 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1829 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1830 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1836 for (int x = 0; x < n; ++x) {
1837 connect_input (input (i), ports[x], this);
1849 IO::set_outputs (const string& str)
1851 vector<string> ports;
1856 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1860 // FIXME: audio-only
1861 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1865 string::size_type start, end, ostart;
1872 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1875 if ((end = str.find_first_of ('}', start)) == string::npos) {
1876 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1880 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1881 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1887 for (int x = 0; x < n; ++x) {
1888 connect_output (output (i), ports[x], this);
1900 IO::parse_io_string (const string& str, vector<string>& ports)
1902 string::size_type pos, opos;
1904 if (str.length() == 0) {
1913 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1914 ports.push_back (str.substr (opos, pos - opos));
1918 if (opos < str.length()) {
1919 ports.push_back (str.substr(opos));
1922 return ports.size();
1926 IO::parse_gain_string (const string& str, vector<string>& ports)
1928 string::size_type pos, opos;
1934 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1935 ports.push_back (str.substr (opos, pos - opos));
1939 if (opos < str.length()) {
1940 ports.push_back (str.substr(opos));
1943 return ports.size();
1947 IO::set_name (const string& requested_name)
1949 if (requested_name == _name) {
1955 if ( (rt = dynamic_cast<Route *>(this))) {
1956 name = Route::ensure_track_or_route_name(requested_name, _session);
1958 name = requested_name;
1962 /* replace all colons in the name. i wish we didn't have to do this */
1964 if (replace_all (name, ":", "-")) {
1965 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1968 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1969 string current_name = i->name();
1970 current_name.replace (current_name.find (_name), _name.length(), name);
1971 i->set_name (current_name);
1974 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1975 string current_name = i->name();
1976 current_name.replace (current_name.find (_name), _name.length(), name);
1977 i->set_name (current_name);
1980 bool const r = SessionObject::set_name(name);
1982 setup_bundles_for_inputs_and_outputs ();
1988 IO::set_input_minimum (ChanCount n)
1994 IO::set_input_maximum (ChanCount n)
2000 IO::set_output_minimum (ChanCount n)
2002 _output_minimum = n;
2006 IO::set_output_maximum (ChanCount n)
2008 _output_maximum = n;
2012 IO::set_port_latency (nframes_t nframes)
2014 Glib::Mutex::Lock lm (io_lock);
2016 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2017 i->set_latency (nframes);
2022 IO::output_latency () const
2024 nframes_t max_latency;
2029 /* io lock not taken - must be protected by other means */
2031 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2032 if ((latency = i->total_latency ()) > max_latency) {
2033 max_latency = latency;
2041 IO::input_latency () const
2043 nframes_t max_latency;
2048 /* io lock not taken - must be protected by other means */
2050 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2051 if ((latency = i->total_latency ()) > max_latency) {
2052 max_latency = latency;
2060 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2063 BLOCK_PROCESS_CALLBACK ();
2064 Glib::Mutex::Lock lm2 (io_lock);
2066 c->connect (_bundle_for_inputs, _session.engine());
2068 /* If this is a UserBundle, make a note of what we've done */
2070 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2073 /* See if we already know about this one */
2074 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2075 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2079 if (i == _bundles_connected_to_inputs.end()) {
2080 /* We don't, so make a note */
2081 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2086 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2091 IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2094 BLOCK_PROCESS_CALLBACK ();
2095 Glib::Mutex::Lock lm2 (io_lock);
2097 c->disconnect (_bundle_for_inputs, _session.engine());
2099 /* If this is a UserBundle, make a note of what we've done */
2101 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2104 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2105 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2109 if (i != _bundles_connected_to_inputs.end()) {
2110 _bundles_connected_to_inputs.erase (i);
2115 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2120 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2123 BLOCK_PROCESS_CALLBACK ();
2124 Glib::Mutex::Lock lm2 (io_lock);
2126 c->connect (_bundle_for_outputs, _session.engine());
2128 /* If this is a UserBundle, make a note of what we've done */
2130 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2133 /* See if we already know about this one */
2134 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2135 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2139 if (i == _bundles_connected_to_outputs.end()) {
2140 /* We don't, so make a note */
2141 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2146 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2152 IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2155 BLOCK_PROCESS_CALLBACK ();
2156 Glib::Mutex::Lock lm2 (io_lock);
2158 c->disconnect (_bundle_for_outputs, _session.engine());
2160 /* If this is a UserBundle, make a note of what we've done */
2162 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2165 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2166 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2170 if (i != _bundles_connected_to_outputs.end()) {
2171 _bundles_connected_to_outputs.erase (i);
2176 output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2182 IO::disable_connecting ()
2184 connecting_legal = false;
2189 IO::enable_connecting ()
2191 connecting_legal = true;
2192 return ConnectingLegal ();
2196 IO::disable_ports ()
2198 ports_legal = false;
2206 return PortsLegal ();
2210 IO::disable_panners (void)
2212 panners_legal = false;
2217 IO::reset_panners ()
2219 panners_legal = true;
2220 return PannersLegal ();
2224 IO::bundle_changed (Bundle::Change c)
2227 // connect_input_ports_to_bundle (_input_bundle, this);
2231 IO::GainControl::set_value (float val)
2233 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2234 if (val > 1.99526231f)
2237 _io->set_gain (val, this);
2239 AutomationControl::set_value(val);
2243 IO::GainControl::get_value (void) const
2245 return AutomationControl::get_value();
2249 IO::setup_peak_meters()
2251 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2252 _meter->configure_io (max_streams, max_streams);
2256 Update the peak meters.
2258 The meter signal lock is taken to prevent modification of the
2259 Meter signal while updating the meters, taking the meter signal
2260 lock prior to taking the io_lock ensures that all IO will remain
2261 valid while metering.
2266 Glib::Mutex::Lock guard (m_meter_signal_lock);
2267 Meter(); /* EMIT SIGNAL */
2273 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2275 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2280 IO::clear_automation ()
2282 data().clear (); // clears gain automation
2283 _panner->data().clear();
2287 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2289 // XXX: would be nice to get rid of this special hack
2291 if (param.type() == GainAutomation) {
2293 bool changed = false;
2296 Glib::Mutex::Lock lm (control_lock());
2298 boost::shared_ptr<AutomationList> gain_auto
2299 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2301 if (state != gain_auto->automation_state()) {
2303 _last_automation_snapshot = 0;
2304 gain_auto->set_automation_state (state);
2307 // FIXME: shouldn't this use Curve?
2308 set_gain (gain_auto->eval (_session.transport_frame()), this);
2314 _session.set_dirty ();
2318 AutomatableControls::set_parameter_automation_state(param, state);
2323 IO::inc_gain (gain_t factor, void *src)
2325 if (_desired_gain == 0.0f)
2326 set_gain (0.000001f + (0.000001f * factor), src);
2328 set_gain (_desired_gain + (_desired_gain * factor), src);
2332 IO::set_gain (gain_t val, void *src)
2334 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2335 if (val > 1.99526231f) {
2339 //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2341 if (src != _gain_control.get()) {
2342 _gain_control->set_value(val);
2343 // bit twisty, this will come back and call us again
2344 // (this keeps control in sync with reality)
2349 Glib::Mutex::Lock dm (declick_lock);
2350 _desired_gain = val;
2353 if (_session.transport_stopped()) {
2358 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2359 _gain_control->list()->add (_session.transport_frame(), val);
2364 _session.set_dirty();
2368 IO::start_pan_touch (uint32_t which)
2370 if (which < _panner->npanners()) {
2371 (*_panner).pan_control(which)->start_touch();
2376 IO::end_pan_touch (uint32_t which)
2378 if (which < _panner->npanners()) {
2379 (*_panner).pan_control(which)->stop_touch();
2385 IO::automation_snapshot (nframes_t now, bool force)
2387 AutomatableControls::automation_snapshot (now, force);
2388 // XXX: This seems to be wrong.
2389 // drobilla: shouldnt automation_snapshot for panner be called
2390 // "automagically" because its an Automatable now ?
2392 // we could dump this whole method then. <3
2394 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2395 _panner->automation_snapshot (now, force);
2398 _panner->automation_snapshot (now, force);
2399 _last_automation_snapshot = now;
2403 IO::transport_stopped (nframes_t frame)
2405 _gain_control->list()->reposition_for_rt_add (frame);
2407 if (_gain_control->automation_state() != Off) {
2409 /* the src=0 condition is a special signal to not propagate
2410 automation gain changes into the mix group when locating.
2413 // FIXME: shouldn't this use Curve?
2414 set_gain (_gain_control->list()->eval (frame), 0);
2417 _panner->transport_stopped (frame);
2421 IO::build_legal_port_name (DataType type, bool in)
2423 const int name_size = jack_port_name_size();
2428 if (type == DataType::AUDIO) {
2429 suffix = _("audio");
2430 } else if (type == DataType::MIDI) {
2433 throw unknown_type();
2438 maxports = _input_maximum.get(type);
2440 suffix += _("_out");
2441 maxports = _output_maximum.get(type);
2444 if (maxports == 1) {
2445 // allow space for the slash + the suffix
2446 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2447 char buf[name_size+1];
2448 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2449 return string (buf);
2452 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2454 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2456 char buf1[name_size+1];
2457 char buf2[name_size+1];
2459 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2464 port_number = find_input_port_hole (buf1);
2466 port_number = find_output_port_hole (buf1);
2469 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2471 return string (buf2);
2475 IO::find_input_port_hole (const char* base)
2477 /* CALLER MUST HOLD IO LOCK */
2481 if (_inputs.empty()) {
2485 /* we only allow up to 4 characters for the port number
2488 for (n = 1; n < 9999; ++n) {
2489 char buf[jack_port_name_size()];
2490 PortSet::iterator i = _inputs.begin();
2492 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2494 for ( ; i != _inputs.end(); ++i) {
2495 if (i->name() == buf) {
2500 if (i == _inputs.end()) {
2508 IO::find_output_port_hole (const char* base)
2510 /* CALLER MUST HOLD IO LOCK */
2514 if (_outputs.empty()) {
2518 /* we only allow up to 4 characters for the port number
2521 for (n = 1; n < 9999; ++n) {
2522 char buf[jack_port_name_size()];
2523 PortSet::iterator i = _outputs.begin();
2525 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2527 for ( ; i != _outputs.end(); ++i) {
2528 if (i->name() == buf) {
2533 if (i == _outputs.end()) {
2542 IO::set_active (bool yn)
2545 active_changed(); /* EMIT SIGNAL */
2549 IO::audio_input(uint32_t n) const
2551 return dynamic_cast<AudioPort*>(input(n));
2555 IO::audio_output(uint32_t n) const
2557 return dynamic_cast<AudioPort*>(output(n));
2561 IO::midi_input(uint32_t n) const
2563 return dynamic_cast<MidiPort*>(input(n));
2567 IO::midi_output(uint32_t n) const
2569 return dynamic_cast<MidiPort*>(output(n));
2573 IO::set_phase_invert (bool yn, void *src)
2575 if (_phase_invert != yn) {
2577 // phase_invert_changed (src); /* EMIT SIGNAL */
2582 IO::set_denormal_protection (bool yn, void *src)
2584 if (_denormal_protection != yn) {
2585 _denormal_protection = yn;
2586 // denormal_protection_changed (src); /* EMIT SIGNAL */
2591 IO::update_port_total_latencies ()
2593 /* io_lock, not taken: function must be called from Session::process() calltree */
2595 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2596 _session.engine().update_total_latency (*i);
2599 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2600 _session.engine().update_total_latency (*i);
2606 * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
2610 IO::setup_bundles_for_inputs_and_outputs ()
2612 setup_bundle_for_inputs ();
2613 setup_bundle_for_outputs ();
2618 IO::setup_bundle_for_inputs ()
2622 if (!_bundle_for_inputs) {
2623 _bundle_for_inputs.reset (new Bundle (true));
2626 _bundle_for_inputs->suspend_signals ();
2628 _bundle_for_inputs->set_type (default_type ());
2630 _bundle_for_inputs->remove_channels ();
2632 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2633 _bundle_for_inputs->set_name (buf);
2634 uint32_t const ni = inputs().num_ports();
2635 for (uint32_t i = 0; i < ni; ++i) {
2636 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2637 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2640 _bundle_for_inputs->resume_signals ();
2645 IO::setup_bundle_for_outputs ()
2649 if (!_bundle_for_outputs) {
2650 _bundle_for_outputs.reset (new Bundle (false));
2653 _bundle_for_outputs->suspend_signals ();
2655 _bundle_for_outputs->set_type (default_type ());
2657 _bundle_for_outputs->remove_channels ();
2659 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2660 _bundle_for_outputs->set_name (buf);
2661 uint32_t const no = outputs().num_ports();
2662 for (uint32_t i = 0; i < no; ++i) {
2663 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2664 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2667 _bundle_for_outputs->resume_signals ();
2671 /** @return Bundles connected to our inputs */
2673 IO::bundles_connected_to_inputs ()
2678 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2679 bundles.push_back (i->bundle);
2682 /* Session bundles */
2683 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2684 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2685 if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
2686 bundles.push_back (*i);
2691 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2692 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2693 if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
2694 bundles.push_back ((*i)->bundle_for_outputs());
2702 /* @return Bundles connected to our outputs */
2704 IO::bundles_connected_to_outputs ()
2709 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2710 bundles.push_back (i->bundle);
2713 /* Session bundles */
2714 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2715 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2716 if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
2717 bundles.push_back (*i);
2722 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2723 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2724 if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
2725 bundles.push_back ((*i)->bundle_for_inputs());
2733 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2736 changed = b->Changed.connect (
2737 sigc::mem_fun (*io, &IO::bundle_changed)
2742 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2744 /* io_lock, not taken: function must be called from Session::process() calltree */
2748 IO::flush_outputs (nframes_t nframes, nframes_t offset)
2750 /* io_lock, not taken: function must be called from Session::process() calltree */
2751 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2753 /* Only run cycle_start() on output ports, because
2754 inputs must be done in the correct processing order,
2755 which requires interleaving with route processing.
2758 (*i).flush_buffers (nframes, offset);
2764 IO::bundle_channel_name (uint32_t c, uint32_t n) const
2772 return c == 0 ? _("L") : _("R");
2774 snprintf (buf, sizeof(buf), _("%d"), (c + 1));
2782 IO::name_from_state (const XMLNode& node)
2784 const XMLProperty* prop;
2786 if ((prop = node.property ("name")) != 0) {
2787 return prop->value();
2794 IO::set_name_in_state (XMLNode& node, const string& new_name)
2796 const XMLProperty* prop;
2798 if ((prop = node.property ("name")) != 0) {
2799 node.add_property ("name", new_name);