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<void,nframes_t> IO::CycleStart;
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 DataType default_type,
105 ChanCount in_min, ChanCount in_max, ChanCount out_min, ChanCount out_max)
106 : SessionObject (s, name)
107 , AutomatableControls (s)
108 , _output_buffers (new BufferSet())
110 , _default_type (default_type)
111 , _amp (new Amp(s, *this))
112 , _meter (new PeakMeter(s))
113 , _panner (new Panner(name, s))
114 , _input_minimum (ChanCount::ZERO)
115 , _input_maximum (ChanCount::INFINITE)
116 , _output_minimum (ChanCount::ZERO)
117 , _output_maximum (ChanCount::INFINITE)
119 _input_minimum = in_min;
120 _output_minimum = out_min;
121 _input_maximum = in_max;
122 _output_maximum = out_max;
125 pending_state_node = 0;
126 no_panner_reset = false;
127 _phase_invert = false;
130 boost::shared_ptr<AutomationList> gl(
131 new AutomationList(Evoral::Parameter(GainAutomation)));
133 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
135 add_control(_gain_control);
138 // IO::Meter is emitted from another thread so the
139 // Meter signal must be protected.
140 Glib::Mutex::Lock guard (m_meter_signal_lock);
141 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
145 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
147 _session.add_controllable (_gain_control);
149 setup_bundles_for_inputs_and_outputs ();
152 IO::IO (Session& s, const XMLNode& node, DataType dt)
153 : SessionObject(s, "unnamed io")
154 , AutomatableControls (s)
155 , _output_buffers (new BufferSet())
158 , _amp (new Amp(s, *this))
159 , _meter(new PeakMeter (_session))
162 no_panner_reset = false;
165 boost::shared_ptr<AutomationList> gl(
166 new AutomationList(Evoral::Parameter(GainAutomation)));
168 _gain_control = boost::shared_ptr<GainControl>(
169 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
171 add_control(_gain_control);
176 // IO::Meter is emitted from another thread so the
177 // Meter signal must be protected.
178 Glib::Mutex::Lock guard (m_meter_signal_lock);
179 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
183 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
185 _session.add_controllable (_gain_control);
187 setup_bundles_for_inputs_and_outputs ();
192 Glib::Mutex::Lock guard (m_meter_signal_lock);
193 Glib::Mutex::Lock lm (io_lock);
195 BLOCK_PROCESS_CALLBACK ();
197 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
198 _session.engine().unregister_port (*i);
201 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
202 _session.engine().unregister_port (*i);
205 m_meter_connection.disconnect();
209 IO::silence (nframes_t nframes)
211 /* io_lock, not taken: function must be called from Session::process() calltree */
213 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
214 i->get_buffer(nframes).silence (nframes);
218 /** Deliver bufs to the IO's output ports
220 * This function should automatically do whatever it necessary to correctly deliver bufs
221 * to the outputs, eg applying gain or pan or whatever else needs to be done.
224 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
226 // Attach output buffers to port buffers
227 output_buffers().attach_buffers (_outputs, nframes, _output_offset);
229 // Use the panner to distribute audio to output port buffers
230 if (_panner && _panner->npanners() && !_panner->bypassed()) {
232 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes);
234 // Do a 1:1 copy of data to output ports
236 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
237 copy_to_outputs (bufs, DataType::AUDIO, nframes);
239 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
240 copy_to_outputs (bufs, DataType::MIDI, nframes);
244 // Apply gain to output buffers if gain automation isn't playing
245 if ( ! _amp->apply_gain_automation()) {
247 gain_t dg = _gain; // desired gain
250 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
253 dg = _gain_control->user_float();
258 if (dg != _gain || dg != 1.0) {
259 Amp::apply_gain(output_buffers(), nframes, _gain, dg, _phase_invert);
267 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
269 // Copy any buffers 1:1 to outputs
271 PortSet::iterator o = _outputs.begin(type);
272 BufferSet::iterator i = bufs.begin(type);
273 BufferSet::iterator prev = i;
275 while (i != bufs.end(type) && o != _outputs.end (type)) {
276 Buffer& port_buffer (o->get_buffer (nframes));
277 port_buffer.read_from (*i, nframes, _output_offset);
283 // Copy last buffer to any extra outputs
284 while (o != _outputs.end(type)) {
285 Buffer& port_buffer (o->get_buffer (nframes));
286 port_buffer.read_from (*prev, nframes, _output_offset);
292 IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset)
294 assert(outs.available() >= n_inputs());
296 if (n_inputs() == ChanCount::ZERO) {
300 outs.set_count(n_inputs());
302 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
303 PortSet::iterator i = _inputs.begin(*t);
304 BufferSet::iterator o = outs.begin(*t);
306 for (uint32_t off = 0; off < offset.get(*t); ++off, ++o) {
307 if (o == outs.end(*t)) {
312 for ( ; i != _inputs.end(*t); ++i, ++o) {
313 Buffer& b (i->get_buffer (nframes));
314 o->read_from (b, nframes);
320 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
322 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
323 collect_input (bufs, nframes);
324 _meter->run_in_place (bufs, start_frame, end_frame, nframes);
329 IO::check_bundles_connected_to_inputs ()
331 check_bundles (_bundles_connected_to_inputs, inputs());
335 IO::check_bundles_connected_to_outputs ()
337 check_bundles (_bundles_connected_to_outputs, outputs());
341 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
343 std::vector<UserBundleInfo> new_list;
345 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
347 uint32_t const N = i->bundle->nchannels ();
349 if (ports.num_ports (default_type()) < N) {
355 for (uint32_t j = 0; j < N; ++j) {
356 /* Every port on bundle channel j must be connected to our input j */
357 Bundle::PortList const pl = i->bundle->channel_ports (j);
358 for (uint32_t k = 0; k < pl.size(); ++k) {
359 if (ports.port(j)->connected_to (pl[k]) == false) {
371 new_list.push_back (*i);
373 i->changed.disconnect ();
382 IO::disconnect_input (Port* our_port, string other_port, void* src)
384 if (other_port.length() == 0 || our_port == 0) {
389 BLOCK_PROCESS_CALLBACK ();
392 Glib::Mutex::Lock lm (io_lock);
394 /* check that our_port is really one of ours */
396 if ( ! _inputs.contains(our_port)) {
400 /* disconnect it from the source */
402 if (our_port->disconnect (other_port)) {
403 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
407 check_bundles_connected_to_inputs ();
411 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
412 _session.set_dirty ();
418 IO::connect_input (Port* our_port, string other_port, void* src)
420 if (other_port.length() == 0 || our_port == 0) {
425 BLOCK_PROCESS_CALLBACK ();
428 Glib::Mutex::Lock lm (io_lock);
430 /* check that our_port is really one of ours */
432 if ( ! _inputs.contains(our_port) ) {
436 /* connect it to the source */
438 if (our_port->connect (other_port)) {
444 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
445 _session.set_dirty ();
450 IO::disconnect_output (Port* our_port, string other_port, void* src)
452 if (other_port.length() == 0 || our_port == 0) {
457 BLOCK_PROCESS_CALLBACK ();
460 Glib::Mutex::Lock lm (io_lock);
462 /* check that our_port is really one of ours */
464 if ( ! _outputs.contains(our_port) ) {
468 /* disconnect it from the destination */
470 if (our_port->disconnect (other_port)) {
471 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
475 check_bundles_connected_to_outputs ();
479 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
480 _session.set_dirty ();
485 IO::connect_output (Port* our_port, string other_port, void* src)
487 if (other_port.length() == 0 || our_port == 0) {
492 BLOCK_PROCESS_CALLBACK ();
496 Glib::Mutex::Lock lm (io_lock);
498 /* check that our_port is really one of ours */
500 if ( ! _outputs.contains(our_port) ) {
504 /* connect it to the destination */
506 if (our_port->connect (other_port)) {
512 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
513 _session.set_dirty ();
518 IO::set_input (Port* other_port, void* src)
520 /* this removes all but one ports, and connects that one port
521 to the specified source.
524 if (_input_minimum.n_total() > 1) {
525 /* sorry, you can't do this */
529 if (other_port == 0) {
530 if (_input_minimum == ChanCount::ZERO) {
531 return ensure_inputs (ChanCount::ZERO, false, true, src);
537 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
541 return connect_input (_inputs.port(0), other_port->name(), src);
545 IO::remove_output_port (Port* port, void* src)
547 IOChange change (NoChange);
550 BLOCK_PROCESS_CALLBACK ();
554 Glib::Mutex::Lock lm (io_lock);
556 if (n_outputs() <= _output_minimum) {
557 /* sorry, you can't do this */
561 if (_outputs.remove(port)) {
562 change = IOChange (change|ConfigurationChanged);
564 if (port->connected()) {
565 change = IOChange (change|ConnectionsChanged);
568 _session.engine().unregister_port (*port);
569 check_bundles_connected_to_outputs ();
571 setup_peak_meters ();
576 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
579 if (change == ConfigurationChanged) {
580 setup_bundle_for_outputs ();
583 if (change != NoChange) {
584 output_changed (change, src);
585 _session.set_dirty ();
592 /** Add an output port.
594 * @param destination Name of input port to connect new port to.
595 * @param src Source for emitted ConfigurationChanged signal.
596 * @param type Data type of port. Default value (NIL) will use this IO's default type.
599 IO::add_output_port (string destination, void* src, DataType type)
603 if (type == DataType::NIL)
604 type = _default_type;
607 BLOCK_PROCESS_CALLBACK ();
611 Glib::Mutex::Lock lm (io_lock);
613 if (n_outputs() >= _output_maximum) {
617 /* Create a new output port */
619 string portname = build_legal_port_name (type, false);
621 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
622 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
626 _outputs.add (our_port);
627 setup_peak_meters ();
631 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
634 if (destination.length()) {
635 if (our_port->connect (destination)) {
640 // pan_changed (src); /* EMIT SIGNAL */
641 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
642 setup_bundle_for_outputs ();
643 _session.set_dirty ();
649 IO::remove_input_port (Port* port, void* src)
651 IOChange change (NoChange);
654 BLOCK_PROCESS_CALLBACK ();
658 Glib::Mutex::Lock lm (io_lock);
660 if (n_inputs() <= _input_minimum) {
661 /* sorry, you can't do this */
665 if (_inputs.remove(port)) {
666 change = IOChange (change|ConfigurationChanged);
668 if (port->connected()) {
669 change = IOChange (change|ConnectionsChanged);
672 _session.engine().unregister_port (*port);
673 check_bundles_connected_to_inputs ();
675 setup_peak_meters ();
680 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
683 if (change == ConfigurationChanged) {
684 setup_bundle_for_inputs ();
687 if (change != NoChange) {
688 input_changed (change, src);
689 _session.set_dirty ();
697 /** Add an input port.
699 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
700 * @param destination Name of input port to connect new port to.
701 * @param src Source for emitted ConfigurationChanged signal.
704 IO::add_input_port (string source, void* src, DataType type)
708 if (type == DataType::NIL)
709 type = _default_type;
712 BLOCK_PROCESS_CALLBACK ();
715 Glib::Mutex::Lock lm (io_lock);
717 if (n_inputs().get (type) >= _input_maximum.get (type)) {
721 /* Create a new input port */
723 string portname = build_legal_port_name (type, true);
725 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
726 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
730 _inputs.add (our_port);
731 setup_peak_meters ();
735 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
738 if (source.length()) {
740 if (our_port->connect (source)) {
745 // pan_changed (src); /* EMIT SIGNAL */
746 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
747 setup_bundle_for_inputs ();
748 _session.set_dirty ();
754 IO::disconnect_inputs (void* src)
757 BLOCK_PROCESS_CALLBACK ();
760 Glib::Mutex::Lock lm (io_lock);
762 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
763 i->disconnect_all ();
766 check_bundles_connected_to_inputs ();
770 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
776 IO::disconnect_outputs (void* src)
779 BLOCK_PROCESS_CALLBACK ();
782 Glib::Mutex::Lock lm (io_lock);
784 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
785 i->disconnect_all ();
788 check_bundles_connected_to_outputs ();
792 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
793 _session.set_dirty ();
799 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
801 Port* input_port = 0;
802 bool changed = false;
804 _configured_inputs = count;
806 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
808 const size_t n = count.get(*t);
810 /* remove unused ports */
811 for (size_t i = n_inputs().get(*t); i > n; --i) {
812 input_port = _inputs.port(*t, i-1);
815 _inputs.remove(input_port);
816 _session.engine().unregister_port (*input_port);
821 /* create any necessary new ports */
822 while (n_inputs().get(*t) < n) {
824 string portname = build_legal_port_name (*t, true);
828 if ((input_port = _session.engine().register_input_port (*t, portname)) == 0) {
829 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
834 catch (AudioEngine::PortRegistrationFailure& err) {
835 setup_peak_meters ();
838 throw AudioEngine::PortRegistrationFailure();
841 _inputs.add (input_port);
847 check_bundles_connected_to_inputs ();
848 setup_peak_meters ();
850 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
851 _session.set_dirty ();
855 /* disconnect all existing ports so that we get a fresh start */
856 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
857 i->disconnect_all ();
865 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
867 bool in_changed = false;
868 bool out_changed = false;
869 bool need_pan_reset = false;
871 assert(in != ChanCount::INFINITE);
872 assert(out != ChanCount::INFINITE);
874 in = ChanCount::min (_input_maximum, in);
875 out = ChanCount::min (_output_maximum, out);
877 _configured_inputs = in;
878 _configured_outputs = out;
880 if (in == n_inputs() && out == n_outputs() && !clear) {
885 BLOCK_PROCESS_CALLBACK ();
886 Glib::Mutex::Lock lm (io_lock);
890 if (n_outputs() != out) {
891 need_pan_reset = true;
894 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
896 const size_t nin = in.get(*t);
897 const size_t nout = out.get(*t);
899 Port* output_port = 0;
900 Port* input_port = 0;
902 /* remove unused output ports */
903 for (size_t i = n_outputs().get(*t); i > nout; --i) {
904 output_port = _outputs.port(*t, i-1);
907 _outputs.remove(output_port);
908 _session.engine().unregister_port (*output_port);
913 /* remove unused input ports */
914 for (size_t i = n_inputs().get(*t); i > nin; --i) {
915 input_port = _inputs.port(*t, i-1);
918 _inputs.remove(input_port);
919 _session.engine().unregister_port (*input_port);
924 /* create any necessary new input ports */
925 while (n_inputs().get(*t) < nin) {
926 string portname = build_legal_port_name (*t, true);
929 if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
930 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
935 catch (AudioEngine::PortRegistrationFailure& err) {
936 setup_peak_meters ();
946 /* create any necessary new output ports */
948 while (n_outputs().get(*t) < nout) {
950 string portname = build_legal_port_name (*t, false);
953 if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
954 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
959 catch (AudioEngine::PortRegistrationFailure& err) {
960 setup_peak_meters ();
973 /* disconnect all existing ports so that we get a fresh start */
975 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
976 i->disconnect_all ();
979 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
980 i->disconnect_all ();
984 if (in_changed || out_changed) {
985 setup_peak_meters ();
991 check_bundles_connected_to_outputs ();
992 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
993 setup_bundle_for_outputs ();
997 check_bundles_connected_to_inputs ();
998 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
999 setup_bundle_for_inputs ();
1002 if (in_changed || out_changed) {
1003 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1004 _session.set_dirty ();
1011 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1013 bool changed = false;
1015 count = min (_input_maximum, count);
1017 if (count == n_inputs() && !clear) {
1022 BLOCK_PROCESS_CALLBACK ();
1023 Glib::Mutex::Lock im (io_lock);
1024 changed = ensure_inputs_locked (count, clear, src);
1026 changed = ensure_inputs_locked (count, clear, src);
1030 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1031 setup_bundle_for_inputs ();
1032 _session.set_dirty ();
1038 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1040 Port* output_port = 0;
1041 bool changed = false;
1042 bool need_pan_reset = false;
1044 _configured_outputs = count;
1046 if (n_outputs() != count) {
1047 need_pan_reset = true;
1050 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1052 const size_t n = count.get(*t);
1054 /* remove unused ports */
1055 for (size_t i = n_outputs().get(*t); i > n; --i) {
1056 output_port = _outputs.port(*t, i-1);
1058 assert(output_port);
1059 _outputs.remove(output_port);
1060 _session.engine().unregister_port (*output_port);
1065 /* create any necessary new ports */
1066 while (n_outputs().get(*t) < n) {
1068 string portname = build_legal_port_name (*t, false);
1070 if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
1071 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1075 _outputs.add (output_port);
1077 setup_peak_meters ();
1079 if (need_pan_reset) {
1086 check_bundles_connected_to_outputs ();
1087 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1088 _session.set_dirty ();
1092 /* disconnect all existing ports so that we get a fresh start */
1093 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1094 i->disconnect_all ();
1102 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1104 bool changed = false;
1106 if (_output_maximum != ChanCount::INFINITE) {
1107 count = min (_output_maximum, count);
1108 if (count == n_outputs() && !clear) {
1113 /* XXX caller should hold io_lock, but generally doesn't */
1116 BLOCK_PROCESS_CALLBACK ();
1117 Glib::Mutex::Lock im (io_lock);
1118 changed = ensure_outputs_locked (count, clear, src);
1120 changed = ensure_outputs_locked (count, clear, src);
1124 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1125 setup_bundle_for_outputs ();
1132 IO::effective_gain () const
1134 return _gain_control->get_value();
1140 if (panners_legal) {
1141 if (!no_panner_reset) {
1142 _panner->reset (n_outputs().n_audio(), pans_required());
1145 panner_legal_c.disconnect ();
1146 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1151 IO::panners_became_legal ()
1153 _panner->reset (n_outputs().n_audio(), pans_required());
1154 _panner->load (); // automation
1155 panner_legal_c.disconnect ();
1160 IO::defer_pan_reset ()
1162 no_panner_reset = true;
1166 IO::allow_pan_reset ()
1168 no_panner_reset = false;
1174 IO::get_state (void)
1176 return state (true);
1180 IO::state (bool full_state)
1182 XMLNode* node = new XMLNode (state_node_name);
1185 vector<string>::iterator ci;
1187 LocaleGuard lg (X_("POSIX"));
1188 Glib::Mutex::Lock lm (io_lock);
1190 node->add_property("name", _name);
1191 id().print (buf, sizeof (buf));
1192 node->add_property("id", buf);
1195 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1196 i != _bundles_connected_to_inputs.end();
1200 XMLNode* n = new XMLNode ("InputBundle");
1201 n->add_property ("name", i->bundle->name ());
1202 node->add_child_nocopy (*n);
1206 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1207 i != _bundles_connected_to_outputs.end();
1211 XMLNode* n = new XMLNode ("OutputBundle");
1212 n->add_property ("name", i->bundle->name ());
1213 node->add_child_nocopy (*n);
1218 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1220 vector<string> connections;
1222 if (i->get_connections (connections)) {
1226 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1231 /* if its a connection to our own port,
1232 return only the port name, not the
1233 whole thing. this allows connections
1234 to be re-established even when our
1235 client name is different.
1238 str += _session.engine().make_port_name_relative (*ci);
1248 node->add_property ("inputs", str);
1252 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1254 vector<string> connections;
1256 if (i->get_connections (connections)) {
1260 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1265 str += _session.engine().make_port_name_relative (*ci);
1275 node->add_property ("outputs", str);
1277 node->add_child_nocopy (_panner->state (full_state));
1278 node->add_child_nocopy (_gain_control->get_state ());
1280 snprintf (buf, sizeof(buf), "%2.12f", gain());
1281 node->add_property ("gain", buf);
1285 node->add_child_nocopy(*n_inputs().state("Inputs"));
1286 node->add_child_nocopy(*n_outputs().state("Outputs"));
1291 node->add_child_nocopy (get_automation_state());
1297 IO::set_state (const XMLNode& node)
1299 const XMLProperty* prop;
1300 XMLNodeConstIterator iter;
1301 LocaleGuard lg (X_("POSIX"));
1303 /* force use of non-localized representation of decimal point,
1304 since we use it a lot in XML files and so forth.
1307 if (node.name() != state_node_name) {
1308 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1312 if ((prop = node.property ("name")) != 0) {
1313 _name = prop->value();
1314 /* used to set panner name with this, but no more */
1317 if ((prop = node.property ("id")) != 0) {
1318 _id = prop->value ();
1326 if ((prop = node.property ("iolimits")) != 0) {
1327 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1328 &in_min, &in_max, &out_min, &out_max);
1331 // minimum == -1 => minimum == 0
1332 // maximum == -1 => maximum == infinity
1335 _input_minimum = ChanCount::ZERO;
1337 _input_minimum = ChanCount (_default_type, in_min);
1341 _input_maximum = ChanCount::INFINITE;
1343 _input_maximum = ChanCount (_default_type, in_max);
1347 _output_minimum = ChanCount::ZERO;
1349 _output_minimum = ChanCount (_default_type, out_min);
1353 _output_maximum = ChanCount::INFINITE;
1355 _output_maximum = ChanCount (_default_type, out_max);
1359 if ((prop = node.property ("gain")) != 0) {
1360 set_gain (atof (prop->value().c_str()), this);
1361 _gain = _gain_control->user_float();
1364 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1365 /* old school automation handling */
1368 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1370 // Old school Panner.
1371 if ((*iter)->name() == "Panner") {
1373 _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
1375 _panner->set_state (**iter);
1378 if ((*iter)->name() == "Processor") {
1379 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1381 _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
1383 _panner->set_state (**iter);
1387 if ((*iter)->name() == X_("Automation")) {
1389 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1392 if ((*iter)->name() == X_("Controllable")) {
1393 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1394 _gain_control->set_state (**iter);
1399 get_port_counts (node);
1403 if (create_ports (node)) {
1409 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1413 _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
1416 if (panners_legal) {
1419 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1422 if (connecting_legal) {
1424 if (make_connections (node)) {
1430 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1433 if (!ports_legal || !connecting_legal) {
1434 pending_state_node = new XMLNode (node);
1441 IO::load_automation (string path)
1446 uint32_t linecnt = 0;
1448 LocaleGuard lg (X_("POSIX"));
1450 fullpath = Glib::build_filename(_session.automation_dir(), path);
1452 in.open (fullpath.c_str());
1455 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1457 in.open (fullpath.c_str());
1460 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1465 clear_automation ();
1467 while (in.getline (line, sizeof(line), '\n')) {
1472 if (++linecnt == 1) {
1473 if (memcmp (line, "version", 7) == 0) {
1474 if (sscanf (line, "version %f", &version) != 1) {
1475 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1479 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1486 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1487 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1493 _gain_control->list()->fast_simple_add (when, value);
1503 /* older (pre-1.0) versions of ardour used this */
1507 warning << _("dubious automation event found (and ignored)") << endmsg;
1515 IO::connecting_became_legal ()
1519 if (pending_state_node == 0) {
1520 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1525 connection_legal_c.disconnect ();
1527 ret = make_connections (*pending_state_node);
1530 delete pending_state_node;
1531 pending_state_node = 0;
1537 IO::ports_became_legal ()
1541 if (pending_state_node == 0) {
1542 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1547 port_legal_c.disconnect ();
1549 get_port_counts (*pending_state_node);
1550 ret = create_ports (*pending_state_node);
1552 if (connecting_legal) {
1553 delete pending_state_node;
1554 pending_state_node = 0;
1560 boost::shared_ptr<Bundle>
1561 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1563 static const string digits = "0123456789";
1565 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1568 int bundle_number, mask;
1569 string possible_name;
1570 bool stereo = false;
1571 string::size_type last_non_digit_pos;
1573 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1576 // find numeric suffix of desired name
1579 last_non_digit_pos = desired_name.find_last_not_of(digits);
1581 if (last_non_digit_pos != string::npos) {
1583 s << desired_name.substr(last_non_digit_pos);
1587 // see if it's a stereo connection e.g. "in 3+4"
1589 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1590 int left_bundle_number = 0;
1591 string::size_type left_last_non_digit_pos;
1593 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1595 if (left_last_non_digit_pos != string::npos) {
1597 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1598 s >> left_bundle_number;
1600 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1611 // find highest set bit
1613 while ((mask <= bundle_number) && (mask <<= 1)) {}
1615 // "wrap" bundle number into largest possible power of 2
1620 if (bundle_number & mask) {
1621 bundle_number &= ~mask;
1624 s << default_name << " " << bundle_number + 1;
1627 s << "+" << bundle_number + 2;
1630 possible_name = s.str();
1632 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1639 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1642 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1653 IO::get_port_counts (const XMLNode& node)
1655 XMLProperty const * prop;
1656 XMLNodeConstIterator iter;
1657 ChanCount num_inputs = n_inputs();
1658 ChanCount num_outputs = n_outputs();
1660 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1661 if ((*iter)->name() == X_("Inputs")) {
1662 num_inputs = ChanCount::max(num_inputs, ChanCount(**iter));
1663 } else if ((*iter)->name() == X_("Outputs")) {
1664 num_outputs = ChanCount::max(num_inputs, ChanCount(**iter));
1668 if ((prop = node.property ("input-connection")) != 0) {
1670 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1672 num_inputs = ChanCount::max(num_inputs, ChanCount(c->type(), c->nchannels()));
1675 } else if ((prop = node.property ("inputs")) != 0) {
1677 num_inputs = ChanCount::max(num_inputs, ChanCount(_default_type,
1678 count (prop->value().begin(), prop->value().end(), '{')));
1681 if ((prop = node.property ("output-connection")) != 0) {
1683 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1685 num_outputs = ChanCount::max(num_outputs, ChanCount(c->type(), c->nchannels()));
1688 } else if ((prop = node.property ("outputs")) != 0) {
1690 num_outputs = ChanCount::max(num_outputs, ChanCount(_default_type,
1691 count (prop->value().begin(), prop->value().end(), '{')));
1694 _configured_inputs = num_inputs;
1695 _configured_outputs = num_outputs;
1697 _input_minimum = ChanCount::min(_input_minimum, num_inputs);
1698 _input_maximum = ChanCount::max(_input_maximum, num_inputs);
1699 _output_minimum = ChanCount::min(_output_minimum, num_outputs);
1700 _output_maximum = ChanCount::max(_output_maximum, num_outputs);
1706 IO::create_ports (const XMLNode& node)
1708 no_panner_reset = true;
1710 if (ensure_io (_input_minimum, _output_minimum, true, this)) {
1711 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1715 no_panner_reset = false;
1717 set_deferred_state ();
1723 IO::make_connections (const XMLNode& node)
1725 const XMLProperty* prop;
1727 if ((prop = node.property ("input-connection")) != 0) {
1728 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1734 if (n_inputs().get(c->type()) == c->nchannels() && c->ports_are_outputs()) {
1735 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 if (n_outputs().get(c->type()) == c->nchannels() && c->ports_are_inputs()) {
1753 connect_output_ports_to_bundle (c, this);
1756 } else if ((prop = node.property ("outputs")) != 0) {
1757 if (set_outputs (prop->value())) {
1758 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1763 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1765 if ((*i)->name() == "InputBundle") {
1766 XMLProperty const * prop = (*i)->property ("name");
1768 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1770 connect_input_ports_to_bundle (b, this);
1774 } else if ((*i)->name() == "OutputBundle") {
1775 XMLProperty const * prop = (*i)->property ("name");
1777 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1779 connect_output_ports_to_bundle (b, this);
1789 IO::set_inputs (const string& str)
1791 vector<string> ports;
1796 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1800 // FIXME: audio-only
1801 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1805 string::size_type start, end, ostart;
1812 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1815 if ((end = str.find_first_of ('}', start)) == string::npos) {
1816 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1820 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1821 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1827 for (int x = 0; x < n; ++x) {
1828 connect_input (input (i), ports[x], this);
1840 IO::set_outputs (const string& str)
1842 vector<string> ports;
1847 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1851 // FIXME: audio-only
1852 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1856 string::size_type start, end, ostart;
1863 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1866 if ((end = str.find_first_of ('}', start)) == string::npos) {
1867 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1871 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1872 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1878 for (int x = 0; x < n; ++x) {
1879 connect_output (output (i), ports[x], this);
1891 IO::parse_io_string (const string& str, vector<string>& ports)
1893 string::size_type pos, opos;
1895 if (str.length() == 0) {
1904 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1905 ports.push_back (str.substr (opos, pos - opos));
1909 if (opos < str.length()) {
1910 ports.push_back (str.substr(opos));
1913 return ports.size();
1917 IO::parse_gain_string (const string& str, vector<string>& ports)
1919 string::size_type pos, opos;
1925 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1926 ports.push_back (str.substr (opos, pos - opos));
1930 if (opos < str.length()) {
1931 ports.push_back (str.substr(opos));
1934 return ports.size();
1938 IO::set_name (const string& requested_name)
1940 if (requested_name == _name) {
1946 if ( (rt = dynamic_cast<Route *>(this))) {
1947 name = Route::ensure_track_or_route_name(requested_name, _session);
1949 name = requested_name;
1953 /* replace all colons in the name. i wish we didn't have to do this */
1955 if (replace_all (name, ":", "-")) {
1956 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1959 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1960 string current_name = i->name();
1961 current_name.replace (current_name.find (_name), _name.length(), name);
1962 i->set_name (current_name);
1965 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1966 string current_name = i->name();
1967 current_name.replace (current_name.find (_name), _name.length(), name);
1968 i->set_name (current_name);
1971 bool const r = SessionObject::set_name(name);
1973 setup_bundles_for_inputs_and_outputs ();
1979 IO::set_input_minimum (ChanCount n)
1985 IO::set_input_maximum (ChanCount n)
1991 IO::set_output_minimum (ChanCount n)
1993 _output_minimum = n;
1997 IO::set_output_maximum (ChanCount n)
1999 _output_maximum = n;
2003 IO::set_port_latency (nframes_t nframes)
2005 Glib::Mutex::Lock lm (io_lock);
2007 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2008 i->set_latency (nframes);
2013 IO::output_latency () const
2015 nframes_t max_latency;
2020 /* io lock not taken - must be protected by other means */
2022 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2023 if ((latency = i->total_latency ()) > max_latency) {
2024 max_latency = latency;
2032 IO::input_latency () const
2034 nframes_t max_latency;
2039 /* io lock not taken - must be protected by other means */
2041 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2042 if ((latency = i->total_latency ()) > max_latency) {
2043 max_latency = latency;
2051 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2054 BLOCK_PROCESS_CALLBACK ();
2055 Glib::Mutex::Lock lm2 (io_lock);
2057 c->connect (_bundle_for_inputs, _session.engine());
2059 /* If this is a UserBundle, make a note of what we've done */
2061 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2064 /* See if we already know about this one */
2065 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2066 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2070 if (i == _bundles_connected_to_inputs.end()) {
2071 /* We don't, so make a note */
2072 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2077 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2082 IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2085 BLOCK_PROCESS_CALLBACK ();
2086 Glib::Mutex::Lock lm2 (io_lock);
2088 c->disconnect (_bundle_for_inputs, _session.engine());
2090 /* If this is a UserBundle, make a note of what we've done */
2092 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2095 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2096 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2100 if (i != _bundles_connected_to_inputs.end()) {
2101 _bundles_connected_to_inputs.erase (i);
2106 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2111 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2114 BLOCK_PROCESS_CALLBACK ();
2115 Glib::Mutex::Lock lm2 (io_lock);
2117 c->connect (_bundle_for_outputs, _session.engine());
2119 /* If this is a UserBundle, make a note of what we've done */
2121 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2124 /* See if we already know about this one */
2125 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2126 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2130 if (i == _bundles_connected_to_outputs.end()) {
2131 /* We don't, so make a note */
2132 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2137 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2143 IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2146 BLOCK_PROCESS_CALLBACK ();
2147 Glib::Mutex::Lock lm2 (io_lock);
2149 c->disconnect (_bundle_for_outputs, _session.engine());
2151 /* If this is a UserBundle, make a note of what we've done */
2153 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2156 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2157 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2161 if (i != _bundles_connected_to_outputs.end()) {
2162 _bundles_connected_to_outputs.erase (i);
2167 output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2173 IO::disable_connecting ()
2175 connecting_legal = false;
2180 IO::enable_connecting ()
2182 connecting_legal = true;
2183 return ConnectingLegal ();
2187 IO::disable_ports ()
2189 ports_legal = false;
2197 return PortsLegal ();
2201 IO::disable_panners (void)
2203 panners_legal = false;
2208 IO::reset_panners ()
2210 panners_legal = true;
2211 return PannersLegal ();
2215 IO::bundle_changed (Bundle::Change c)
2218 // connect_input_ports_to_bundle (_input_bundle, this);
2222 IO::GainControl::set_value (float val)
2224 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2225 if (val > 1.99526231f)
2228 _io->set_gain (val, this);
2230 AutomationControl::set_value(val);
2234 IO::GainControl::get_value (void) const
2236 return AutomationControl::get_value();
2240 IO::setup_peak_meters()
2242 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2243 _meter->configure_io (max_streams, max_streams);
2247 Update the peak meters.
2249 The meter signal lock is taken to prevent modification of the
2250 Meter signal while updating the meters, taking the meter signal
2251 lock prior to taking the io_lock ensures that all IO will remain
2252 valid while metering.
2257 Glib::Mutex::Lock guard (m_meter_signal_lock);
2258 Meter(); /* EMIT SIGNAL */
2264 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2266 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2271 IO::clear_automation ()
2273 data().clear_controls (); // clears gain automation
2274 _panner->data().clear_controls ();
2278 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2280 // XXX: would be nice to get rid of this special hack
2282 if (param.type() == GainAutomation) {
2284 bool changed = false;
2287 Glib::Mutex::Lock lm (control_lock());
2289 boost::shared_ptr<AutomationList> gain_auto
2290 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2292 if (state != gain_auto->automation_state()) {
2294 _last_automation_snapshot = 0;
2295 gain_auto->set_automation_state (state);
2298 // FIXME: shouldn't this use Curve?
2299 set_gain (gain_auto->eval (_session.transport_frame()), this);
2305 _session.set_dirty ();
2309 AutomatableControls::set_parameter_automation_state(param, state);
2314 IO::inc_gain (gain_t factor, void *src)
2316 float desired_gain = _gain_control->user_float();
2317 if (desired_gain == 0.0f) {
2318 set_gain (0.000001f + (0.000001f * factor), src);
2320 set_gain (desired_gain + (desired_gain * factor), src);
2325 IO::set_gain (gain_t val, void *src)
2327 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2328 if (val > 1.99526231f) {
2332 //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2334 if (src != _gain_control.get()) {
2335 _gain_control->set_value(val);
2336 // bit twisty, this will come back and call us again
2337 // (this keeps control in sync with reality)
2342 Glib::Mutex::Lock dm (declick_lock);
2343 _gain_control->set_float(val, false);
2346 if (_session.transport_stopped()) {
2351 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2352 _gain_control->list()->add (_session.transport_frame(), val);
2357 _session.set_dirty();
2361 IO::start_pan_touch (uint32_t which)
2363 if (which < _panner->npanners()) {
2364 (*_panner).pan_control(which)->start_touch();
2369 IO::end_pan_touch (uint32_t which)
2371 if (which < _panner->npanners()) {
2372 (*_panner).pan_control(which)->stop_touch();
2378 IO::automation_snapshot (nframes_t now, bool force)
2380 AutomatableControls::automation_snapshot (now, force);
2381 // XXX: This seems to be wrong.
2382 // drobilla: shouldnt automation_snapshot for panner be called
2383 // "automagically" because its an Automatable now ?
2385 // we could dump this whole method then. <3
2387 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2388 _panner->automation_snapshot (now, force);
2391 _panner->automation_snapshot (now, force);
2392 _last_automation_snapshot = now;
2396 IO::transport_stopped (nframes_t frame)
2398 _gain_control->list()->reposition_for_rt_add (frame);
2400 if (_gain_control->automation_state() != Off) {
2402 /* the src=0 condition is a special signal to not propagate
2403 automation gain changes into the mix group when locating.
2406 // FIXME: shouldn't this use Curve?
2407 set_gain (_gain_control->list()->eval (frame), 0);
2410 _panner->transport_stopped (frame);
2414 IO::build_legal_port_name (DataType type, bool in)
2416 const int name_size = jack_port_name_size();
2421 if (type == DataType::AUDIO) {
2422 suffix = _("audio");
2423 } else if (type == DataType::MIDI) {
2426 throw unknown_type();
2431 maxports = _input_maximum.get(type);
2433 suffix += _("_out");
2434 maxports = _output_maximum.get(type);
2437 if (maxports == 1) {
2438 // allow space for the slash + the suffix
2439 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2440 char buf[name_size+1];
2441 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2442 return string (buf);
2445 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2447 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2449 char buf1[name_size+1];
2450 char buf2[name_size+1];
2452 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2457 port_number = find_input_port_hole (buf1);
2459 port_number = find_output_port_hole (buf1);
2462 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2464 return string (buf2);
2468 IO::find_input_port_hole (const char* base)
2470 /* CALLER MUST HOLD IO LOCK */
2474 if (_inputs.empty()) {
2478 /* we only allow up to 4 characters for the port number
2481 for (n = 1; n < 9999; ++n) {
2482 char buf[jack_port_name_size()];
2483 PortSet::iterator i = _inputs.begin();
2485 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2487 for ( ; i != _inputs.end(); ++i) {
2488 if (i->name() == buf) {
2493 if (i == _inputs.end()) {
2501 IO::find_output_port_hole (const char* base)
2503 /* CALLER MUST HOLD IO LOCK */
2507 if (_outputs.empty()) {
2511 /* we only allow up to 4 characters for the port number
2514 for (n = 1; n < 9999; ++n) {
2515 char buf[jack_port_name_size()];
2516 PortSet::iterator i = _outputs.begin();
2518 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2520 for ( ; i != _outputs.end(); ++i) {
2521 if (i->name() == buf) {
2526 if (i == _outputs.end()) {
2535 IO::set_active (bool yn)
2538 active_changed(); /* EMIT SIGNAL */
2542 IO::audio_input(uint32_t n) const
2544 return dynamic_cast<AudioPort*>(input(n));
2548 IO::audio_output(uint32_t n) const
2550 return dynamic_cast<AudioPort*>(output(n));
2554 IO::midi_input(uint32_t n) const
2556 return dynamic_cast<MidiPort*>(input(n));
2560 IO::midi_output(uint32_t n) const
2562 return dynamic_cast<MidiPort*>(output(n));
2566 IO::set_phase_invert (bool yn, void *src)
2568 if (_phase_invert != yn) {
2570 // phase_invert_changed (src); /* EMIT SIGNAL */
2575 IO::set_denormal_protection (bool yn, void *src)
2577 if (_denormal_protection != yn) {
2578 _denormal_protection = yn;
2579 // denormal_protection_changed (src); /* EMIT SIGNAL */
2584 IO::update_port_total_latencies ()
2586 /* io_lock, not taken: function must be called from Session::process() calltree */
2588 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2589 _session.engine().update_total_latency (*i);
2592 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2593 _session.engine().update_total_latency (*i);
2599 * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
2603 IO::setup_bundles_for_inputs_and_outputs ()
2605 setup_bundle_for_inputs ();
2606 setup_bundle_for_outputs ();
2611 IO::setup_bundle_for_inputs ()
2615 if (!_bundle_for_inputs) {
2616 _bundle_for_inputs.reset (new Bundle (true));
2619 _bundle_for_inputs->suspend_signals ();
2621 _bundle_for_inputs->set_type (default_type ());
2623 _bundle_for_inputs->remove_channels ();
2625 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2626 _bundle_for_inputs->set_name (buf);
2627 uint32_t const ni = inputs().num_ports();
2628 for (uint32_t i = 0; i < ni; ++i) {
2629 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2630 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2633 _bundle_for_inputs->resume_signals ();
2638 IO::setup_bundle_for_outputs ()
2642 if (!_bundle_for_outputs) {
2643 _bundle_for_outputs.reset (new Bundle (false));
2646 _bundle_for_outputs->suspend_signals ();
2648 _bundle_for_outputs->set_type (default_type ());
2650 _bundle_for_outputs->remove_channels ();
2652 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2653 _bundle_for_outputs->set_name (buf);
2654 uint32_t const no = outputs().num_ports();
2655 for (uint32_t i = 0; i < no; ++i) {
2656 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2657 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2660 _bundle_for_outputs->resume_signals ();
2664 /** @return Bundles connected to our inputs */
2666 IO::bundles_connected_to_inputs ()
2671 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2672 bundles.push_back (i->bundle);
2675 /* Session bundles */
2676 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2677 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2678 if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
2679 bundles.push_back (*i);
2684 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2685 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2686 if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
2687 bundles.push_back ((*i)->bundle_for_outputs());
2695 /* @return Bundles connected to our outputs */
2697 IO::bundles_connected_to_outputs ()
2702 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2703 bundles.push_back (i->bundle);
2706 /* Session bundles */
2707 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2708 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2709 if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
2710 bundles.push_back (*i);
2715 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2716 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2717 if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
2718 bundles.push_back ((*i)->bundle_for_inputs());
2726 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2729 changed = b->Changed.connect (
2730 sigc::mem_fun (*io, &IO::bundle_changed)
2735 IO::prepare_inputs (nframes_t nframes)
2737 /* io_lock, not taken: function must be called from Session::process() calltree */
2741 IO::flush_outputs (nframes_t nframes)
2743 /* io_lock, not taken: function must be called from Session::process() calltree */
2745 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2746 (*i).flush_buffers (nframes, _output_offset);
2751 IO::bundle_channel_name (uint32_t c, uint32_t n) const
2759 return c == 0 ? _("L") : _("R");
2761 snprintf (buf, sizeof(buf), _("%d"), (c + 1));
2769 IO::name_from_state (const XMLNode& node)
2771 const XMLProperty* prop;
2773 if ((prop = node.property ("name")) != 0) {
2774 return prop->value();
2781 IO::set_name_in_state (XMLNode& node, const string& new_name)
2783 const XMLProperty* prop;
2785 if ((prop = node.property ("name")) != 0) {
2786 node.add_property ("name", new_name);
2791 IO::cycle_start (nframes_t nframes)
2797 IO::increment_output_offset (nframes_t n)
2799 _output_offset += n;