2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
28 #include <glibmm/thread.h>
30 #include <pbd/xml++.h>
31 #include <pbd/replace_all.h>
32 #include <pbd/unknown_type.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/io.h>
36 #include <ardour/route.h>
37 #include <ardour/port.h>
38 #include <ardour/audio_port.h>
39 #include <ardour/midi_port.h>
40 #include <ardour/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/buffer_set.h>
44 #include <ardour/meter.h>
45 #include <ardour/amp.h>
46 #include <ardour/user_bundle.h>
53 A bug in OS X's cmath that causes isnan() and isinf() to be
54 "undeclared". the following works around that
57 #if defined(__APPLE__) && defined(__MACH__)
58 extern "C" int isnan (double);
59 extern "C" int isinf (double);
62 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
65 using namespace ARDOUR;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,ChanCount> IO::PortCountChanged;
77 sigc::signal<int> IO::PortsCreated;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
100 /** @param default_type The type of port that will be created by ensure_io
101 * and friends if no type is explicitly requested (to avoid breakage).
103 IO::IO (Session& s, const string& name,
104 int input_min, int input_max, int output_min, int output_max,
105 DataType default_type, bool public_ports)
106 : SessionObject(s, name),
107 AutomatableControls (s),
108 _output_buffers (new BufferSet()),
110 _default_type (default_type),
111 _public_ports (public_ports),
112 _input_minimum (ChanCount::ZERO),
113 _input_maximum (ChanCount::INFINITE),
114 _output_minimum (ChanCount::ZERO),
115 _output_maximum (ChanCount::INFINITE)
117 _panner = new Panner (name, _session);
118 _meter = new PeakMeter (_session);
121 _input_minimum = ChanCount(_default_type, input_min);
123 if (input_max >= 0) {
124 _input_maximum = ChanCount(_default_type, input_max);
126 if (output_min > 0) {
127 _output_minimum = ChanCount(_default_type, output_min);
129 if (output_max >= 0) {
130 _output_maximum = ChanCount(_default_type, output_max);
135 pending_state_node = 0;
136 no_panner_reset = false;
137 _phase_invert = false;
140 boost::shared_ptr<AutomationList> gl(
141 new AutomationList(Evoral::Parameter(GainAutomation)));
143 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
145 add_control(_gain_control);
147 apply_gain_automation = false;
150 // IO::Meter is emitted from another thread so the
151 // Meter signal must be protected.
152 Glib::Mutex::Lock guard (m_meter_signal_lock);
153 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
156 // Connect to our own PortCountChanged signal to connect output buffers
157 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
159 _session.add_controllable (_gain_control);
161 create_bundles_for_inputs_and_outputs ();
164 IO::IO (Session& s, const XMLNode& node, DataType dt)
165 : SessionObject(s, "unnamed io"),
166 AutomatableControls (s),
167 _output_buffers (new BufferSet()),
171 _meter = new PeakMeter (_session);
172 _public_ports = true; // XXX get this from node
175 no_panner_reset = false;
179 apply_gain_automation = false;
181 boost::shared_ptr<AutomationList> gl(
182 new AutomationList(Evoral::Parameter(GainAutomation)));
184 _gain_control = boost::shared_ptr<GainControl>(
185 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
187 add_control(_gain_control);
192 // IO::Meter is emitted from another thread so the
193 // Meter signal must be protected.
194 Glib::Mutex::Lock guard (m_meter_signal_lock);
195 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
198 // Connect to our own PortCountChanged signal to connect output buffers
199 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
201 _session.add_controllable (_gain_control);
203 create_bundles_for_inputs_and_outputs ();
208 Glib::Mutex::Lock guard (m_meter_signal_lock);
209 Glib::Mutex::Lock lm (io_lock);
211 BLOCK_PROCESS_CALLBACK ();
213 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
214 _session.engine().unregister_port (*i);
217 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
218 _session.engine().unregister_port (*i);
221 m_meter_connection.disconnect();
225 delete _output_buffers;
229 IO::silence (nframes_t nframes, nframes_t offset)
231 /* io_lock, not taken: function must be called from Session::process() calltree */
233 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
234 i->get_buffer(nframes,offset).silence (nframes, offset);
238 /** Deliver bufs to the IO's output ports
240 * This function should automatically do whatever it necessary to correctly deliver bufs
241 * to the outputs, eg applying gain or pan or whatever else needs to be done.
244 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
246 // FIXME: type specific code doesn't actually need to be here, it will go away in time
248 /* ********** AUDIO ********** */
250 // Apply gain if gain automation isn't playing
251 if ( ! apply_gain_automation) {
253 gain_t dg = _gain; // desired gain
256 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
264 if (dg != _gain || dg != 1.0) {
265 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
270 // Use the panner to distribute audio to output port buffers
271 if( _panner && _panner->npanners() && !_panner->bypassed()) {
272 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
274 const DataType type = DataType::AUDIO;
276 // Copy any audio 1:1 to outputs
278 BufferSet::iterator o = output_buffers().begin(type);
279 BufferSet::iterator i = bufs.begin(type);
280 BufferSet::iterator prev = i;
282 while (i != bufs.end(type) && o != output_buffers().end (type)) {
283 o->read_from(*i, nframes, offset);
289 /* extra outputs get a copy of the last buffer */
291 while (o != output_buffers().end(type)) {
292 o->read_from(*prev, nframes, offset);
297 /* ********** MIDI ********** */
299 // No MIDI, we're done here
300 if (bufs.count().n_midi() == 0 || output_buffers().count().n_midi () == 0) {
304 const DataType type = DataType::MIDI;
306 // Copy any MIDI 1:1 to outputs
307 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
308 BufferSet::iterator o = output_buffers().begin(type);
309 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
310 o->read_from(*i, nframes, offset);
315 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
317 assert(outs.available() >= n_inputs());
319 if (n_inputs() == ChanCount::ZERO)
322 outs.set_count(n_inputs());
324 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
326 BufferSet::iterator o = outs.begin(*t);
327 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
328 o->read_from(i->get_buffer(nframes,offset), nframes, offset);
335 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
336 nframes_t nframes, nframes_t offset)
338 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
340 collect_input (bufs, nframes, offset);
342 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
347 IO::check_bundles_connected_to_inputs ()
349 check_bundles (_bundles_connected_to_inputs, inputs());
353 IO::check_bundles_connected_to_outputs ()
355 check_bundles (_bundles_connected_to_outputs, outputs());
359 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
361 std::vector<UserBundleInfo> new_list;
363 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
365 uint32_t const N = i->bundle->nchannels ();
367 if (ports.num_ports (default_type()) < N) {
373 for (uint32_t j = 0; j < N; ++j) {
374 /* Every port on bundle channel j must be connected to our input j */
375 Bundle::PortList const pl = i->bundle->channel_ports (j);
376 for (uint32_t k = 0; k < pl.size(); ++k) {
377 if (ports.port(j)->connected_to (pl[k]) == false) {
389 new_list.push_back (*i);
391 i->configuration_changed.disconnect ();
392 i->ports_changed.disconnect ();
401 IO::disconnect_input (Port* our_port, string other_port, void* src)
403 if (other_port.length() == 0 || our_port == 0) {
408 BLOCK_PROCESS_CALLBACK ();
411 Glib::Mutex::Lock lm (io_lock);
413 /* check that our_port is really one of ours */
415 if ( ! _inputs.contains(our_port)) {
419 /* disconnect it from the source */
421 if (_session.engine().disconnect (other_port, our_port->name())) {
422 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
426 check_bundles_connected_to_inputs ();
430 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
431 _session.set_dirty ();
437 IO::connect_input (Port* our_port, string other_port, void* src)
439 if (other_port.length() == 0 || our_port == 0) {
444 BLOCK_PROCESS_CALLBACK ();
447 Glib::Mutex::Lock lm (io_lock);
449 /* check that our_port is really one of ours */
451 if ( ! _inputs.contains(our_port) ) {
455 /* connect it to the source */
457 if (_session.engine().connect (other_port, our_port->name())) {
463 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
464 _session.set_dirty ();
469 IO::disconnect_output (Port* our_port, string other_port, void* src)
471 if (other_port.length() == 0 || our_port == 0) {
476 BLOCK_PROCESS_CALLBACK ();
479 Glib::Mutex::Lock lm (io_lock);
481 /* check that our_port is really one of ours */
483 if ( ! _outputs.contains(our_port) ) {
487 /* disconnect it from the destination */
489 if (_session.engine().disconnect (our_port->name(), other_port)) {
490 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
494 check_bundles_connected_to_outputs ();
498 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
499 _session.set_dirty ();
504 IO::connect_output (Port* our_port, string other_port, void* src)
506 if (other_port.length() == 0 || our_port == 0) {
511 BLOCK_PROCESS_CALLBACK ();
515 Glib::Mutex::Lock lm (io_lock);
517 /* check that our_port is really one of ours */
519 if ( ! _outputs.contains(our_port) ) {
523 /* connect it to the destination */
525 if (_session.engine().connect (our_port->name(), other_port)) {
531 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
532 _session.set_dirty ();
537 IO::set_input (Port* other_port, void* src)
539 /* this removes all but one ports, and connects that one port
540 to the specified source.
543 if (_input_minimum.n_total() > 1) {
544 /* sorry, you can't do this */
548 if (other_port == 0) {
549 if (_input_minimum == ChanCount::ZERO) {
550 return ensure_inputs (ChanCount::ZERO, false, true, src);
556 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
560 return connect_input (_inputs.port(0), other_port->name(), src);
564 IO::remove_output_port (Port* port, void* src)
566 IOChange change (NoChange);
569 BLOCK_PROCESS_CALLBACK ();
573 Glib::Mutex::Lock lm (io_lock);
575 if (n_outputs() <= _output_minimum) {
576 /* sorry, you can't do this */
580 if (_outputs.remove(port)) {
581 change = IOChange (change|ConfigurationChanged);
583 if (port->connected()) {
584 change = IOChange (change|ConnectionsChanged);
587 _session.engine().unregister_port (*port);
588 check_bundles_connected_to_outputs ();
590 setup_peak_meters ();
595 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
598 if (change == ConfigurationChanged) {
599 setup_bundles_for_inputs_and_outputs ();
602 if (change != NoChange) {
603 output_changed (change, src);
604 _session.set_dirty ();
611 /** Add an output port.
613 * @param destination Name of input port to connect new port to.
614 * @param src Source for emitted ConfigurationChanged signal.
615 * @param type Data type of port. Default value (NIL) will use this IO's default type.
618 IO::add_output_port (string destination, void* src, DataType type)
622 if (type == DataType::NIL)
623 type = _default_type;
626 BLOCK_PROCESS_CALLBACK ();
630 Glib::Mutex::Lock lm (io_lock);
632 if (n_outputs() >= _output_maximum) {
636 /* Create a new output port */
638 string portname = build_legal_port_name (type, false);
640 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
641 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
645 _outputs.add (our_port);
646 setup_peak_meters ();
650 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
653 if (destination.length()) {
654 if (_session.engine().connect (our_port->name(), destination)) {
659 // pan_changed (src); /* EMIT SIGNAL */
660 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
661 setup_bundles_for_inputs_and_outputs ();
662 _session.set_dirty ();
668 IO::remove_input_port (Port* port, void* src)
670 IOChange change (NoChange);
673 BLOCK_PROCESS_CALLBACK ();
677 Glib::Mutex::Lock lm (io_lock);
679 if (n_inputs() <= _input_minimum) {
680 /* sorry, you can't do this */
684 if (_inputs.remove(port)) {
685 change = IOChange (change|ConfigurationChanged);
687 if (port->connected()) {
688 change = IOChange (change|ConnectionsChanged);
691 _session.engine().unregister_port (*port);
692 check_bundles_connected_to_inputs ();
694 setup_peak_meters ();
699 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
702 if (change == ConfigurationChanged) {
703 setup_bundles_for_inputs_and_outputs ();
706 if (change != NoChange) {
707 input_changed (change, src);
708 _session.set_dirty ();
716 /** Add an input port.
718 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
719 * @param destination Name of input port to connect new port to.
720 * @param src Source for emitted ConfigurationChanged signal.
723 IO::add_input_port (string source, void* src, DataType type)
727 if (type == DataType::NIL)
728 type = _default_type;
731 BLOCK_PROCESS_CALLBACK ();
734 Glib::Mutex::Lock lm (io_lock);
736 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
740 /* Create a new input port */
742 string portname = build_legal_port_name (type, true);
744 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
745 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
749 _inputs.add (our_port);
750 setup_peak_meters ();
754 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
757 if (source.length()) {
759 if (_session.engine().connect (source, our_port->name())) {
764 // pan_changed (src); /* EMIT SIGNAL */
765 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
766 setup_bundles_for_inputs_and_outputs ();
767 _session.set_dirty ();
773 IO::disconnect_inputs (void* src)
776 BLOCK_PROCESS_CALLBACK ();
779 Glib::Mutex::Lock lm (io_lock);
781 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
782 _session.engine().disconnect (*i);
785 check_bundles_connected_to_inputs ();
789 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
795 IO::disconnect_outputs (void* src)
798 BLOCK_PROCESS_CALLBACK ();
801 Glib::Mutex::Lock lm (io_lock);
803 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
804 _session.engine().disconnect (*i);
807 check_bundles_connected_to_outputs ();
811 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
812 _session.set_dirty ();
818 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
820 Port* input_port = 0;
821 bool changed = false;
824 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
826 const size_t n = count.get(*t);
828 /* remove unused ports */
829 for (size_t i = n_inputs().get(*t); i > n; --i) {
830 input_port = _inputs.port(*t, i-1);
833 _inputs.remove(input_port);
834 _session.engine().unregister_port (*input_port);
839 /* create any necessary new ports */
840 while (n_inputs().get(*t) < n) {
842 string portname = build_legal_port_name (*t, true);
846 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
847 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
852 catch (AudioEngine::PortRegistrationFailure& err) {
853 setup_peak_meters ();
856 throw AudioEngine::PortRegistrationFailure();
859 _inputs.add (input_port);
865 check_bundles_connected_to_inputs ();
866 setup_peak_meters ();
868 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
869 _session.set_dirty ();
873 /* disconnect all existing ports so that we get a fresh start */
874 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
875 _session.engine().disconnect (*i);
882 /** Attach output_buffers to port buffers.
884 * Connected to IO's own PortCountChanged signal.
887 IO::attach_buffers(ChanCount ignored)
889 _output_buffers->attach_buffers(_outputs);
893 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
895 bool in_changed = false;
896 bool out_changed = false;
897 bool need_pan_reset = false;
899 in = min (_input_maximum, in);
901 out = min (_output_maximum, out);
903 if (in == n_inputs() && out == n_outputs() && !clear) {
908 BLOCK_PROCESS_CALLBACK ();
909 Glib::Mutex::Lock lm (io_lock);
913 if (n_outputs() != out) {
914 need_pan_reset = true;
917 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
919 const size_t nin = in.get(*t);
920 const size_t nout = out.get(*t);
922 Port* output_port = 0;
923 Port* input_port = 0;
925 /* remove unused output ports */
926 for (size_t i = n_outputs().get(*t); i > nout; --i) {
927 output_port = _outputs.port(*t, i-1);
930 _outputs.remove(output_port);
931 _session.engine().unregister_port (*output_port);
936 /* remove unused input ports */
937 for (size_t i = n_inputs().get(*t); i > nin; --i) {
938 input_port = _inputs.port(*t, i-1);
941 _inputs.remove(input_port);
942 _session.engine().unregister_port (*input_port);
947 /* create any necessary new input ports */
949 while (n_inputs().get(*t) < nin) {
951 string portname = build_legal_port_name (*t, true);
954 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
955 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
960 catch (AudioEngine::PortRegistrationFailure& err) {
961 setup_peak_meters ();
964 throw AudioEngine::PortRegistrationFailure();
971 /* create any necessary new output ports */
973 while (n_outputs().get(*t) < nout) {
975 string portname = build_legal_port_name (*t, false);
978 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
979 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
984 catch (AudioEngine::PortRegistrationFailure& err) {
985 setup_peak_meters ();
988 throw AudioEngine::PortRegistrationFailure ();
998 /* disconnect all existing ports so that we get a fresh start */
1000 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1001 _session.engine().disconnect (*i);
1004 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1005 _session.engine().disconnect (*i);
1009 if (in_changed || out_changed) {
1010 setup_peak_meters ();
1016 check_bundles_connected_to_outputs ();
1017 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1021 check_bundles_connected_to_inputs ();
1022 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1025 if (in_changed || out_changed) {
1026 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1027 setup_bundles_for_inputs_and_outputs ();
1028 _session.set_dirty ();
1035 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1037 bool changed = false;
1039 count = min (_input_maximum, count);
1041 if (count == n_inputs() && !clear) {
1046 BLOCK_PROCESS_CALLBACK ();
1047 Glib::Mutex::Lock im (io_lock);
1048 changed = ensure_inputs_locked (count, clear, src);
1050 changed = ensure_inputs_locked (count, clear, src);
1054 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1055 setup_bundles_for_inputs_and_outputs ();
1056 _session.set_dirty ();
1062 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1064 Port* output_port = 0;
1065 bool changed = false;
1066 bool need_pan_reset = false;
1068 if (n_outputs() != count) {
1069 need_pan_reset = true;
1072 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1074 const size_t n = count.get(*t);
1076 /* remove unused ports */
1077 for (size_t i = n_outputs().get(*t); i > n; --i) {
1078 output_port = _outputs.port(*t, i-1);
1080 assert(output_port);
1081 _outputs.remove(output_port);
1082 _session.engine().unregister_port (*output_port);
1087 /* create any necessary new ports */
1088 while (n_outputs().get(*t) < n) {
1090 string portname = build_legal_port_name (*t, false);
1092 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1093 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1097 _outputs.add (output_port);
1099 setup_peak_meters ();
1101 if (need_pan_reset) {
1108 check_bundles_connected_to_outputs ();
1109 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1110 _session.set_dirty ();
1114 /* disconnect all existing ports so that we get a fresh start */
1115 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1116 _session.engine().disconnect (*i);
1124 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1126 bool changed = false;
1128 if (_output_maximum < ChanCount::INFINITE) {
1129 count = min (_output_maximum, count);
1130 if (count == n_outputs() && !clear) {
1135 /* XXX caller should hold io_lock, but generally doesn't */
1138 BLOCK_PROCESS_CALLBACK ();
1139 Glib::Mutex::Lock im (io_lock);
1140 changed = ensure_outputs_locked (count, clear, src);
1142 changed = ensure_outputs_locked (count, clear, src);
1146 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1147 setup_bundles_for_inputs_and_outputs ();
1154 IO::effective_gain () const
1156 if (_gain_control->automation_playback()) {
1157 return _gain_control->get_value();
1159 return _desired_gain;
1166 if (panners_legal) {
1167 if (!no_panner_reset) {
1168 _panner->reset (n_outputs().n_audio(), pans_required());
1171 panner_legal_c.disconnect ();
1172 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1177 IO::panners_became_legal ()
1179 _panner->reset (n_outputs().n_audio(), pans_required());
1180 _panner->load (); // automation
1181 panner_legal_c.disconnect ();
1186 IO::defer_pan_reset ()
1188 no_panner_reset = true;
1192 IO::allow_pan_reset ()
1194 no_panner_reset = false;
1200 IO::get_state (void)
1202 return state (true);
1206 IO::state (bool full_state)
1208 XMLNode* node = new XMLNode (state_node_name);
1211 vector<string>::iterator ci;
1213 LocaleGuard lg (X_("POSIX"));
1214 Glib::Mutex::Lock lm (io_lock);
1216 node->add_property("name", _name);
1217 id().print (buf, sizeof (buf));
1218 node->add_property("id", buf);
1221 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1222 i != _bundles_connected_to_inputs.end();
1226 XMLNode* n = new XMLNode ("InputBundle");
1227 n->add_property ("name", i->bundle->name ());
1228 node->add_child_nocopy (*n);
1232 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1233 i != _bundles_connected_to_outputs.end();
1237 XMLNode* n = new XMLNode ("OutputBundle");
1238 n->add_property ("name", i->bundle->name ());
1239 node->add_child_nocopy (*n);
1244 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1246 vector<string> connections;
1248 if (i->get_connections (connections)) {
1252 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1257 /* if its a connection to our own port,
1258 return only the port name, not the
1259 whole thing. this allows connections
1260 to be re-established even when our
1261 client name is different.
1264 str += _session.engine().make_port_name_relative (*ci);
1274 node->add_property ("inputs", str);
1278 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1280 vector<string> connections;
1282 if (i->get_connections (connections)) {
1286 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1291 str += _session.engine().make_port_name_relative (*ci);
1301 node->add_property ("outputs", str);
1303 node->add_child_nocopy (_panner->state (full_state));
1304 node->add_child_nocopy (_gain_control->get_state ());
1306 snprintf (buf, sizeof(buf), "%2.12f", gain());
1307 node->add_property ("gain", buf);
1309 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1313 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1314 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1316 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1318 node->add_property ("iolimits", buf);
1323 node->add_child_nocopy (get_automation_state());
1329 IO::set_state (const XMLNode& node)
1331 const XMLProperty* prop;
1332 XMLNodeConstIterator iter;
1333 LocaleGuard lg (X_("POSIX"));
1335 /* force use of non-localized representation of decimal point,
1336 since we use it a lot in XML files and so forth.
1339 if (node.name() != state_node_name) {
1340 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1344 if ((prop = node.property ("name")) != 0) {
1345 _name = prop->value();
1346 /* used to set panner name with this, but no more */
1349 if ((prop = node.property ("id")) != 0) {
1350 _id = prop->value ();
1358 if ((prop = node.property ("iolimits")) != 0) {
1359 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1360 &in_min, &in_max, &out_min, &out_max);
1362 /* Correct for the difference between the way we write things to session files and the
1363 way things are described by ChanCount; see comments in io.h about what the different
1364 ChanCount values mean. */
1367 _input_minimum = ChanCount::ZERO;
1369 _input_minimum = ChanCount (_default_type, in_min);
1373 _input_maximum = ChanCount::INFINITE;
1375 _input_maximum = ChanCount (_default_type, in_max);
1379 _output_minimum = ChanCount::ZERO;
1381 _output_minimum = ChanCount (_default_type, out_min);
1385 _output_maximum = ChanCount::INFINITE;
1387 _output_maximum = ChanCount (_default_type, out_max);
1391 if ((prop = node.property ("gain")) != 0) {
1392 set_gain (atof (prop->value().c_str()), this);
1393 _gain = _desired_gain;
1396 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1397 /* old school automation handling */
1400 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1402 // Old school Panner.
1403 if ((*iter)->name() == "Panner") {
1405 _panner = new Panner (_name, _session);
1407 _panner->set_state (**iter);
1410 if ((*iter)->name() == "Processor") {
1411 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1413 _panner = new Panner (_name, _session);
1415 _panner->set_state (**iter);
1419 if ((*iter)->name() == X_("Automation")) {
1421 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1424 if ((*iter)->name() == X_("controllable")) {
1425 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1426 _gain_control->set_state (**iter);
1433 if (create_ports (node)) {
1439 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1443 _panner = new Panner( _name, _session );
1444 if (panners_legal) {
1447 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1450 if (connecting_legal) {
1452 if (make_connections (node)) {
1458 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1461 if (!ports_legal || !connecting_legal) {
1462 pending_state_node = new XMLNode (node);
1469 IO::load_automation (string path)
1474 uint32_t linecnt = 0;
1476 LocaleGuard lg (X_("POSIX"));
1478 fullpath = Glib::build_filename(_session.automation_dir(), path);
1480 in.open (fullpath.c_str());
1483 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1485 in.open (fullpath.c_str());
1488 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1493 clear_automation ();
1495 while (in.getline (line, sizeof(line), '\n')) {
1500 if (++linecnt == 1) {
1501 if (memcmp (line, "version", 7) == 0) {
1502 if (sscanf (line, "version %f", &version) != 1) {
1503 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1507 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1514 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1515 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1521 _gain_control->list()->fast_simple_add (when, value);
1531 /* older (pre-1.0) versions of ardour used this */
1535 warning << _("dubious automation event found (and ignored)") << endmsg;
1543 IO::connecting_became_legal ()
1547 if (pending_state_node == 0) {
1548 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1553 connection_legal_c.disconnect ();
1555 ret = make_connections (*pending_state_node);
1558 delete pending_state_node;
1559 pending_state_node = 0;
1565 IO::ports_became_legal ()
1569 if (pending_state_node == 0) {
1570 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1575 port_legal_c.disconnect ();
1577 ret = create_ports (*pending_state_node);
1579 if (connecting_legal) {
1580 delete pending_state_node;
1581 pending_state_node = 0;
1587 boost::shared_ptr<Bundle>
1588 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1590 static const string digits = "0123456789";
1592 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1595 int bundle_number, mask;
1596 string possible_name;
1597 bool stereo = false;
1598 string::size_type last_non_digit_pos;
1600 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1603 // find numeric suffix of desired name
1606 last_non_digit_pos = desired_name.find_last_not_of(digits);
1608 if (last_non_digit_pos != string::npos) {
1610 s << desired_name.substr(last_non_digit_pos);
1614 // see if it's a stereo connection e.g. "in 3+4"
1616 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1617 int left_bundle_number = 0;
1618 string::size_type left_last_non_digit_pos;
1620 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1622 if (left_last_non_digit_pos != string::npos) {
1624 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1625 s >> left_bundle_number;
1627 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1638 // find highest set bit
1640 while ((mask <= bundle_number) && (mask <<= 1));
1642 // "wrap" bundle number into largest possible power of 2
1647 if (bundle_number & mask) {
1648 bundle_number &= ~mask;
1651 s << default_name << " " << bundle_number + 1;
1654 s << "+" << bundle_number + 2;
1657 possible_name = s.str();
1659 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1666 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1669 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1680 IO::create_ports (const XMLNode& node)
1682 XMLProperty const * prop;
1683 uint32_t num_inputs = 0;
1684 uint32_t num_outputs = 0;
1686 if ((prop = node.property ("input-connection")) != 0) {
1688 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1694 num_inputs = c->nchannels();
1696 } else if ((prop = node.property ("inputs")) != 0) {
1698 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1701 if ((prop = node.property ("output-connection")) != 0) {
1703 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1709 num_outputs = c->nchannels ();
1711 } else if ((prop = node.property ("outputs")) != 0) {
1713 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1716 no_panner_reset = true;
1718 if (ensure_io (ChanCount (_default_type, num_inputs),
1719 ChanCount (_default_type, num_outputs),
1722 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1726 no_panner_reset = false;
1728 set_deferred_state ();
1736 IO::make_connections (const XMLNode& node)
1739 const XMLProperty* prop;
1741 if ((prop = node.property ("input-connection")) != 0) {
1742 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1748 connect_input_ports_to_bundle (c, this);
1750 } else if ((prop = node.property ("inputs")) != 0) {
1751 if (set_inputs (prop->value())) {
1752 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1757 if ((prop = node.property ("output-connection")) != 0) {
1758 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1764 connect_output_ports_to_bundle (c, this);
1766 } else if ((prop = node.property ("outputs")) != 0) {
1767 if (set_outputs (prop->value())) {
1768 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1773 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1775 if ((*i)->name() == "InputBundle") {
1776 XMLProperty const * prop = (*i)->property ("name");
1778 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1780 connect_input_ports_to_bundle (b, this);
1784 } else if ((*i)->name() == "OutputBundle") {
1785 XMLProperty const * prop = (*i)->property ("name");
1787 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1789 connect_output_ports_to_bundle (b, this);
1799 IO::set_inputs (const string& str)
1801 vector<string> ports;
1806 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1810 // FIXME: audio-only
1811 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1815 string::size_type start, end, ostart;
1822 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1825 if ((end = str.find_first_of ('}', start)) == string::npos) {
1826 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1830 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1831 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1837 for (int x = 0; x < n; ++x) {
1838 connect_input (input (i), ports[x], this);
1850 IO::set_outputs (const string& str)
1852 vector<string> ports;
1857 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1861 // FIXME: audio-only
1862 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1866 string::size_type start, end, ostart;
1873 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1876 if ((end = str.find_first_of ('}', start)) == string::npos) {
1877 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1881 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1882 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1888 for (int x = 0; x < n; ++x) {
1889 connect_output (output (i), ports[x], this);
1901 IO::parse_io_string (const string& str, vector<string>& ports)
1903 string::size_type pos, opos;
1905 if (str.length() == 0) {
1914 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1915 ports.push_back (str.substr (opos, pos - opos));
1919 if (opos < str.length()) {
1920 ports.push_back (str.substr(opos));
1923 return ports.size();
1927 IO::parse_gain_string (const string& str, vector<string>& ports)
1929 string::size_type pos, opos;
1935 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1936 ports.push_back (str.substr (opos, pos - opos));
1940 if (opos < str.length()) {
1941 ports.push_back (str.substr(opos));
1944 return ports.size();
1948 IO::set_name (const string& requested_name)
1950 if (requested_name == _name) {
1956 if ( (rt = dynamic_cast<Route *>(this))) {
1957 name = Route::ensure_track_or_route_name(requested_name, _session);
1959 name = requested_name;
1963 /* replace all colons in the name. i wish we didn't have to do this */
1965 if (replace_all (name, ":", "-")) {
1966 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1969 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1970 string current_name = i->name();
1971 current_name.replace (current_name.find (_name), _name.length(), name);
1972 i->set_name (current_name);
1975 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1976 string current_name = i->name();
1977 current_name.replace (current_name.find (_name), _name.length(), name);
1978 i->set_name (current_name);
1981 bool const r = SessionObject::set_name(name);
1983 setup_bundles_for_inputs_and_outputs ();
1989 IO::set_input_minimum (ChanCount n)
1995 IO::set_input_maximum (ChanCount n)
2001 IO::set_output_minimum (ChanCount n)
2003 _output_minimum = n;
2007 IO::set_output_maximum (ChanCount n)
2009 _output_maximum = n;
2013 IO::set_port_latency (nframes_t nframes)
2015 Glib::Mutex::Lock lm (io_lock);
2017 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2018 i->set_latency (nframes);
2023 IO::output_latency () const
2025 nframes_t max_latency;
2030 /* io lock not taken - must be protected by other means */
2032 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2033 if ((latency = i->total_latency ()) > max_latency) {
2034 max_latency = latency;
2042 IO::input_latency () const
2044 nframes_t max_latency;
2049 /* io lock not taken - must be protected by other means */
2051 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2052 if ((latency = i->total_latency ()) > max_latency) {
2053 max_latency = latency;
2061 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2064 BLOCK_PROCESS_CALLBACK ();
2065 Glib::Mutex::Lock lm2 (io_lock);
2067 /* Connect to the bundle, not worrying about any connections
2068 that are already made. */
2070 uint32_t cnt = c->nchannels ();
2072 for (uint32_t n = 0; n < cnt; ++n) {
2073 const Bundle::PortList& pl = c->channel_ports (n);
2075 for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2077 if (!_inputs.port(n)->connected_to (*i)) {
2079 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
2087 /* If this is a UserBundle, make a note of what we've done */
2089 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2092 /* See if we already know about this one */
2093 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2094 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2098 if (i == _bundles_connected_to_inputs.end()) {
2099 /* We don't, so make a note */
2100 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2105 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2110 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2113 BLOCK_PROCESS_CALLBACK ();
2114 Glib::Mutex::Lock lm2 (io_lock);
2116 /* Connect to the bundle, not worrying about any connections
2117 that are already made. */
2119 uint32_t cnt = c->nchannels ();
2121 for (uint32_t n = 0; n < cnt; ++n) {
2123 const Bundle::PortList& pl = c->channel_ports (n);
2125 for (Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
2127 if (!_outputs.port(n)->connected_to (*i)) {
2129 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
2136 /* If this is a UserBundle, make a note of what we've done */
2138 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2141 /* See if we already know about this one */
2142 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2143 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2147 if (i == _bundles_connected_to_outputs.end()) {
2148 /* We don't, so make a note */
2149 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2154 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2160 IO::disable_connecting ()
2162 connecting_legal = false;
2167 IO::enable_connecting ()
2169 connecting_legal = true;
2170 return ConnectingLegal ();
2174 IO::disable_ports ()
2176 ports_legal = false;
2184 return PortsLegal ();
2188 IO::disable_panners (void)
2190 panners_legal = false;
2195 IO::reset_panners ()
2197 panners_legal = true;
2198 return PannersLegal ();
2202 IO::bundle_configuration_changed ()
2205 // connect_input_ports_to_bundle (_input_bundle, this);
2209 IO::bundle_ports_changed (int ignored)
2212 // connect_output_ports_to_bundle (_output_bundle, this);
2216 IO::GainControl::set_value (float val)
2218 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2219 if (val > 1.99526231f)
2222 _io->set_gain (val, this);
2224 AutomationControl::set_value(val);
2228 IO::GainControl::get_value (void) const
2230 return AutomationControl::get_value();
2234 IO::setup_peak_meters()
2236 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2237 _meter->configure_io (max_streams, max_streams);
2241 Update the peak meters.
2243 The meter signal lock is taken to prevent modification of the
2244 Meter signal while updating the meters, taking the meter signal
2245 lock prior to taking the io_lock ensures that all IO will remain
2246 valid while metering.
2251 Glib::Mutex::Lock guard (m_meter_signal_lock);
2252 Meter(); /* EMIT SIGNAL */
2258 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2260 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2265 IO::clear_automation ()
2267 data().clear (); // clears gain automation
2268 _panner->data().clear();
2272 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2274 // XXX: would be nice to get rid of this special hack
2276 if (param.type() == GainAutomation) {
2278 bool changed = false;
2281 Glib::Mutex::Lock lm (control_lock());
2283 boost::shared_ptr<AutomationList> gain_auto
2284 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2286 if (state != gain_auto->automation_state()) {
2288 _last_automation_snapshot = 0;
2289 gain_auto->set_automation_state (state);
2292 // FIXME: shouldn't this use Curve?
2293 set_gain (gain_auto->eval (_session.transport_frame()), this);
2299 _session.set_dirty ();
2303 AutomatableControls::set_parameter_automation_state(param, state);
2308 IO::inc_gain (gain_t factor, void *src)
2310 if (_desired_gain == 0.0f)
2311 set_gain (0.000001f + (0.000001f * factor), src);
2313 set_gain (_desired_gain + (_desired_gain * factor), src);
2317 IO::set_gain (gain_t val, void *src)
2319 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2320 if (val > 1.99526231f) {
2324 if (src != _gain_control.get()) {
2325 _gain_control->set_value(val);
2326 // bit twisty, this will come back and call us again
2327 // (this keeps control in sync with reality)
2332 Glib::Mutex::Lock dm (declick_lock);
2333 _desired_gain = val;
2336 if (_session.transport_stopped()) {
2341 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2342 _gain_control->list()->add (_session.transport_frame(), val);
2347 _session.set_dirty();
2351 IO::start_pan_touch (uint32_t which)
2353 if (which < _panner->npanners()) {
2354 (*_panner).pan_control(which)->start_touch();
2359 IO::end_pan_touch (uint32_t which)
2361 if (which < _panner->npanners()) {
2362 (*_panner).pan_control(which)->stop_touch();
2368 IO::automation_snapshot (nframes_t now, bool force)
2370 AutomatableControls::automation_snapshot (now, force);
2371 // XXX: This seems to be wrong.
2372 // drobilla: shouldnt automation_snapshot for panner be called
2373 // "automagically" because its an Automatable now ?
2375 // we could dump this whole method then. <3
2377 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2378 _panner->automation_snapshot (now, force);
2381 _panner->automation_snapshot (now, force);
2382 _last_automation_snapshot = now;
2386 IO::transport_stopped (nframes_t frame)
2388 _gain_control->list()->reposition_for_rt_add (frame);
2390 if (_gain_control->automation_state() != Off) {
2392 /* the src=0 condition is a special signal to not propagate
2393 automation gain changes into the mix group when locating.
2396 // FIXME: shouldn't this use Curve?
2397 set_gain (_gain_control->list()->eval (frame), 0);
2400 _panner->transport_stopped (frame);
2404 IO::build_legal_port_name (DataType type, bool in)
2406 const int name_size = jack_port_name_size();
2411 if (type == DataType::AUDIO) {
2412 suffix = _("audio");
2413 } else if (type == DataType::MIDI) {
2416 throw unknown_type();
2421 maxports = _input_maximum.get(type);
2423 suffix += _("_out");
2424 maxports = _output_maximum.get(type);
2427 if (maxports == 1) {
2428 // allow space for the slash + the suffix
2429 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2430 char buf[name_size+1];
2431 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2432 return string (buf);
2435 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2437 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2439 char buf1[name_size+1];
2440 char buf2[name_size+1];
2442 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2447 port_number = find_input_port_hole (buf1);
2449 port_number = find_output_port_hole (buf1);
2452 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2454 return string (buf2);
2458 IO::find_input_port_hole (const char* base)
2460 /* CALLER MUST HOLD IO LOCK */
2464 if (_inputs.empty()) {
2468 /* we only allow up to 4 characters for the port number
2471 for (n = 1; n < 9999; ++n) {
2472 char buf[jack_port_name_size()];
2473 PortSet::iterator i = _inputs.begin();
2475 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2477 for ( ; i != _inputs.end(); ++i) {
2478 if (i->name() == buf) {
2483 if (i == _inputs.end()) {
2491 IO::find_output_port_hole (const char* base)
2493 /* CALLER MUST HOLD IO LOCK */
2497 if (_outputs.empty()) {
2501 /* we only allow up to 4 characters for the port number
2504 for (n = 1; n < 9999; ++n) {
2505 char buf[jack_port_name_size()];
2506 PortSet::iterator i = _outputs.begin();
2508 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2510 for ( ; i != _outputs.end(); ++i) {
2511 if (i->name() == buf) {
2516 if (i == _outputs.end()) {
2525 IO::set_active (bool yn)
2528 active_changed(); /* EMIT SIGNAL */
2532 IO::audio_input(uint32_t n) const
2534 return dynamic_cast<AudioPort*>(input(n));
2538 IO::audio_output(uint32_t n) const
2540 return dynamic_cast<AudioPort*>(output(n));
2544 IO::midi_input(uint32_t n) const
2546 return dynamic_cast<MidiPort*>(input(n));
2550 IO::midi_output(uint32_t n) const
2552 return dynamic_cast<MidiPort*>(output(n));
2556 IO::set_phase_invert (bool yn, void *src)
2558 if (_phase_invert != yn) {
2560 // phase_invert_changed (src); /* EMIT SIGNAL */
2565 IO::set_denormal_protection (bool yn, void *src)
2567 if (_denormal_protection != yn) {
2568 _denormal_protection = yn;
2569 // denormal_protection_changed (src); /* EMIT SIGNAL */
2574 IO::update_port_total_latencies ()
2576 /* io_lock, not taken: function must be called from Session::process() calltree */
2578 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2579 _session.engine().update_total_latency (*i);
2582 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2583 _session.engine().update_total_latency (*i);
2589 * Setup bundles that describe our inputs and outputs.
2593 IO::setup_bundles_for_inputs_and_outputs ()
2597 _bundle_for_inputs->remove_channels ();
2598 _bundle_for_outputs->remove_channels ();
2600 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2601 _bundle_for_inputs->set_name (buf);
2602 uint32_t const ni = inputs().num_ports();
2603 for (uint32_t i = 0; i < ni; ++i) {
2604 snprintf (buf, sizeof(buf), _("in %d"), (i + 1));
2605 _bundle_for_inputs->add_channel (buf);
2606 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2609 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2610 _bundle_for_outputs->set_name (buf);
2611 uint32_t const no = outputs().num_ports();
2612 for (uint32_t i = 0; i < no; ++i) {
2613 snprintf (buf, sizeof(buf), _("out %d"), (i + 1));
2614 _bundle_for_outputs->add_channel (buf);
2615 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2621 * Create and setup bundles that describe our inputs and outputs.
2625 IO::create_bundles_for_inputs_and_outputs ()
2627 _bundle_for_inputs = boost::shared_ptr<Bundle> (new Bundle (true));
2628 _bundle_for_outputs = boost::shared_ptr<Bundle> (new Bundle (false));
2629 setup_bundles_for_inputs_and_outputs ();
2632 /** @return Bundles connected to our inputs */
2634 IO::bundles_connected_to_inputs ()
2639 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2640 bundles.push_back (i->bundle);
2643 /* Normal bundles */
2644 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2645 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2646 if ((*i)->ports_are_outputs() == false || (*i)->nchannels() != n_inputs().n_total()) {
2650 for (uint32_t j = 0; j < n_inputs().n_total(); ++j) {
2652 Bundle::PortList const& pl = (*i)->channel_ports (j);
2653 if (!pl.empty() && input(j)->connected_to (pl[0])) {
2654 bundles.push_back (*i);
2664 /* @return Bundles connected to our outputs */
2666 IO::bundles_connected_to_outputs ()
2671 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2672 bundles.push_back (i->bundle);
2676 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2677 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2678 if ((*i)->ports_are_inputs() == false || (*i)->nchannels() != n_outputs().n_total()) {
2682 for (uint32_t j = 0; j < n_outputs().n_total(); ++j) {
2684 Bundle::PortList const& pl = (*i)->channel_ports (j);
2686 if (!pl.empty() && output(j)->connected_to (pl[0])) {
2687 bundles.push_back (*i);
2696 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2699 configuration_changed = b->ConfigurationChanged.connect (
2700 sigc::mem_fun (*io, &IO::bundle_configuration_changed)
2702 ports_changed = b->PortsChanged.connect (
2703 sigc::mem_fun (*io, &IO::bundle_ports_changed)
2708 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2710 /* io_lock, not taken: function must be called from Session::process() calltree */
2714 IO::flush_outputs (nframes_t nframes, nframes_t offset)
2716 /* io_lock, not taken: function must be called from Session::process() calltree */
2717 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2719 /* Only run cycle_start() on output ports, because
2720 inputs must be done in the correct processing order,
2721 which requires interleaving with route processing.
2724 (*i).flush_buffers (nframes, offset);