2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
28 #include <glibmm/thread.h>
30 #include <pbd/xml++.h>
31 #include <pbd/replace_all.h>
32 #include <pbd/unknown_type.h>
34 #include <ardour/audioengine.h>
35 #include <ardour/io.h>
36 #include <ardour/route.h>
37 #include <ardour/port.h>
38 #include <ardour/audio_port.h>
39 #include <ardour/midi_port.h>
40 #include <ardour/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/buffer_set.h>
44 #include <ardour/meter.h>
45 #include <ardour/amp.h>
46 #include <ardour/user_bundle.h>
53 A bug in OS X's cmath that causes isnan() and isinf() to be
54 "undeclared". the following works around that
57 #if defined(__APPLE__) && defined(__MACH__)
58 extern "C" int isnan (double);
59 extern "C" int isinf (double);
62 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
65 using namespace ARDOUR;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,ChanCount> IO::PortCountChanged;
77 sigc::signal<int> IO::PortsCreated;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
100 /** @param default_type The type of port that will be created by ensure_io
101 * and friends if no type is explicitly requested (to avoid breakage).
103 IO::IO (Session& s, const string& name,
104 int input_min, int input_max, int output_min, int output_max,
105 DataType default_type)
106 : SessionObject(s, name),
107 AutomatableControls (s),
108 _output_buffers (new BufferSet()),
110 _default_type (default_type),
111 _input_minimum (ChanCount::ZERO),
112 _input_maximum (ChanCount::INFINITE),
113 _output_minimum (ChanCount::ZERO),
114 _output_maximum (ChanCount::INFINITE)
116 _panner = new Panner (name, _session);
117 _meter = new PeakMeter (_session);
120 _input_minimum = ChanCount(_default_type, input_min);
122 if (input_max >= 0) {
123 _input_maximum = ChanCount(_default_type, input_max);
125 if (output_min > 0) {
126 _output_minimum = ChanCount(_default_type, output_min);
128 if (output_max >= 0) {
129 _output_maximum = ChanCount(_default_type, output_max);
134 pending_state_node = 0;
135 no_panner_reset = false;
136 _phase_invert = false;
139 boost::shared_ptr<AutomationList> gl(
140 new AutomationList(Evoral::Parameter(GainAutomation)));
142 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
144 add_control(_gain_control);
146 apply_gain_automation = false;
149 // IO::Meter is emitted from another thread so the
150 // Meter signal must be protected.
151 Glib::Mutex::Lock guard (m_meter_signal_lock);
152 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
155 _session.add_controllable (_gain_control);
157 setup_bundles_for_inputs_and_outputs ();
160 IO::IO (Session& s, const XMLNode& node, DataType dt)
161 : SessionObject(s, "unnamed io"),
162 AutomatableControls (s),
163 _output_buffers (new BufferSet()),
167 _meter = new PeakMeter (_session);
170 no_panner_reset = false;
174 apply_gain_automation = false;
176 boost::shared_ptr<AutomationList> gl(
177 new AutomationList(Evoral::Parameter(GainAutomation)));
179 _gain_control = boost::shared_ptr<GainControl>(
180 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
182 add_control(_gain_control);
187 // IO::Meter is emitted from another thread so the
188 // Meter signal must be protected.
189 Glib::Mutex::Lock guard (m_meter_signal_lock);
190 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
193 _session.add_controllable (_gain_control);
195 setup_bundles_for_inputs_and_outputs ();
200 Glib::Mutex::Lock guard (m_meter_signal_lock);
201 Glib::Mutex::Lock lm (io_lock);
203 BLOCK_PROCESS_CALLBACK ();
205 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
206 _session.engine().unregister_port (*i);
209 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
210 _session.engine().unregister_port (*i);
213 m_meter_connection.disconnect();
220 IO::silence (nframes_t nframes, nframes_t offset)
222 /* io_lock, not taken: function must be called from Session::process() calltree */
224 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
225 i->get_buffer(nframes,offset).silence (nframes, offset);
229 /** Deliver bufs to the IO's output ports
231 * This function should automatically do whatever it necessary to correctly deliver bufs
232 * to the outputs, eg applying gain or pan or whatever else needs to be done.
235 IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
237 // FIXME: type specific code doesn't actually need to be here, it will go away in time
239 /* ********** AUDIO ********** */
241 // Apply gain if gain automation isn't playing
242 if ( ! apply_gain_automation) {
244 gain_t dg = _gain; // desired gain
247 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
255 if (dg != _gain || dg != 1.0) {
256 Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
261 /* do this so that any processing that comes after deliver_outputs()
262 can use the output buffers.
265 output_buffers().attach_buffers (_outputs, nframes, offset);
267 // Use the panner to distribute audio to output port buffers
269 if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
271 /* blech .. we shouldn't be creating and tearing this down every process()
272 cycle. XXX fix me to not waste cycles and do memory allocation etc.
275 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes, offset);
279 /* do a 1:1 copy of data to output ports */
281 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
282 copy_to_outputs (bufs, DataType::AUDIO, nframes, offset);
284 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
285 copy_to_outputs (bufs, DataType::MIDI, nframes, offset);
291 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
293 // Copy any buffers 1:1 to outputs
295 PortSet::iterator o = _outputs.begin(type);
296 BufferSet::iterator i = bufs.begin(type);
297 BufferSet::iterator prev = i;
299 while (i != bufs.end(type) && o != _outputs.end (type)) {
301 Buffer& port_buffer (o->get_buffer (nframes, offset));
302 port_buffer.read_from (*i, nframes, offset);
309 /* extra outputs get a copy of the last buffer */
311 while (o != _outputs.end(type)) {
312 Buffer& port_buffer (o->get_buffer (nframes, offset));
313 port_buffer.read_from(*prev, nframes, offset);
319 IO::collect_input (BufferSet& outs, nframes_t nframes, nframes_t offset)
321 assert(outs.available() >= n_inputs());
323 if (n_inputs() == ChanCount::ZERO)
326 outs.set_count(n_inputs());
328 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
330 BufferSet::iterator o = outs.begin(*t);
331 PortSet::iterator e = _inputs.end (*t);
332 for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
333 Buffer& b (i->get_buffer (nframes,offset));
334 o->read_from (b, nframes, offset);
341 IO::just_meter_input (nframes_t start_frame, nframes_t end_frame,
342 nframes_t nframes, nframes_t offset)
344 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
346 collect_input (bufs, nframes, offset);
348 _meter->run_in_place(bufs, start_frame, end_frame, nframes, offset);
353 IO::check_bundles_connected_to_inputs ()
355 check_bundles (_bundles_connected_to_inputs, inputs());
359 IO::check_bundles_connected_to_outputs ()
361 check_bundles (_bundles_connected_to_outputs, outputs());
365 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
367 std::vector<UserBundleInfo> new_list;
369 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
371 uint32_t const N = i->bundle->nchannels ();
373 if (ports.num_ports (default_type()) < N) {
379 for (uint32_t j = 0; j < N; ++j) {
380 /* Every port on bundle channel j must be connected to our input j */
381 Bundle::PortList const pl = i->bundle->channel_ports (j);
382 for (uint32_t k = 0; k < pl.size(); ++k) {
383 if (ports.port(j)->connected_to (pl[k]) == false) {
395 new_list.push_back (*i);
397 i->changed.disconnect ();
406 IO::disconnect_input (Port* our_port, string other_port, void* src)
408 if (other_port.length() == 0 || our_port == 0) {
413 BLOCK_PROCESS_CALLBACK ();
416 Glib::Mutex::Lock lm (io_lock);
418 /* check that our_port is really one of ours */
420 if ( ! _inputs.contains(our_port)) {
424 /* disconnect it from the source */
426 if (our_port->disconnect (other_port)) {
427 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
431 check_bundles_connected_to_inputs ();
435 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
436 _session.set_dirty ();
442 IO::connect_input (Port* our_port, string other_port, void* src)
444 if (other_port.length() == 0 || our_port == 0) {
449 BLOCK_PROCESS_CALLBACK ();
452 Glib::Mutex::Lock lm (io_lock);
454 /* check that our_port is really one of ours */
456 if ( ! _inputs.contains(our_port) ) {
460 /* connect it to the source */
462 if (our_port->connect (other_port)) {
468 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
469 _session.set_dirty ();
474 IO::disconnect_output (Port* our_port, string other_port, void* src)
476 if (other_port.length() == 0 || our_port == 0) {
481 BLOCK_PROCESS_CALLBACK ();
484 Glib::Mutex::Lock lm (io_lock);
486 /* check that our_port is really one of ours */
488 if ( ! _outputs.contains(our_port) ) {
492 /* disconnect it from the destination */
494 if (our_port->disconnect (other_port)) {
495 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
499 check_bundles_connected_to_outputs ();
503 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
504 _session.set_dirty ();
509 IO::connect_output (Port* our_port, string other_port, void* src)
511 if (other_port.length() == 0 || our_port == 0) {
516 BLOCK_PROCESS_CALLBACK ();
520 Glib::Mutex::Lock lm (io_lock);
522 /* check that our_port is really one of ours */
524 if ( ! _outputs.contains(our_port) ) {
528 /* connect it to the destination */
530 if (our_port->connect (other_port)) {
536 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
537 _session.set_dirty ();
542 IO::set_input (Port* other_port, void* src)
544 /* this removes all but one ports, and connects that one port
545 to the specified source.
548 if (_input_minimum.n_total() > 1) {
549 /* sorry, you can't do this */
553 if (other_port == 0) {
554 if (_input_minimum == ChanCount::ZERO) {
555 return ensure_inputs (ChanCount::ZERO, false, true, src);
561 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
565 return connect_input (_inputs.port(0), other_port->name(), src);
569 IO::remove_output_port (Port* port, void* src)
571 IOChange change (NoChange);
574 BLOCK_PROCESS_CALLBACK ();
578 Glib::Mutex::Lock lm (io_lock);
580 if (n_outputs() <= _output_minimum) {
581 /* sorry, you can't do this */
585 if (_outputs.remove(port)) {
586 change = IOChange (change|ConfigurationChanged);
588 if (port->connected()) {
589 change = IOChange (change|ConnectionsChanged);
592 _session.engine().unregister_port (*port);
593 check_bundles_connected_to_outputs ();
595 setup_peak_meters ();
600 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
603 if (change == ConfigurationChanged) {
604 setup_bundle_for_outputs ();
607 if (change != NoChange) {
608 output_changed (change, src);
609 _session.set_dirty ();
616 /** Add an output port.
618 * @param destination Name of input port to connect new port to.
619 * @param src Source for emitted ConfigurationChanged signal.
620 * @param type Data type of port. Default value (NIL) will use this IO's default type.
623 IO::add_output_port (string destination, void* src, DataType type)
627 if (type == DataType::NIL)
628 type = _default_type;
631 BLOCK_PROCESS_CALLBACK ();
635 Glib::Mutex::Lock lm (io_lock);
637 if (n_outputs() >= _output_maximum) {
641 /* Create a new output port */
643 string portname = build_legal_port_name (type, false);
645 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
646 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
650 _outputs.add (our_port);
651 setup_peak_meters ();
655 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
658 if (destination.length()) {
659 if (our_port->connect (destination)) {
664 // pan_changed (src); /* EMIT SIGNAL */
665 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
666 setup_bundle_for_outputs ();
667 _session.set_dirty ();
673 IO::remove_input_port (Port* port, void* src)
675 IOChange change (NoChange);
678 BLOCK_PROCESS_CALLBACK ();
682 Glib::Mutex::Lock lm (io_lock);
684 if (n_inputs() <= _input_minimum) {
685 /* sorry, you can't do this */
689 if (_inputs.remove(port)) {
690 change = IOChange (change|ConfigurationChanged);
692 if (port->connected()) {
693 change = IOChange (change|ConnectionsChanged);
696 _session.engine().unregister_port (*port);
697 check_bundles_connected_to_inputs ();
699 setup_peak_meters ();
704 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
707 if (change == ConfigurationChanged) {
708 setup_bundle_for_inputs ();
711 if (change != NoChange) {
712 input_changed (change, src);
713 _session.set_dirty ();
721 /** Add an input port.
723 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
724 * @param destination Name of input port to connect new port to.
725 * @param src Source for emitted ConfigurationChanged signal.
728 IO::add_input_port (string source, void* src, DataType type)
732 if (type == DataType::NIL)
733 type = _default_type;
736 BLOCK_PROCESS_CALLBACK ();
739 Glib::Mutex::Lock lm (io_lock);
741 if (_input_maximum.get(type) >= 0 && n_inputs().get (type) >= _input_maximum.get (type)) {
745 /* Create a new input port */
747 string portname = build_legal_port_name (type, true);
749 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
750 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
754 _inputs.add (our_port);
755 setup_peak_meters ();
759 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
762 if (source.length()) {
764 if (our_port->connect (source)) {
769 // pan_changed (src); /* EMIT SIGNAL */
770 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
771 setup_bundle_for_inputs ();
772 _session.set_dirty ();
778 IO::disconnect_inputs (void* src)
781 BLOCK_PROCESS_CALLBACK ();
784 Glib::Mutex::Lock lm (io_lock);
786 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
787 i->disconnect_all ();
790 check_bundles_connected_to_inputs ();
794 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
800 IO::disconnect_outputs (void* src)
803 BLOCK_PROCESS_CALLBACK ();
806 Glib::Mutex::Lock lm (io_lock);
808 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
809 i->disconnect_all ();
812 check_bundles_connected_to_outputs ();
816 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
817 _session.set_dirty ();
823 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
825 Port* input_port = 0;
826 bool changed = false;
829 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
831 const size_t n = count.get(*t);
833 /* remove unused ports */
834 for (size_t i = n_inputs().get(*t); i > n; --i) {
835 input_port = _inputs.port(*t, i-1);
838 _inputs.remove(input_port);
839 _session.engine().unregister_port (*input_port);
844 /* create any necessary new ports */
845 while (n_inputs().get(*t) < n) {
847 string portname = build_legal_port_name (*t, true);
851 if ((input_port = _session.engine().register_input_port (*t, portname)) == 0) {
852 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
857 catch (AudioEngine::PortRegistrationFailure& err) {
858 setup_peak_meters ();
861 throw AudioEngine::PortRegistrationFailure();
864 _inputs.add (input_port);
870 check_bundles_connected_to_inputs ();
871 setup_peak_meters ();
873 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
874 _session.set_dirty ();
878 /* disconnect all existing ports so that we get a fresh start */
879 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
880 i->disconnect_all ();
888 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
890 bool in_changed = false;
891 bool out_changed = false;
892 bool need_pan_reset = false;
894 in = min (_input_maximum, in);
896 out = min (_output_maximum, out);
898 if (in == n_inputs() && out == n_outputs() && !clear) {
903 BLOCK_PROCESS_CALLBACK ();
904 Glib::Mutex::Lock lm (io_lock);
908 if (n_outputs() != out) {
909 need_pan_reset = true;
912 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
914 const size_t nin = in.get(*t);
915 const size_t nout = out.get(*t);
917 Port* output_port = 0;
918 Port* input_port = 0;
920 /* remove unused output ports */
921 for (size_t i = n_outputs().get(*t); i > nout; --i) {
922 output_port = _outputs.port(*t, i-1);
925 _outputs.remove(output_port);
926 _session.engine().unregister_port (*output_port);
931 /* remove unused input ports */
932 for (size_t i = n_inputs().get(*t); i > nin; --i) {
933 input_port = _inputs.port(*t, i-1);
936 _inputs.remove(input_port);
937 _session.engine().unregister_port (*input_port);
942 /* create any necessary new input ports */
944 while (n_inputs().get(*t) < nin) {
946 string portname = build_legal_port_name (*t, true);
949 if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
950 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
955 catch (AudioEngine::PortRegistrationFailure& err) {
956 setup_peak_meters ();
959 throw AudioEngine::PortRegistrationFailure();
966 /* create any necessary new output ports */
968 while (n_outputs().get(*t) < nout) {
970 string portname = build_legal_port_name (*t, false);
973 if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
974 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
979 catch (AudioEngine::PortRegistrationFailure& err) {
980 setup_peak_meters ();
983 throw AudioEngine::PortRegistrationFailure ();
993 /* disconnect all existing ports so that we get a fresh start */
995 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
996 i->disconnect_all ();
999 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1000 i->disconnect_all ();
1004 if (in_changed || out_changed) {
1005 setup_peak_meters ();
1011 check_bundles_connected_to_outputs ();
1012 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1013 setup_bundle_for_outputs ();
1017 check_bundles_connected_to_inputs ();
1018 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1019 setup_bundle_for_inputs ();
1022 if (in_changed || out_changed) {
1023 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
1024 _session.set_dirty ();
1031 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
1033 bool changed = false;
1035 count = min (_input_maximum, count);
1037 if (count == n_inputs() && !clear) {
1042 BLOCK_PROCESS_CALLBACK ();
1043 Glib::Mutex::Lock im (io_lock);
1044 changed = ensure_inputs_locked (count, clear, src);
1046 changed = ensure_inputs_locked (count, clear, src);
1050 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1051 setup_bundle_for_inputs ();
1052 _session.set_dirty ();
1058 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
1060 Port* output_port = 0;
1061 bool changed = false;
1062 bool need_pan_reset = false;
1064 if (n_outputs() != count) {
1065 need_pan_reset = true;
1068 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1070 const size_t n = count.get(*t);
1072 /* remove unused ports */
1073 for (size_t i = n_outputs().get(*t); i > n; --i) {
1074 output_port = _outputs.port(*t, i-1);
1076 assert(output_port);
1077 _outputs.remove(output_port);
1078 _session.engine().unregister_port (*output_port);
1083 /* create any necessary new ports */
1084 while (n_outputs().get(*t) < n) {
1086 string portname = build_legal_port_name (*t, false);
1088 if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
1089 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1093 _outputs.add (output_port);
1095 setup_peak_meters ();
1097 if (need_pan_reset) {
1104 check_bundles_connected_to_outputs ();
1105 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1106 _session.set_dirty ();
1110 /* disconnect all existing ports so that we get a fresh start */
1111 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1112 i->disconnect_all ();
1120 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1122 bool changed = false;
1124 if (_output_maximum < ChanCount::INFINITE) {
1125 count = min (_output_maximum, count);
1126 if (count == n_outputs() && !clear) {
1131 /* XXX caller should hold io_lock, but generally doesn't */
1134 BLOCK_PROCESS_CALLBACK ();
1135 Glib::Mutex::Lock im (io_lock);
1136 changed = ensure_outputs_locked (count, clear, src);
1138 changed = ensure_outputs_locked (count, clear, src);
1142 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1143 setup_bundle_for_outputs ();
1150 IO::effective_gain () const
1152 if (_gain_control->automation_playback()) {
1153 return _gain_control->get_value();
1155 return _desired_gain;
1162 if (panners_legal) {
1163 if (!no_panner_reset) {
1164 _panner->reset (n_outputs().n_audio(), pans_required());
1167 panner_legal_c.disconnect ();
1168 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1173 IO::panners_became_legal ()
1175 _panner->reset (n_outputs().n_audio(), pans_required());
1176 _panner->load (); // automation
1177 panner_legal_c.disconnect ();
1182 IO::defer_pan_reset ()
1184 no_panner_reset = true;
1188 IO::allow_pan_reset ()
1190 no_panner_reset = false;
1196 IO::get_state (void)
1198 return state (true);
1202 IO::state (bool full_state)
1204 XMLNode* node = new XMLNode (state_node_name);
1207 vector<string>::iterator ci;
1209 LocaleGuard lg (X_("POSIX"));
1210 Glib::Mutex::Lock lm (io_lock);
1212 node->add_property("name", _name);
1213 id().print (buf, sizeof (buf));
1214 node->add_property("id", buf);
1217 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1218 i != _bundles_connected_to_inputs.end();
1222 XMLNode* n = new XMLNode ("InputBundle");
1223 n->add_property ("name", i->bundle->name ());
1224 node->add_child_nocopy (*n);
1228 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1229 i != _bundles_connected_to_outputs.end();
1233 XMLNode* n = new XMLNode ("OutputBundle");
1234 n->add_property ("name", i->bundle->name ());
1235 node->add_child_nocopy (*n);
1240 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1242 vector<string> connections;
1244 if (i->get_connections (connections)) {
1248 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1253 /* if its a connection to our own port,
1254 return only the port name, not the
1255 whole thing. this allows connections
1256 to be re-established even when our
1257 client name is different.
1260 str += _session.engine().make_port_name_relative (*ci);
1270 node->add_property ("inputs", str);
1274 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1276 vector<string> connections;
1278 if (i->get_connections (connections)) {
1282 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1287 str += _session.engine().make_port_name_relative (*ci);
1297 node->add_property ("outputs", str);
1299 node->add_child_nocopy (_panner->state (full_state));
1300 node->add_child_nocopy (_gain_control->get_state ());
1302 snprintf (buf, sizeof(buf), "%2.12f", gain());
1303 node->add_property ("gain", buf);
1305 /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
1309 int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
1310 int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
1312 snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
1314 node->add_property ("iolimits", buf);
1319 node->add_child_nocopy (get_automation_state());
1325 IO::set_state (const XMLNode& node)
1327 const XMLProperty* prop;
1328 XMLNodeConstIterator iter;
1329 LocaleGuard lg (X_("POSIX"));
1331 /* force use of non-localized representation of decimal point,
1332 since we use it a lot in XML files and so forth.
1335 if (node.name() != state_node_name) {
1336 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1340 if ((prop = node.property ("name")) != 0) {
1341 _name = prop->value();
1342 /* used to set panner name with this, but no more */
1345 if ((prop = node.property ("id")) != 0) {
1346 _id = prop->value ();
1354 if ((prop = node.property ("iolimits")) != 0) {
1355 sscanf (prop->value().c_str(), "%d,%d,%d,%d",
1356 &in_min, &in_max, &out_min, &out_max);
1358 /* Correct for the difference between the way we write things to session files and the
1359 way things are described by ChanCount; see comments in io.h about what the different
1360 ChanCount values mean. */
1363 _input_minimum = ChanCount::ZERO;
1365 _input_minimum = ChanCount (_default_type, in_min);
1369 _input_maximum = ChanCount::INFINITE;
1371 _input_maximum = ChanCount (_default_type, in_max);
1375 _output_minimum = ChanCount::ZERO;
1377 _output_minimum = ChanCount (_default_type, out_min);
1381 _output_maximum = ChanCount::INFINITE;
1383 _output_maximum = ChanCount (_default_type, out_max);
1387 if ((prop = node.property ("gain")) != 0) {
1388 set_gain (atof (prop->value().c_str()), this);
1389 _gain = _desired_gain;
1392 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1393 /* old school automation handling */
1396 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1398 // Old school Panner.
1399 if ((*iter)->name() == "Panner") {
1401 _panner = new Panner (_name, _session);
1403 _panner->set_state (**iter);
1406 if ((*iter)->name() == "Processor") {
1407 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1409 _panner = new Panner (_name, _session);
1411 _panner->set_state (**iter);
1415 if ((*iter)->name() == X_("Automation")) {
1417 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1420 if ((*iter)->name() == X_("controllable")) {
1421 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1422 _gain_control->set_state (**iter);
1429 if (create_ports (node)) {
1435 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1439 _panner = new Panner( _name, _session );
1440 if (panners_legal) {
1443 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1446 if (connecting_legal) {
1448 if (make_connections (node)) {
1454 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1457 if (!ports_legal || !connecting_legal) {
1458 pending_state_node = new XMLNode (node);
1465 IO::load_automation (string path)
1470 uint32_t linecnt = 0;
1472 LocaleGuard lg (X_("POSIX"));
1474 fullpath = Glib::build_filename(_session.automation_dir(), path);
1476 in.open (fullpath.c_str());
1479 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1481 in.open (fullpath.c_str());
1484 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1489 clear_automation ();
1491 while (in.getline (line, sizeof(line), '\n')) {
1496 if (++linecnt == 1) {
1497 if (memcmp (line, "version", 7) == 0) {
1498 if (sscanf (line, "version %f", &version) != 1) {
1499 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1503 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1510 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1511 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1517 _gain_control->list()->fast_simple_add (when, value);
1527 /* older (pre-1.0) versions of ardour used this */
1531 warning << _("dubious automation event found (and ignored)") << endmsg;
1539 IO::connecting_became_legal ()
1543 if (pending_state_node == 0) {
1544 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1549 connection_legal_c.disconnect ();
1551 ret = make_connections (*pending_state_node);
1554 delete pending_state_node;
1555 pending_state_node = 0;
1561 IO::ports_became_legal ()
1565 if (pending_state_node == 0) {
1566 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1571 port_legal_c.disconnect ();
1573 ret = create_ports (*pending_state_node);
1575 if (connecting_legal) {
1576 delete pending_state_node;
1577 pending_state_node = 0;
1583 boost::shared_ptr<Bundle>
1584 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1586 static const string digits = "0123456789";
1588 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1591 int bundle_number, mask;
1592 string possible_name;
1593 bool stereo = false;
1594 string::size_type last_non_digit_pos;
1596 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1599 // find numeric suffix of desired name
1602 last_non_digit_pos = desired_name.find_last_not_of(digits);
1604 if (last_non_digit_pos != string::npos) {
1606 s << desired_name.substr(last_non_digit_pos);
1610 // see if it's a stereo connection e.g. "in 3+4"
1612 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1613 int left_bundle_number = 0;
1614 string::size_type left_last_non_digit_pos;
1616 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1618 if (left_last_non_digit_pos != string::npos) {
1620 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1621 s >> left_bundle_number;
1623 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1634 // find highest set bit
1636 while ((mask <= bundle_number) && (mask <<= 1));
1638 // "wrap" bundle number into largest possible power of 2
1643 if (bundle_number & mask) {
1644 bundle_number &= ~mask;
1647 s << default_name << " " << bundle_number + 1;
1650 s << "+" << bundle_number + 2;
1653 possible_name = s.str();
1655 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1662 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1665 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1676 IO::create_ports (const XMLNode& node)
1678 XMLProperty const * prop;
1679 uint32_t num_inputs = 0;
1680 uint32_t num_outputs = 0;
1682 if ((prop = node.property ("input-connection")) != 0) {
1684 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1690 num_inputs = c->nchannels();
1692 } else if ((prop = node.property ("inputs")) != 0) {
1694 num_inputs = count (prop->value().begin(), prop->value().end(), '{');
1697 if ((prop = node.property ("output-connection")) != 0) {
1699 boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
1705 num_outputs = c->nchannels ();
1707 } else if ((prop = node.property ("outputs")) != 0) {
1709 num_outputs = count (prop->value().begin(), prop->value().end(), '{');
1712 no_panner_reset = true;
1714 if (ensure_io (ChanCount (_default_type, num_inputs),
1715 ChanCount (_default_type, num_outputs),
1718 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1722 no_panner_reset = false;
1724 set_deferred_state ();
1732 IO::make_connections (const XMLNode& node)
1735 const XMLProperty* prop;
1737 if ((prop = node.property ("input-connection")) != 0) {
1738 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1744 connect_input_ports_to_bundle (c, this);
1746 } else if ((prop = node.property ("inputs")) != 0) {
1747 if (set_inputs (prop->value())) {
1748 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1753 if ((prop = node.property ("output-connection")) != 0) {
1754 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1760 connect_output_ports_to_bundle (c, this);
1762 } else if ((prop = node.property ("outputs")) != 0) {
1763 if (set_outputs (prop->value())) {
1764 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1769 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1771 if ((*i)->name() == "InputBundle") {
1772 XMLProperty const * prop = (*i)->property ("name");
1774 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1776 connect_input_ports_to_bundle (b, this);
1780 } else if ((*i)->name() == "OutputBundle") {
1781 XMLProperty const * prop = (*i)->property ("name");
1783 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1785 connect_output_ports_to_bundle (b, this);
1795 IO::set_inputs (const string& str)
1797 vector<string> ports;
1802 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1806 // FIXME: audio-only
1807 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1811 string::size_type start, end, ostart;
1818 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1821 if ((end = str.find_first_of ('}', start)) == string::npos) {
1822 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1826 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1827 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1833 for (int x = 0; x < n; ++x) {
1834 connect_input (input (i), ports[x], this);
1846 IO::set_outputs (const string& str)
1848 vector<string> ports;
1853 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1857 // FIXME: audio-only
1858 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1862 string::size_type start, end, ostart;
1869 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1872 if ((end = str.find_first_of ('}', start)) == string::npos) {
1873 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1877 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1878 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1884 for (int x = 0; x < n; ++x) {
1885 connect_output (output (i), ports[x], this);
1897 IO::parse_io_string (const string& str, vector<string>& ports)
1899 string::size_type pos, opos;
1901 if (str.length() == 0) {
1910 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1911 ports.push_back (str.substr (opos, pos - opos));
1915 if (opos < str.length()) {
1916 ports.push_back (str.substr(opos));
1919 return ports.size();
1923 IO::parse_gain_string (const string& str, vector<string>& ports)
1925 string::size_type pos, opos;
1931 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1932 ports.push_back (str.substr (opos, pos - opos));
1936 if (opos < str.length()) {
1937 ports.push_back (str.substr(opos));
1940 return ports.size();
1944 IO::set_name (const string& requested_name)
1946 if (requested_name == _name) {
1952 if ( (rt = dynamic_cast<Route *>(this))) {
1953 name = Route::ensure_track_or_route_name(requested_name, _session);
1955 name = requested_name;
1959 /* replace all colons in the name. i wish we didn't have to do this */
1961 if (replace_all (name, ":", "-")) {
1962 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1965 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1966 string current_name = i->name();
1967 current_name.replace (current_name.find (_name), _name.length(), name);
1968 i->set_name (current_name);
1971 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1972 string current_name = i->name();
1973 current_name.replace (current_name.find (_name), _name.length(), name);
1974 i->set_name (current_name);
1977 bool const r = SessionObject::set_name(name);
1979 setup_bundles_for_inputs_and_outputs ();
1985 IO::set_input_minimum (ChanCount n)
1991 IO::set_input_maximum (ChanCount n)
1997 IO::set_output_minimum (ChanCount n)
1999 _output_minimum = n;
2003 IO::set_output_maximum (ChanCount n)
2005 _output_maximum = n;
2009 IO::set_port_latency (nframes_t nframes)
2011 Glib::Mutex::Lock lm (io_lock);
2013 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2014 i->set_latency (nframes);
2019 IO::output_latency () const
2021 nframes_t max_latency;
2026 /* io lock not taken - must be protected by other means */
2028 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2029 if ((latency = i->total_latency ()) > max_latency) {
2030 max_latency = latency;
2038 IO::input_latency () const
2040 nframes_t max_latency;
2045 /* io lock not taken - must be protected by other means */
2047 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2048 if ((latency = i->total_latency ()) > max_latency) {
2049 max_latency = latency;
2057 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2060 BLOCK_PROCESS_CALLBACK ();
2061 Glib::Mutex::Lock lm2 (io_lock);
2063 c->connect (_bundle_for_inputs, _session.engine());
2065 /* If this is a UserBundle, make a note of what we've done */
2067 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2070 /* See if we already know about this one */
2071 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2072 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2076 if (i == _bundles_connected_to_inputs.end()) {
2077 /* We don't, so make a note */
2078 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
2083 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2088 IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2091 BLOCK_PROCESS_CALLBACK ();
2092 Glib::Mutex::Lock lm2 (io_lock);
2094 c->disconnect (_bundle_for_inputs, _session.engine());
2096 /* If this is a UserBundle, make a note of what we've done */
2098 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2101 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
2102 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
2106 if (i != _bundles_connected_to_inputs.end()) {
2107 _bundles_connected_to_inputs.erase (i);
2112 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2117 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
2120 BLOCK_PROCESS_CALLBACK ();
2121 Glib::Mutex::Lock lm2 (io_lock);
2123 c->connect (_bundle_for_outputs, _session.engine());
2125 /* If this is a UserBundle, make a note of what we've done */
2127 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2130 /* See if we already know about this one */
2131 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2132 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2136 if (i == _bundles_connected_to_outputs.end()) {
2137 /* We don't, so make a note */
2138 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2143 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2149 IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2152 BLOCK_PROCESS_CALLBACK ();
2153 Glib::Mutex::Lock lm2 (io_lock);
2155 c->disconnect (_bundle_for_outputs, _session.engine());
2157 /* If this is a UserBundle, make a note of what we've done */
2159 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2162 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2163 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2167 if (i != _bundles_connected_to_outputs.end()) {
2168 _bundles_connected_to_outputs.erase (i);
2173 output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2179 IO::disable_connecting ()
2181 connecting_legal = false;
2186 IO::enable_connecting ()
2188 connecting_legal = true;
2189 return ConnectingLegal ();
2193 IO::disable_ports ()
2195 ports_legal = false;
2203 return PortsLegal ();
2207 IO::disable_panners (void)
2209 panners_legal = false;
2214 IO::reset_panners ()
2216 panners_legal = true;
2217 return PannersLegal ();
2221 IO::bundle_changed (Bundle::Change c)
2224 // connect_input_ports_to_bundle (_input_bundle, this);
2228 IO::GainControl::set_value (float val)
2230 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2231 if (val > 1.99526231f)
2234 _io->set_gain (val, this);
2236 AutomationControl::set_value(val);
2240 IO::GainControl::get_value (void) const
2242 return AutomationControl::get_value();
2246 IO::setup_peak_meters()
2248 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2249 _meter->configure_io (max_streams, max_streams);
2253 Update the peak meters.
2255 The meter signal lock is taken to prevent modification of the
2256 Meter signal while updating the meters, taking the meter signal
2257 lock prior to taking the io_lock ensures that all IO will remain
2258 valid while metering.
2263 Glib::Mutex::Lock guard (m_meter_signal_lock);
2264 Meter(); /* EMIT SIGNAL */
2270 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2272 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2277 IO::clear_automation ()
2279 data().clear (); // clears gain automation
2280 _panner->data().clear();
2284 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2286 // XXX: would be nice to get rid of this special hack
2288 if (param.type() == GainAutomation) {
2290 bool changed = false;
2293 Glib::Mutex::Lock lm (control_lock());
2295 boost::shared_ptr<AutomationList> gain_auto
2296 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2298 if (state != gain_auto->automation_state()) {
2300 _last_automation_snapshot = 0;
2301 gain_auto->set_automation_state (state);
2304 // FIXME: shouldn't this use Curve?
2305 set_gain (gain_auto->eval (_session.transport_frame()), this);
2311 _session.set_dirty ();
2315 AutomatableControls::set_parameter_automation_state(param, state);
2320 IO::inc_gain (gain_t factor, void *src)
2322 if (_desired_gain == 0.0f)
2323 set_gain (0.000001f + (0.000001f * factor), src);
2325 set_gain (_desired_gain + (_desired_gain * factor), src);
2329 IO::set_gain (gain_t val, void *src)
2331 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2332 if (val > 1.99526231f) {
2336 //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2338 if (src != _gain_control.get()) {
2339 _gain_control->set_value(val);
2340 // bit twisty, this will come back and call us again
2341 // (this keeps control in sync with reality)
2346 Glib::Mutex::Lock dm (declick_lock);
2347 _desired_gain = val;
2350 if (_session.transport_stopped()) {
2355 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2356 _gain_control->list()->add (_session.transport_frame(), val);
2361 _session.set_dirty();
2365 IO::start_pan_touch (uint32_t which)
2367 if (which < _panner->npanners()) {
2368 (*_panner).pan_control(which)->start_touch();
2373 IO::end_pan_touch (uint32_t which)
2375 if (which < _panner->npanners()) {
2376 (*_panner).pan_control(which)->stop_touch();
2382 IO::automation_snapshot (nframes_t now, bool force)
2384 AutomatableControls::automation_snapshot (now, force);
2385 // XXX: This seems to be wrong.
2386 // drobilla: shouldnt automation_snapshot for panner be called
2387 // "automagically" because its an Automatable now ?
2389 // we could dump this whole method then. <3
2391 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2392 _panner->automation_snapshot (now, force);
2395 _panner->automation_snapshot (now, force);
2396 _last_automation_snapshot = now;
2400 IO::transport_stopped (nframes_t frame)
2402 _gain_control->list()->reposition_for_rt_add (frame);
2404 if (_gain_control->automation_state() != Off) {
2406 /* the src=0 condition is a special signal to not propagate
2407 automation gain changes into the mix group when locating.
2410 // FIXME: shouldn't this use Curve?
2411 set_gain (_gain_control->list()->eval (frame), 0);
2414 _panner->transport_stopped (frame);
2418 IO::build_legal_port_name (DataType type, bool in)
2420 const int name_size = jack_port_name_size();
2425 if (type == DataType::AUDIO) {
2426 suffix = _("audio");
2427 } else if (type == DataType::MIDI) {
2430 throw unknown_type();
2435 maxports = _input_maximum.get(type);
2437 suffix += _("_out");
2438 maxports = _output_maximum.get(type);
2441 if (maxports == 1) {
2442 // allow space for the slash + the suffix
2443 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 1);
2444 char buf[name_size+1];
2445 snprintf (buf, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2446 return string (buf);
2449 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2451 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2453 char buf1[name_size+1];
2454 char buf2[name_size+1];
2456 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2461 port_number = find_input_port_hole (buf1);
2463 port_number = find_output_port_hole (buf1);
2466 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2468 return string (buf2);
2472 IO::find_input_port_hole (const char* base)
2474 /* CALLER MUST HOLD IO LOCK */
2478 if (_inputs.empty()) {
2482 /* we only allow up to 4 characters for the port number
2485 for (n = 1; n < 9999; ++n) {
2486 char buf[jack_port_name_size()];
2487 PortSet::iterator i = _inputs.begin();
2489 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2491 for ( ; i != _inputs.end(); ++i) {
2492 if (i->name() == buf) {
2497 if (i == _inputs.end()) {
2505 IO::find_output_port_hole (const char* base)
2507 /* CALLER MUST HOLD IO LOCK */
2511 if (_outputs.empty()) {
2515 /* we only allow up to 4 characters for the port number
2518 for (n = 1; n < 9999; ++n) {
2519 char buf[jack_port_name_size()];
2520 PortSet::iterator i = _outputs.begin();
2522 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2524 for ( ; i != _outputs.end(); ++i) {
2525 if (i->name() == buf) {
2530 if (i == _outputs.end()) {
2539 IO::set_active (bool yn)
2542 active_changed(); /* EMIT SIGNAL */
2546 IO::audio_input(uint32_t n) const
2548 return dynamic_cast<AudioPort*>(input(n));
2552 IO::audio_output(uint32_t n) const
2554 return dynamic_cast<AudioPort*>(output(n));
2558 IO::midi_input(uint32_t n) const
2560 return dynamic_cast<MidiPort*>(input(n));
2564 IO::midi_output(uint32_t n) const
2566 return dynamic_cast<MidiPort*>(output(n));
2570 IO::set_phase_invert (bool yn, void *src)
2572 if (_phase_invert != yn) {
2574 // phase_invert_changed (src); /* EMIT SIGNAL */
2579 IO::set_denormal_protection (bool yn, void *src)
2581 if (_denormal_protection != yn) {
2582 _denormal_protection = yn;
2583 // denormal_protection_changed (src); /* EMIT SIGNAL */
2588 IO::update_port_total_latencies ()
2590 /* io_lock, not taken: function must be called from Session::process() calltree */
2592 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2593 _session.engine().update_total_latency (*i);
2596 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2597 _session.engine().update_total_latency (*i);
2603 * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
2607 IO::setup_bundles_for_inputs_and_outputs ()
2609 setup_bundle_for_inputs ();
2610 setup_bundle_for_outputs ();
2615 IO::setup_bundle_for_inputs ()
2619 if (!_bundle_for_inputs) {
2620 _bundle_for_inputs.reset (new Bundle (true));
2623 _bundle_for_inputs->suspend_signals ();
2625 _bundle_for_inputs->set_type (default_type ());
2627 _bundle_for_inputs->remove_channels ();
2629 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2630 _bundle_for_inputs->set_name (buf);
2631 uint32_t const ni = inputs().num_ports();
2632 for (uint32_t i = 0; i < ni; ++i) {
2633 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2634 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2637 _bundle_for_inputs->resume_signals ();
2642 IO::setup_bundle_for_outputs ()
2646 if (!_bundle_for_outputs) {
2647 _bundle_for_outputs.reset (new Bundle (false));
2650 _bundle_for_outputs->suspend_signals ();
2652 _bundle_for_outputs->set_type (default_type ());
2654 _bundle_for_outputs->remove_channels ();
2656 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2657 _bundle_for_outputs->set_name (buf);
2658 uint32_t const no = outputs().num_ports();
2659 for (uint32_t i = 0; i < no; ++i) {
2660 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2661 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2664 _bundle_for_outputs->resume_signals ();
2668 /** @return Bundles connected to our inputs */
2670 IO::bundles_connected_to_inputs ()
2675 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2676 bundles.push_back (i->bundle);
2679 /* Session bundles */
2680 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2681 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2682 if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
2683 bundles.push_back (*i);
2688 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2689 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2690 if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
2691 bundles.push_back ((*i)->bundle_for_outputs());
2699 /* @return Bundles connected to our outputs */
2701 IO::bundles_connected_to_outputs ()
2706 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2707 bundles.push_back (i->bundle);
2710 /* Session bundles */
2711 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2712 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2713 if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
2714 bundles.push_back (*i);
2719 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2720 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2721 if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
2722 bundles.push_back ((*i)->bundle_for_inputs());
2730 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2733 changed = b->Changed.connect (
2734 sigc::mem_fun (*io, &IO::bundle_changed)
2739 IO::prepare_inputs (nframes_t nframes, nframes_t offset)
2741 /* io_lock, not taken: function must be called from Session::process() calltree */
2745 IO::flush_outputs (nframes_t nframes, nframes_t offset)
2747 /* io_lock, not taken: function must be called from Session::process() calltree */
2748 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2750 /* Only run cycle_start() on output ports, because
2751 inputs must be done in the correct processing order,
2752 which requires interleaving with route processing.
2755 (*i).flush_buffers (nframes, offset);
2761 IO::bundle_channel_name (uint32_t c, uint32_t n) const
2769 return c == 0 ? _("L") : _("R");
2771 snprintf (buf, sizeof(buf), _("%d"), (c + 1));