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>
27 #include <glibmm/thread.h>
29 #include <pbd/xml++.h>
30 #include <pbd/replace_all.h>
31 #include <pbd/unknown_type.h>
33 #include <ardour/audioengine.h>
34 #include <ardour/io.h>
35 #include <ardour/route.h>
36 #include <ardour/port.h>
37 #include <ardour/audio_port.h>
38 #include <ardour/midi_port.h>
39 #include <ardour/auto_bundle.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>
52 A bug in OS X's cmath that causes isnan() and isinf() to be
53 "undeclared". the following works around that
56 #if defined(__APPLE__) && defined(__MACH__)
57 extern "C" int isnan (double);
58 extern "C" int isinf (double);
61 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
64 using namespace ARDOUR;
67 const string IO::state_node_name = "IO";
68 bool IO::connecting_legal = false;
69 bool IO::ports_legal = false;
70 bool IO::panners_legal = false;
71 sigc::signal<void> IO::Meter;
72 sigc::signal<int> IO::ConnectingLegal;
73 sigc::signal<int> IO::PortsLegal;
74 sigc::signal<int> IO::PannersLegal;
75 sigc::signal<void,ChanCount> IO::PortCountChanged;
76 sigc::signal<int> IO::PortsCreated;
78 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
80 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
81 others can be imagined.
85 static gain_t direct_control_to_gain (double fract) {
86 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
87 /* this maxes at +6dB */
88 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
91 static double direct_gain_to_control (gain_t gain) {
92 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
93 if (gain == 0) return 0.0;
95 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
99 /** @param default_type The type of port that will be created by ensure_io
100 * and friends if no type is explicitly requested (to avoid breakage).
102 IO::IO (Session& s, const string& name,
103 int input_min, int input_max, int output_min, int output_max,
104 DataType default_type, bool public_ports)
105 : Automatable (s, name),
106 _output_buffers (new BufferSet()),
108 _default_type (default_type),
109 _public_ports (public_ports),
110 _input_minimum (ChanCount::ZERO),
111 _input_maximum (ChanCount::INFINITE),
112 _output_minimum (ChanCount::ZERO),
113 _output_maximum (ChanCount::INFINITE)
115 _panner = new Panner (name, _session);
116 _meter = new PeakMeter (_session);
119 _input_minimum = ChanCount(_default_type, input_min);
121 if (input_max >= 0) {
122 _input_maximum = ChanCount(_default_type, input_max);
124 if (output_min > 0) {
125 _output_minimum = ChanCount(_default_type, output_min);
127 if (output_max >= 0) {
128 _output_maximum = ChanCount(_default_type, output_max);
133 pending_state_node = 0;
134 no_panner_reset = false;
135 _phase_invert = false;
138 boost::shared_ptr<AutomationList> gl(
139 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
141 _gain_control = boost::shared_ptr<GainControl>(
142 new GainControl(X_("gaincontrol"), *this, gl));
144 add_control(_gain_control);
146 apply_gain_automation = false;
149 // IO::Meter is emitted from another thread so the
150 // Meter signal must be protected.
151 Glib::Mutex::Lock guard (m_meter_signal_lock);
152 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
155 // Connect to our own PortCountChanged signal to connect output buffers
156 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
158 _session.add_controllable (_gain_control);
160 create_bundles_for_inputs_and_outputs ();
163 IO::IO (Session& s, const XMLNode& node, DataType dt)
164 : Automatable (s, "unnamed io"),
165 _output_buffers (new BufferSet()),
169 _meter = new PeakMeter (_session);
170 _public_ports = true; // XXX get this from node
173 no_panner_reset = false;
177 apply_gain_automation = false;
179 boost::shared_ptr<AutomationList> gl(
180 new AutomationList(Parameter(GainAutomation), 0.0, 2.0, 1.0));
182 _gain_control = boost::shared_ptr<GainControl>(
183 new GainControl(X_("gaincontrol"), *this, gl));
185 add_control(_gain_control);
190 // IO::Meter is emitted from another thread so the
191 // Meter signal must be protected.
192 Glib::Mutex::Lock guard (m_meter_signal_lock);
193 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
196 // Connect to our own PortCountChanged signal to connect output buffers
197 IO::PortCountChanged.connect (mem_fun (*this, &IO::attach_buffers));
199 _session.add_controllable (_gain_control);
201 create_bundles_for_inputs_and_outputs ();
206 Glib::Mutex::Lock guard (m_meter_signal_lock);
207 Glib::Mutex::Lock lm (io_lock);
209 BLOCK_PROCESS_CALLBACK ();
211 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
212 _session.engine().unregister_port (*i);
215 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
216 _session.engine().unregister_port (*i);
219 m_meter_connection.disconnect();
223 delete _output_buffers;
227 IO::silence (nframes_t nframes, nframes_t offset)
229 /* io_lock, not taken: function must be called from Session::process() calltree */
231 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
232 i->get_buffer().silence (nframes, offset);
236 /** Deliver bufs to the IO's output ports
238 * This function should automatically do whatever it necessary to correctly deliver bufs
239 * to the outputs, eg applying gain or pan or whatever else needs to be done.
242 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
244 // FIXME: type specific code doesn't actually need to be here, it will go away in time
246 /* ********** AUDIO ********** */
248 // Apply gain if gain automation isn't playing
249 if ( ! apply_gain_automation) {
251 gain_t dg = _gain; // desired gain
254 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
262 if (dg != _gain || dg != 1.0)
263 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
266 // Use the panner to distribute audio to output port buffers
267 if (_panner && !_panner->empty() && !_panner->bypassed()) {
268 _panner->distribute (bufs, output_buffers(), start_frame, end_frame, nframes, offset);
270 const DataType type = DataType::AUDIO;
272 // Copy any audio 1:1 to outputs
274 BufferSet::iterator o = output_buffers().begin(type);
275 BufferSet::iterator i = bufs.begin(type);
276 BufferSet::iterator prev = i;
278 while (i != bufs.end(type) && o != output_buffers().end (type)) {
279 o->read_from(*i, nframes, offset);
285 /* extra outputs get a copy of the last buffer */
287 while (o != output_buffers().end(type)) {
288 o->read_from(*prev, nframes, offset);
293 /* ********** MIDI ********** */
295 // No MIDI, we're done here
296 if (bufs.count().n_midi() == 0) {
300 const DataType type = DataType::MIDI;
302 // Copy any MIDI 1:1 to outputs
303 assert(bufs.count().n_midi() == output_buffers().count().n_midi());
304 BufferSet::iterator o = output_buffers().begin(type);
305 for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) {
306 o->read_from(*i, nframes, offset);
311 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
313 assert(outs.available() >= n_inputs());
315 if (n_inputs() == ChanCount::ZERO)
318 outs.set_count(n_inputs());
320 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
322 BufferSet::iterator o = outs.begin(*t);
323 for (PortSet::iterator i = _inputs.begin(*t); i != _inputs.end(*t); ++i, ++o) {
324 o->read_from(i->get_buffer(), nframes, offset);
331 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
332 nframes_t nframes, nframes_t offset)
334 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
336 collect_input (bufs, nframes, offset);
338 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
343 IO::check_bundles_connected_to_inputs ()
345 check_bundles (_bundles_connected_to_inputs, inputs());
349 IO::check_bundles_connected_to_outputs ()
351 check_bundles (_bundles_connected_to_outputs, outputs());
355 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
357 std::vector<UserBundleInfo> new_list;
359 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
361 uint32_t const N = i->bundle->nchannels ();
363 if (ports.num_ports() < N) {
368 for (uint32_t j = 0; j < N; ++j) {
369 /* Every port on bundle channel j must be connected to our input j */
370 PortList const pl = i->bundle->channel_ports (j);
371 for (uint32_t k = 0; k < pl.size(); ++k) {
372 if (ports.port(j)->connected_to (pl[k]) == false) {
384 new_list.push_back (*i);
386 i->configuration_will_change.disconnect ();
387 i->configuration_has_changed.disconnect ();
388 i->ports_will_change.disconnect ();
389 i->ports_have_changed.disconnect ();
398 IO::disconnect_input (Port* our_port, string other_port, void* src)
400 if (other_port.length() == 0 || our_port == 0) {
405 BLOCK_PROCESS_CALLBACK ();
408 Glib::Mutex::Lock lm (io_lock);
410 /* check that our_port is really one of ours */
412 if ( ! _inputs.contains(our_port)) {
416 /* disconnect it from the source */
418 if (_session.engine().disconnect (other_port, our_port->name())) {
419 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
423 check_bundles_connected_to_inputs ();
427 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
428 _session.set_dirty ();
434 IO::connect_input (Port* our_port, string other_port, void* src)
436 if (other_port.length() == 0 || our_port == 0) {
441 BLOCK_PROCESS_CALLBACK ();
444 Glib::Mutex::Lock lm (io_lock);
446 /* check that our_port is really one of ours */
448 if ( ! _inputs.contains(our_port) ) {
452 /* connect it to the source */
454 if (_session.engine().connect (other_port, our_port->name())) {
460 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
461 _session.set_dirty ();
466 IO::disconnect_output (Port* our_port, string other_port, void* src)
468 if (other_port.length() == 0 || our_port == 0) {
473 BLOCK_PROCESS_CALLBACK ();
476 Glib::Mutex::Lock lm (io_lock);
478 /* check that our_port is really one of ours */
480 if ( ! _outputs.contains(our_port) ) {
484 /* disconnect it from the destination */
486 if (_session.engine().disconnect (our_port->name(), other_port)) {
487 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
491 check_bundles_connected_to_outputs ();
495 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
496 _session.set_dirty ();
501 IO::connect_output (Port* our_port, string other_port, void* src)
503 if (other_port.length() == 0 || our_port == 0) {
508 BLOCK_PROCESS_CALLBACK ();
512 Glib::Mutex::Lock lm (io_lock);
514 /* check that our_port is really one of ours */
516 if ( ! _outputs.contains(our_port) ) {
520 /* connect it to the destination */
522 if (_session.engine().connect (our_port->name(), other_port)) {
528 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
529 _session.set_dirty ();
534 IO::set_input (Port* other_port, void* src)
536 /* this removes all but one ports, and connects that one port
537 to the specified source.
540 if (_input_minimum.n_total() > 1) {
541 /* sorry, you can't do this */
545 if (other_port == 0) {
546 if (_input_minimum == ChanCount::ZERO) {
547 return ensure_inputs (ChanCount::ZERO, false, true, src);
553 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
557 return connect_input (_inputs.port(0), other_port->name(), src);
561 IO::remove_output_port (Port* port, void* src)
563 IOChange change (NoChange);
566 BLOCK_PROCESS_CALLBACK ();
570 Glib::Mutex::Lock lm (io_lock);
572 if (n_outputs() <= _output_minimum) {
573 /* sorry, you can't do this */
577 if (_outputs.remove(port)) {
578 change = IOChange (change|ConfigurationChanged);
580 if (port->connected()) {
581 change = IOChange (change|ConnectionsChanged);
584 _session.engine().unregister_port (*port);
585 check_bundles_connected_to_outputs ();
587 setup_peak_meters ();
592 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
595 if (change == ConnectionsChanged) {
596 setup_bundles_for_inputs_and_outputs ();
599 if (change != NoChange) {
600 output_changed (change, src);
601 _session.set_dirty ();
608 /** Add an output port.
610 * @param destination Name of input port to connect new port to.
611 * @param src Source for emitted ConfigurationChanged signal.
612 * @param type Data type of port. Default value (NIL) will use this IO's default type.
615 IO::add_output_port (string destination, void* src, DataType type)
619 if (type == DataType::NIL)
620 type = _default_type;
623 BLOCK_PROCESS_CALLBACK ();
627 Glib::Mutex::Lock lm (io_lock);
629 if (n_outputs() >= _output_maximum) {
633 /* Create a new output port */
635 string portname = build_legal_port_name (type, false);
637 if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) {
638 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
642 _outputs.add (our_port);
643 setup_peak_meters ();
647 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
650 if (destination.length()) {
651 if (_session.engine().connect (our_port->name(), destination)) {
656 // pan_changed (src); /* EMIT SIGNAL */
657 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
658 setup_bundles_for_inputs_and_outputs ();
659 _session.set_dirty ();
665 IO::remove_input_port (Port* port, void* src)
667 IOChange change (NoChange);
670 BLOCK_PROCESS_CALLBACK ();
674 Glib::Mutex::Lock lm (io_lock);
676 if (n_inputs() <= _input_minimum) {
677 /* sorry, you can't do this */
681 if (_inputs.remove(port)) {
682 change = IOChange (change|ConfigurationChanged);
684 if (port->connected()) {
685 change = IOChange (change|ConnectionsChanged);
688 _session.engine().unregister_port (*port);
689 check_bundles_connected_to_inputs ();
691 setup_peak_meters ();
696 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
699 if (change == ConfigurationChanged) {
700 setup_bundles_for_inputs_and_outputs ();
703 if (change != NoChange) {
704 input_changed (change, src);
705 _session.set_dirty ();
713 /** Add an input port.
715 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
716 * @param destination Name of input port to connect new port to.
717 * @param src Source for emitted ConfigurationChanged signal.
720 IO::add_input_port (string source, void* src, DataType type)
724 if (type == DataType::NIL)
725 type = _default_type;
728 BLOCK_PROCESS_CALLBACK ();
731 Glib::Mutex::Lock lm (io_lock);
733 if (n_inputs() >= _input_maximum) {
737 /* Create a new input port */
739 string portname = build_legal_port_name (type, true);
741 if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) {
742 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
746 _inputs.add (our_port);
747 setup_peak_meters ();
751 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
754 if (source.length()) {
756 if (_session.engine().connect (source, our_port->name())) {
761 // pan_changed (src); /* EMIT SIGNAL */
762 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
763 setup_bundles_for_inputs_and_outputs ();
764 _session.set_dirty ();
770 IO::disconnect_inputs (void* src)
773 BLOCK_PROCESS_CALLBACK ();
776 Glib::Mutex::Lock lm (io_lock);
778 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
779 _session.engine().disconnect (*i);
782 check_bundles_connected_to_inputs ();
786 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
792 IO::disconnect_outputs (void* src)
795 BLOCK_PROCESS_CALLBACK ();
798 Glib::Mutex::Lock lm (io_lock);
800 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
801 _session.engine().disconnect (*i);
804 check_bundles_connected_to_outputs ();
808 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
809 _session.set_dirty ();
815 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
817 Port* input_port = 0;
818 bool changed = false;
821 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
823 const size_t n = count.get(*t);
825 /* remove unused ports */
826 for (size_t i = n_inputs().get(*t); i > n; --i) {
827 input_port = _inputs.port(*t, i-1);
830 _inputs.remove(input_port);
831 _session.engine().unregister_port (*input_port);
836 /* create any necessary new ports */
837 while (n_inputs().get(*t) < n) {
839 string portname = build_legal_port_name (*t, true);
843 if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
844 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
849 catch (AudioEngine::PortRegistrationFailure& err) {
850 setup_peak_meters ();
853 throw AudioEngine::PortRegistrationFailure();
856 _inputs.add (input_port);
862 check_bundles_connected_to_inputs ();
863 setup_peak_meters ();
865 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
866 _session.set_dirty ();
870 /* disconnect all existing ports so that we get a fresh start */
871 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
872 _session.engine().disconnect (*i);
879 /** Attach output_buffers to port buffers.
881 * Connected to IO's own PortCountChanged signal.
884 IO::attach_buffers(ChanCount ignored)
886 _output_buffers->attach_buffers(_outputs);
890 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
892 bool in_changed = false;
893 bool out_changed = false;
894 bool need_pan_reset = false;
896 in = min (_input_maximum, in);
898 out = min (_output_maximum, out);
900 if (in == n_inputs() && out == n_outputs() && !clear) {
905 BLOCK_PROCESS_CALLBACK ();
906 Glib::Mutex::Lock lm (io_lock);
910 if (n_outputs() != out) {
911 need_pan_reset = true;
914 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
916 const size_t nin = in.get(*t);
917 const size_t nout = out.get(*t);
919 Port* output_port = 0;
920 Port* input_port = 0;
922 /* remove unused output ports */
923 for (size_t i = n_outputs().get(*t); i > nout; --i) {
924 output_port = _outputs.port(*t, i-1);
927 _outputs.remove(output_port);
928 _session.engine().unregister_port (*output_port);
933 /* remove unused input ports */
934 for (size_t i = n_inputs().get(*t); i > nin; --i) {
935 input_port = _inputs.port(*t, i-1);
938 _inputs.remove(input_port);
939 _session.engine().unregister_port (*input_port);
944 /* create any necessary new input ports */
946 while (n_inputs().get(*t) < nin) {
948 string portname = build_legal_port_name (*t, true);
951 if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) {
952 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
957 catch (AudioEngine::PortRegistrationFailure& err) {
958 setup_peak_meters ();
961 throw AudioEngine::PortRegistrationFailure();
968 /* create any necessary new output ports */
970 while (n_outputs().get(*t) < nout) {
972 string portname = build_legal_port_name (*t, false);
975 if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
976 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
981 catch (AudioEngine::PortRegistrationFailure& err) {
982 setup_peak_meters ();
985 throw AudioEngine::PortRegistrationFailure ();
995 /* disconnect all existing ports so that we get a fresh start */
997 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
998 _session.engine().disconnect (*i);
1001 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1002 _session.engine().disconnect (*i);
1006 if (in_changed || out_changed) {
1007 setup_peak_meters ();
1013 check_bundles_connected_to_outputs ();
1014 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1018 check_bundles_connected_to_inputs ();
1019 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1022 if (in_changed || out_changed) {
1023 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1024 setup_bundles_for_inputs_and_outputs ();
1025 _session.set_dirty ();
1032 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1034 bool changed = false;
1036 count = min (_input_maximum, count);
1038 if (count == n_inputs() && !clear) {
1043 BLOCK_PROCESS_CALLBACK ();
1044 Glib::Mutex::Lock im (io_lock);
1045 changed = ensure_inputs_locked (count, clear, src);
1047 changed = ensure_inputs_locked (count, clear, src);
1051 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1052 setup_bundles_for_inputs_and_outputs ();
1053 _session.set_dirty ();
1059 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1061 Port* output_port = 0;
1062 bool changed = false;
1063 bool need_pan_reset = false;
1065 if (n_outputs() != count) {
1066 need_pan_reset = true;
1069 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1071 const size_t n = count.get(*t);
1073 /* remove unused ports */
1074 for (size_t i = n_outputs().get(*t); i > n; --i) {
1075 output_port = _outputs.port(*t, i-1);
1077 assert(output_port);
1078 _outputs.remove(output_port);
1079 _session.engine().unregister_port (*output_port);
1084 /* create any necessary new ports */
1085 while (n_outputs().get(*t) < n) {
1087 string portname = build_legal_port_name (*t, false);
1089 if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) {
1090 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1094 _outputs.add (output_port);
1096 setup_peak_meters ();
1098 if (need_pan_reset) {
1105 check_bundles_connected_to_outputs ();
1106 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1107 _session.set_dirty ();
1111 /* disconnect all existing ports so that we get a fresh start */
1112 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1113 _session.engine().disconnect (*i);
1121 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1123 bool changed = false;
1125 if (_output_maximum < ChanCount::INFINITE) {
1126 count = min (_output_maximum, count);
1127 if (count == n_outputs() && !clear) {
1132 /* XXX caller should hold io_lock, but generally doesn't */
1135 BLOCK_PROCESS_CALLBACK ();
1136 Glib::Mutex::Lock im (io_lock);
1137 changed = ensure_outputs_locked (count, clear, src);
1139 changed = ensure_outputs_locked (count, clear, src);
1143 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1144 setup_bundles_for_inputs_and_outputs ();
1151 IO::effective_gain () const
1153 if (_gain_control->list()->automation_playback()) {
1154 return _gain_control->get_value();
1156 return _desired_gain;
1163 if (panners_legal) {
1164 if (!no_panner_reset) {
1165 _panner->reset (n_outputs().n_audio(), pans_required());
1168 panner_legal_c.disconnect ();
1169 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1174 IO::panners_became_legal ()
1176 _panner->reset (n_outputs().n_audio(), pans_required());
1177 _panner->load (); // automation
1178 panner_legal_c.disconnect ();
1183 IO::defer_pan_reset ()
1185 no_panner_reset = true;
1189 IO::allow_pan_reset ()
1191 no_panner_reset = false;
1197 IO::get_state (void)
1199 return state (true);
1203 IO::state (bool full_state)
1205 XMLNode* node = new XMLNode (state_node_name);
1208 vector<string>::iterator ci;
1210 LocaleGuard lg (X_("POSIX"));
1211 Glib::Mutex::Lock lm (io_lock);
1213 node->add_property("name", _name);
1214 id().print (buf, sizeof (buf));
1215 node->add_property("id", buf);
1218 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1219 i != _bundles_connected_to_inputs.end();
1223 XMLNode* n = new XMLNode ("InputBundle");
1224 n->add_property ("name", i->bundle->name ());
1225 node->add_child_nocopy (*n);
1229 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1230 i != _bundles_connected_to_outputs.end();
1234 XMLNode* n = new XMLNode ("OutputBundle");
1235 n->add_property ("name", i->bundle->name ());
1236 node->add_child_nocopy (*n);
1241 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1243 vector<string> connections;
1245 if (i->get_connections (connections)) {
1249 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1254 /* if its a connection to our own port,
1255 return only the port name, not the
1256 whole thing. this allows connections
1257 to be re-established even when our
1258 client name is different.
1261 str += _session.engine().make_port_name_relative (*ci);
1271 node->add_property ("inputs", str);
1275 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1277 vector<string> connections;
1279 if (i->get_connections (connections)) {
1283 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1288 str += _session.engine().make_port_name_relative (*ci);
1298 node->add_property ("outputs", str);
1300 node->add_child_nocopy (_panner->state (full_state));
1301 node->add_child_nocopy (_gain_control->get_state ());
1303 snprintf (buf, sizeof(buf), "%2.12f", gain());
1304 node->add_property ("gain", buf);
1306 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1310 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1311 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1313 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1315 node->add_property ("iolimits", buf);
1320 node->add_child_nocopy (get_automation_state());
1326 IO::set_state (const XMLNode& node)
1328 const XMLProperty* prop;
1329 XMLNodeConstIterator iter;
1330 LocaleGuard lg (X_("POSIX"));
1332 /* force use of non-localized representation of decimal point,
1333 since we use it a lot in XML files and so forth.
1336 if (node.name() != state_node_name) {
1337 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1341 if ((prop = node.property ("name")) != 0) {
1342 _name = prop->value();
1343 /* used to set panner name with this, but no more */
1346 if ((prop = node.property ("id")) != 0) {
1347 _id = prop->value ();
1355 if ((prop = node.property ("iolimits")) != 0) {
1356 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1357 &in_min, &in_max, &out_min, &out_max);
1359 /* Correct for the difference between the way we write things to session files and the
1360 way things are described by ChanCount; see comments in io.h about what the different
1361 ChanCount values mean. */
1364 _input_minimum = ChanCount::ZERO;
1366 _input_minimum = ChanCount (_default_type, in_min);
1370 _input_maximum = ChanCount::INFINITE;
1372 _input_maximum = ChanCount (_default_type, in_max);
1376 _output_minimum = ChanCount::ZERO;
1378 _output_minimum = ChanCount (_default_type, out_min);
1382 _output_maximum = ChanCount::INFINITE;
1384 _output_maximum = ChanCount (_default_type, out_max);
1388 if ((prop = node.property ("gain")) != 0) {
1389 set_gain (atof (prop->value().c_str()), this);
1390 _gain = _desired_gain;
1393 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1394 /* old school automation handling */
1397 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1399 if ((*iter)->name() == "Panner") {
1401 _panner = new Panner (_name, _session);
1403 _panner->set_state (**iter);
1406 if ((*iter)->name() == X_("Automation")) {
1408 set_automation_state (*(*iter), Parameter(GainAutomation));
1411 if ((*iter)->name() == X_("controllable")) {
1412 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1413 _gain_control->set_state (**iter);
1420 if (create_ports (node)) {
1426 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1429 if (panners_legal) {
1432 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1435 if (connecting_legal) {
1437 if (make_connections (node)) {
1443 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1446 if (!ports_legal || !connecting_legal) {
1447 pending_state_node = new XMLNode (node);
1454 IO::load_automation (string path)
1459 uint32_t linecnt = 0;
1461 LocaleGuard lg (X_("POSIX"));
1463 fullpath = _session.automation_dir();
1466 in.open (fullpath.c_str());
1469 fullpath = _session.automation_dir();
1470 fullpath += _session.snap_name();
1474 in.open (fullpath.c_str());
1477 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1482 clear_automation ();
1484 while (in.getline (line, sizeof(line), '\n')) {
1489 if (++linecnt == 1) {
1490 if (memcmp (line, "version", 7) == 0) {
1491 if (sscanf (line, "version %f", &version) != 1) {
1492 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1496 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1503 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1504 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1510 _gain_control->list()->fast_simple_add (when, value);
1520 /* older (pre-1.0) versions of ardour used this */
1524 warning << _("dubious automation event found (and ignored)") << endmsg;
1532 IO::connecting_became_legal ()
1536 if (pending_state_node == 0) {
1537 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1542 connection_legal_c.disconnect ();
1544 ret = make_connections (*pending_state_node);
1547 delete pending_state_node;
1548 pending_state_node = 0;
1554 IO::ports_became_legal ()
1558 if (pending_state_node == 0) {
1559 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1564 port_legal_c.disconnect ();
1566 ret = create_ports (*pending_state_node);
1568 if (connecting_legal) {
1569 delete pending_state_node;
1570 pending_state_node = 0;
1577 IO::create_ports (const XMLNode& node)
1579 XMLProperty const * prop;
1581 int num_outputs = 0;
1583 if ((prop = node.property ("inputs")) != 0) {
1584 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1585 } else if ((prop = node.property ("outputs")) != 0) {
1586 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1589 no_panner_reset = true;
1591 // FIXME: audio-only
1592 if (ensure_io (ChanCount(DataType::AUDIO, num_inputs), ChanCount(DataType::AUDIO, num_outputs), true, this)) {
1593 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1597 no_panner_reset = false;
1599 set_deferred_state ();
1607 IO::make_connections (const XMLNode& node)
1609 XMLProperty const * prop;
1611 if ((prop = node.property ("inputs")) != 0) {
1612 if (set_inputs (prop->value())) {
1613 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1619 if ((prop = node.property ("outputs")) != 0) {
1620 if (set_outputs (prop->value())) {
1621 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1626 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1628 if ((*i)->name() == "InputBundle") {
1629 XMLProperty const * prop = (*i)->property ("name");
1631 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1633 connect_input_ports_to_bundle (b, this);
1635 error << string_compose(_("Unknown bundle \"%1\" listed for input of %2"), prop->value(), _name) << endmsg;
1639 } else if ((*i)->name() == "OutputBundle") {
1640 XMLProperty const * prop = (*i)->property ("name");
1642 boost::shared_ptr<Bundle> b = _session.bundle_by_name (prop->value());
1644 connect_output_ports_to_bundle (b, this);
1646 error << string_compose(_("Unknown bundle \"%1\" listed for output of %2"), prop->value(), _name) << endmsg;
1656 IO::set_inputs (const string& str)
1658 vector<string> ports;
1663 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1667 // FIXME: audio-only
1668 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1672 string::size_type start, end, ostart;
1679 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1682 if ((end = str.find_first_of ('}', start)) == string::npos) {
1683 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1687 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1688 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1694 for (int x = 0; x < n; ++x) {
1695 connect_input (input (i), ports[x], this);
1707 IO::set_outputs (const string& str)
1709 vector<string> ports;
1714 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1718 // FIXME: audio-only
1719 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1723 string::size_type start, end, ostart;
1730 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1733 if ((end = str.find_first_of ('}', start)) == string::npos) {
1734 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1738 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1739 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1745 for (int x = 0; x < n; ++x) {
1746 connect_output (output (i), ports[x], this);
1758 IO::parse_io_string (const string& str, vector<string>& ports)
1760 string::size_type pos, opos;
1762 if (str.length() == 0) {
1771 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1772 ports.push_back (str.substr (opos, pos - opos));
1776 if (opos < str.length()) {
1777 ports.push_back (str.substr(opos));
1780 return ports.size();
1784 IO::parse_gain_string (const string& str, vector<string>& ports)
1786 string::size_type pos, opos;
1792 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1793 ports.push_back (str.substr (opos, pos - opos));
1797 if (opos < str.length()) {
1798 ports.push_back (str.substr(opos));
1801 return ports.size();
1805 IO::set_name (const string& requested_name)
1807 if (requested_name == _name) {
1813 if ( (rt = dynamic_cast<Route *>(this))) {
1814 name = Route::ensure_track_or_route_name(requested_name, _session);
1816 name = requested_name;
1820 /* replace all colons in the name. i wish we didn't have to do this */
1822 if (replace_all (name, ":", "-")) {
1823 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1826 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1827 string current_name = i->short_name();
1828 current_name.replace (current_name.find (_name), _name.length(), name);
1829 i->set_name (current_name);
1832 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1833 string current_name = i->short_name();
1834 current_name.replace (current_name.find (_name), _name.length(), name);
1835 i->set_name (current_name);
1838 bool const r = SessionObject::set_name(name);
1840 setup_bundles_for_inputs_and_outputs ();
1846 IO::set_input_minimum (ChanCount n)
1852 IO::set_input_maximum (ChanCount n)
1858 IO::set_output_minimum (ChanCount n)
1860 _output_minimum = n;
1864 IO::set_output_maximum (ChanCount n)
1866 _output_maximum = n;
1870 IO::set_port_latency (nframes_t nframes)
1872 Glib::Mutex::Lock lm (io_lock);
1874 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1875 i->set_latency (nframes);
1880 IO::output_latency () const
1882 nframes_t max_latency;
1887 /* io lock not taken - must be protected by other means */
1889 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1890 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1891 max_latency = latency;
1899 IO::input_latency () const
1901 nframes_t max_latency;
1906 /* io lock not taken - must be protected by other means */
1908 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1909 if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
1910 max_latency = latency;
1918 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1921 BLOCK_PROCESS_CALLBACK ();
1922 Glib::Mutex::Lock lm2 (io_lock);
1924 /* Connect to the bundle, not worrying about any connections
1925 that are already made. */
1927 uint32_t const channels = c->nchannels ();
1929 for (uint32_t n = 0; n < channels; ++n) {
1930 const PortList& pl = c->channel_ports (n);
1932 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
1934 if (!_inputs.port(n)->connected_to (*i)) {
1936 if (_session.engine().connect (*i, _inputs.port(n)->name())) {
1944 /* If this is a UserBundle, make a note of what we've done */
1946 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1949 /* See if we already know about this one */
1950 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1951 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
1955 if (i == _bundles_connected_to_inputs.end()) {
1956 /* We don't, so make a note */
1957 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
1962 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
1967 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1970 BLOCK_PROCESS_CALLBACK ();
1971 Glib::Mutex::Lock lm2 (io_lock);
1973 /* Connect to the bundle, not worrying about any connections
1974 that are already made. */
1976 uint32_t const channels = c->nchannels ();
1978 for (uint32_t n = 0; n < channels; ++n) {
1980 const PortList& pl = c->channel_ports (n);
1982 for (PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
1984 if (!_outputs.port(n)->connected_to (*i)) {
1986 if (_session.engine().connect (_outputs.port(n)->name(), *i)) {
1993 /* If this is a UserBundle, make a note of what we've done */
1995 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1998 /* See if we already know about this one */
1999 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2000 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2004 if (i == _bundles_connected_to_outputs.end()) {
2005 /* We don't, so make a note */
2006 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2011 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2017 IO::disable_connecting ()
2019 connecting_legal = false;
2024 IO::enable_connecting ()
2026 connecting_legal = true;
2027 return ConnectingLegal ();
2031 IO::disable_ports ()
2033 ports_legal = false;
2041 return PortsLegal ();
2045 IO::disable_panners (void)
2047 panners_legal = false;
2052 IO::reset_panners ()
2054 panners_legal = true;
2055 return PannersLegal ();
2059 IO::bundle_configuration_will_change ()
2062 // connect_input_ports_to_bundle (_input_bundle, this);
2066 IO::bundle_configuration_has_changed ()
2069 // connect_input_ports_to_bundle (_input_bundle, this);
2073 IO::bundle_ports_will_change (int ignored)
2076 // connect_output_ports_to_bundle (_output_bundle, this);
2080 IO::bundle_ports_have_changed (int ignored)
2083 // connect_output_ports_to_bundle (_output_bundle, this);
2087 IO::GainControl::set_value (float val)
2089 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2090 if (val > 1.99526231f)
2094 _io.set_gain (val, this);
2096 Changed(); /* EMIT SIGNAL */
2100 IO::GainControl::get_value (void) const
2102 return AutomationControl::get_value();
2106 IO::setup_peak_meters()
2108 ChanCount max_streams = std::max(_inputs.count(), _outputs.count());
2109 _meter->configure_io(max_streams, max_streams);
2113 Update the peak meters.
2115 The meter signal lock is taken to prevent modification of the
2116 Meter signal while updating the meters, taking the meter signal
2117 lock prior to taking the io_lock ensures that all IO will remain
2118 valid while metering.
2123 Glib::Mutex::Lock guard (m_meter_signal_lock);
2124 Meter(); /* EMIT SIGNAL */
2130 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2132 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2137 IO::clear_automation ()
2139 Automatable::clear_automation (); // clears gain automation
2140 _panner->clear_automation ();
2144 IO::set_parameter_automation_state (Parameter param, AutoState state)
2146 // XXX: would be nice to get rid of this special hack
2148 if (param.type() == GainAutomation) {
2150 bool changed = false;
2153 Glib::Mutex::Lock lm (_automation_lock);
2155 boost::shared_ptr<AutomationList> gain_auto = _gain_control->list();
2157 if (state != gain_auto->automation_state()) {
2159 _last_automation_snapshot = 0;
2160 gain_auto->set_automation_state (state);
2163 // FIXME: shouldn't this use Curve?
2164 set_gain (gain_auto->eval (_session.transport_frame()), this);
2170 _session.set_dirty ();
2174 Automatable::set_parameter_automation_state(param, state);
2179 IO::inc_gain (gain_t factor, void *src)
2181 if (_desired_gain == 0.0f)
2182 set_gain (0.000001f + (0.000001f * factor), src);
2184 set_gain (_desired_gain + (_desired_gain * factor), src);
2188 IO::set_gain (gain_t val, void *src)
2190 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2191 if (val > 1.99526231f)
2194 if (src != _gain_control.get()) {
2195 _gain_control->set_value(val);
2196 // bit twisty, this will come back and call us again
2197 // (this keeps control in sync with reality)
2202 Glib::Mutex::Lock dm (declick_lock);
2203 _desired_gain = val;
2206 if (_session.transport_stopped()) {
2210 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->list()->automation_write()) {
2211 _gain_control->list()->add (_session.transport_frame(), val);
2215 _session.set_dirty();
2219 IO::start_pan_touch (uint32_t which)
2221 if (which < _panner->size()) {
2222 (*_panner)[which]->pan_control()->list()->start_touch();
2227 IO::end_pan_touch (uint32_t which)
2229 if (which < _panner->size()) {
2230 (*_panner)[which]->pan_control()->list()->stop_touch();
2236 IO::automation_snapshot (nframes_t now, bool force)
2238 Automatable::automation_snapshot (now, force);
2240 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2241 _panner->snapshot (now);
2244 _panner->snapshot (now);
2245 _last_automation_snapshot = now;
2249 IO::transport_stopped (nframes_t frame)
2251 _gain_control->list()->reposition_for_rt_add (frame);
2253 if (_gain_control->list()->automation_state() != Off) {
2255 /* the src=0 condition is a special signal to not propagate
2256 automation gain changes into the mix group when locating.
2259 // FIXME: shouldn't this use Curve?
2260 set_gain (_gain_control->list()->eval (frame), 0);
2263 _panner->transport_stopped (frame);
2267 IO::build_legal_port_name (DataType type, bool in)
2269 const int name_size = jack_port_name_size();
2274 if (type == DataType::AUDIO) {
2275 suffix = _("audio");
2276 } else if (type == DataType::MIDI) {
2279 throw unknown_type();
2284 maxports = _input_maximum.get(type);
2286 suffix += _("_out");
2287 maxports = _output_maximum.get(type);
2290 if (maxports == 1) {
2291 // allow space for the slash + the suffix
2292 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2293 char buf[name_size+1];
2294 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2295 return string (buf);
2298 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2300 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2302 char buf1[name_size+1];
2303 char buf2[name_size+1];
2305 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2310 port_number = find_input_port_hole (buf1);
2312 port_number = find_output_port_hole (buf1);
2315 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2317 return string (buf2);
2321 IO::find_input_port_hole (const char* base)
2323 /* CALLER MUST HOLD IO LOCK */
2327 if (_inputs.empty()) {
2331 /* we only allow up to 4 characters for the port number
2334 for (n = 1; n < 9999; ++n) {
2335 char buf[jack_port_name_size()];
2336 PortSet::iterator i = _inputs.begin();
2338 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2340 for ( ; i != _inputs.end(); ++i) {
2341 if (i->short_name() == buf) {
2346 if (i == _inputs.end()) {
2354 IO::find_output_port_hole (const char* base)
2356 /* CALLER MUST HOLD IO LOCK */
2360 if (_outputs.empty()) {
2364 /* we only allow up to 4 characters for the port number
2367 for (n = 1; n < 9999; ++n) {
2368 char buf[jack_port_name_size()];
2369 PortSet::iterator i = _outputs.begin();
2371 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2373 for ( ; i != _outputs.end(); ++i) {
2374 if (i->short_name() == buf) {
2379 if (i == _outputs.end()) {
2388 IO::set_active (bool yn)
2391 active_changed(); /* EMIT SIGNAL */
2396 IO::audio_input(uint32_t n) const
2398 return dynamic_cast<AudioPort*>(input(n));
2402 IO::audio_output(uint32_t n) const
2404 return dynamic_cast<AudioPort*>(output(n));
2408 IO::midi_input(uint32_t n) const
2410 return dynamic_cast<MidiPort*>(input(n));
2414 IO::midi_output(uint32_t n) const
2416 return dynamic_cast<MidiPort*>(output(n));
2420 IO::set_phase_invert (bool yn, void *src)
2422 if (_phase_invert != yn) {
2424 // phase_invert_changed (src); /* EMIT SIGNAL */
2429 IO::set_denormal_protection (bool yn, void *src)
2431 if (_denormal_protection != yn) {
2432 _denormal_protection = yn;
2433 // denormal_protection_changed (src); /* EMIT SIGNAL */
2438 IO::update_port_total_latencies ()
2440 /* io_lock, not taken: function must be called from Session::process() calltree */
2442 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2443 _session.engine().update_total_latency (*i);
2446 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2447 _session.engine().update_total_latency (*i);
2453 * Setup bundles that describe our inputs and outputs.
2457 IO::setup_bundles_for_inputs_and_outputs ()
2461 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2462 _bundle_for_inputs->set_name (buf);
2463 uint32_t const ni = inputs().num_ports();
2464 _bundle_for_inputs->set_channels (ni);
2465 for (uint32_t i = 0; i < ni; ++i) {
2466 _bundle_for_inputs->set_port (i, inputs().port(i)->name());
2469 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2470 _bundle_for_outputs->set_name (buf);
2471 uint32_t const no = outputs().num_ports();
2472 _bundle_for_outputs->set_channels (no);
2473 for (uint32_t i = 0; i < no; ++i) {
2474 _bundle_for_outputs->set_port (i, outputs().port(i)->name());
2480 * Create and setup bundles that describe our inputs and outputs.
2484 IO::create_bundles_for_inputs_and_outputs ()
2486 _bundle_for_inputs = boost::shared_ptr<AutoBundle> (new AutoBundle (true));
2487 _bundle_for_outputs = boost::shared_ptr<AutoBundle> (new AutoBundle (false));
2488 setup_bundles_for_inputs_and_outputs ();
2491 /** Add a bundle to a list if is connected to our inputs.
2492 * @param b Bundle to check.
2493 * @param bundles List to add to.
2496 IO::maybe_add_input_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2498 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2499 if (ab == 0 || ab->ports_are_outputs() == false) {
2503 if (ab->nchannels () != n_inputs().n_total ()) {
2507 for (uint32_t i = 0; i < n_inputs().n_total (); ++i) {
2509 PortList const & pl = b->channel_ports (i);
2515 if (!input(i)->connected_to (pl[0])) {
2520 bundles->push_back (b);
2523 /** @return Bundles connected to our inputs */
2524 std::vector<boost::shared_ptr<Bundle> >
2525 IO::bundles_connected_to_inputs ()
2527 std::vector<boost::shared_ptr<Bundle> > bundles;
2530 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2531 bundles.push_back (i->bundle);
2535 _session.foreach_bundle (
2536 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles)
2543 /** Add a bundle to a list if is connected to our outputs.
2544 * @param b Bundle to check.
2545 * @param bundles List to add to.
2548 IO::maybe_add_output_bundle_to_list (boost::shared_ptr<Bundle> b, std::vector<boost::shared_ptr<Bundle> >* bundles)
2550 boost::shared_ptr<AutoBundle> ab = boost::dynamic_pointer_cast<AutoBundle, Bundle> (b);
2551 if (ab == 0 || ab->ports_are_inputs() == false) {
2555 if (ab->nchannels () != n_outputs().n_total ()) {
2559 for (uint32_t i = 0; i < n_outputs().n_total (); ++i) {
2561 PortList const & pl = b->channel_ports (i);
2567 if (!output(i)->connected_to (pl[0])) {
2572 bundles->push_back (b);
2576 /* @return Bundles connected to our outputs */
2577 std::vector<boost::shared_ptr<Bundle> >
2578 IO::bundles_connected_to_outputs ()
2580 std::vector<boost::shared_ptr<Bundle> > bundles;
2583 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2584 bundles.push_back (i->bundle);
2588 _session.foreach_bundle (
2589 sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles)
2596 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2599 configuration_will_change = b->ConfigurationWillChange.connect (
2600 sigc::mem_fun (*io, &IO::bundle_configuration_will_change)
2602 configuration_has_changed = b->ConfigurationHasChanged.connect (
2603 sigc::mem_fun (*io, &IO::bundle_configuration_has_changed)
2605 ports_will_change = b->PortsWillChange.connect (
2606 sigc::mem_fun (*io, &IO::bundle_ports_will_change)
2608 ports_have_changed = b->PortsHaveChanged.connect (
2609 sigc::mem_fun (*io, &IO::bundle_ports_have_changed)