2 Copyright (C) 2000-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
28 #include <glibmm/thread.h>
30 #include "pbd/xml++.h"
31 #include "pbd/replace_all.h"
32 #include "pbd/unknown_type.h"
34 #include "ardour/audioengine.h"
35 #include "ardour/io.h"
36 #include "ardour/route.h"
37 #include "ardour/port.h"
38 #include "ardour/audio_port.h"
39 #include "ardour/midi_port.h"
40 #include "ardour/session.h"
41 #include "ardour/cycle_timer.h"
42 #include "ardour/panner.h"
43 #include "ardour/buffer_set.h"
44 #include "ardour/meter.h"
45 #include "ardour/amp.h"
46 #include "ardour/user_bundle.h"
53 A bug in OS X's cmath that causes isnan() and isinf() to be
54 "undeclared". the following works around that
57 #if defined(__APPLE__) && defined(__MACH__)
58 extern "C" int isnan (double);
59 extern "C" int isinf (double);
62 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
65 using namespace ARDOUR;
68 const string IO::state_node_name = "IO";
69 bool IO::connecting_legal = false;
70 bool IO::ports_legal = false;
71 bool IO::panners_legal = false;
72 sigc::signal<void> IO::Meter;
73 sigc::signal<int> IO::ConnectingLegal;
74 sigc::signal<int> IO::PortsLegal;
75 sigc::signal<int> IO::PannersLegal;
76 sigc::signal<void,ChanCount> IO::PortCountChanged;
77 sigc::signal<void,nframes_t> IO::CycleStart;
79 Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
81 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
82 others can be imagined.
86 static gain_t direct_control_to_gain (double fract) {
87 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
88 /* this maxes at +6dB */
89 return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
92 static double direct_gain_to_control (gain_t gain) {
93 /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
94 if (gain == 0) return 0.0;
96 return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
100 /** @param default_type The type of port that will be created by ensure_io
101 * and friends if no type is explicitly requested (to avoid breakage).
103 IO::IO (Session& s, const string& name, DataType default_type)
104 : SessionObject (s, name)
105 , AutomatableControls (s)
106 , _output_buffers (new BufferSet())
108 , _default_type (default_type)
109 , _amp (new Amp(s, *this))
110 , _meter (new PeakMeter(s))
111 , _panner (new Panner(name, s))
114 pending_state_node = 0;
115 no_panner_reset = false;
116 _phase_invert = false;
119 boost::shared_ptr<AutomationList> gl(
120 new AutomationList(Evoral::Parameter(GainAutomation)));
122 _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
124 add_control(_gain_control);
127 // IO::Meter is emitted from another thread so the
128 // Meter signal must be protected.
129 Glib::Mutex::Lock guard (m_meter_signal_lock);
130 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
134 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
136 _session.add_controllable (_gain_control);
138 setup_bundles_for_inputs_and_outputs ();
141 IO::IO (Session& s, const XMLNode& node, DataType dt)
142 : SessionObject(s, "unnamed io")
143 , AutomatableControls (s)
144 , _output_buffers (new BufferSet())
147 , _amp (new Amp(s, *this))
148 , _meter(new PeakMeter (_session))
151 no_panner_reset = false;
154 boost::shared_ptr<AutomationList> gl(
155 new AutomationList(Evoral::Parameter(GainAutomation)));
157 _gain_control = boost::shared_ptr<GainControl>(
158 new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
160 add_control(_gain_control);
165 // IO::Meter is emitted from another thread so the
166 // Meter signal must be protected.
167 Glib::Mutex::Lock guard (m_meter_signal_lock);
168 m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
172 CycleStart.connect (mem_fun (*this, &IO::cycle_start));
174 _session.add_controllable (_gain_control);
176 setup_bundles_for_inputs_and_outputs ();
181 Glib::Mutex::Lock guard (m_meter_signal_lock);
182 Glib::Mutex::Lock lm (io_lock);
184 BLOCK_PROCESS_CALLBACK ();
186 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
187 _session.engine().unregister_port (*i);
190 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
191 _session.engine().unregister_port (*i);
194 m_meter_connection.disconnect();
198 IO::silence (nframes_t nframes)
200 /* io_lock, not taken: function must be called from Session::process() calltree */
202 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
203 i->get_buffer(nframes).silence (nframes);
207 /** Deliver bufs to the IO's output ports
209 * This function should automatically do whatever it necessary to correctly deliver bufs
210 * to the outputs, eg applying gain or pan or whatever else needs to be done.
213 IO::deliver_output (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
215 // Attach output buffers to port buffers
216 output_buffers().attach_buffers (_outputs, nframes, _output_offset);
218 // Use the panner to distribute audio to output port buffers
219 if (_panner && _panner->npanners() && !_panner->bypassed()) {
221 _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes);
223 // Do a 1:1 copy of data to output ports
225 if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
226 copy_to_outputs (bufs, DataType::AUDIO, nframes);
228 if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
229 copy_to_outputs (bufs, DataType::MIDI, nframes);
233 // Apply gain to output buffers if gain automation isn't playing
234 if ( ! _amp->apply_gain_automation()) {
236 gain_t dg = _gain; // desired gain
239 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
242 dg = _gain_control->user_float();
247 if (dg != _gain || dg != 1.0) {
248 Amp::apply_gain(output_buffers(), nframes, _gain, dg, _phase_invert);
256 IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
258 // Copy any buffers 1:1 to outputs
260 PortSet::iterator o = _outputs.begin(type);
261 BufferSet::iterator i = bufs.begin(type);
262 BufferSet::iterator prev = i;
264 while (i != bufs.end(type) && o != _outputs.end (type)) {
265 Buffer& port_buffer (o->get_buffer (nframes));
266 port_buffer.read_from (*i, nframes, _output_offset);
272 // Copy last buffer to any extra outputs
273 while (o != _outputs.end(type)) {
274 Buffer& port_buffer (o->get_buffer (nframes));
275 port_buffer.read_from (*prev, nframes, _output_offset);
281 IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset)
283 assert(outs.available() >= n_inputs());
285 if (n_inputs() == ChanCount::ZERO) {
289 outs.set_count(n_inputs());
291 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
292 PortSet::iterator i = _inputs.begin(*t);
293 BufferSet::iterator o = outs.begin(*t);
295 for (uint32_t off = 0; off < offset.get(*t); ++off, ++o) {
296 if (o == outs.end(*t)) {
301 for ( ; i != _inputs.end(*t); ++i, ++o) {
302 Buffer& b (i->get_buffer (nframes));
303 o->read_from (b, nframes);
309 IO::just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
311 BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
312 collect_input (bufs, nframes);
313 _meter->run_in_place (bufs, start_frame, end_frame, nframes);
318 IO::check_bundles_connected_to_inputs ()
320 check_bundles (_bundles_connected_to_inputs, inputs());
324 IO::check_bundles_connected_to_outputs ()
326 check_bundles (_bundles_connected_to_outputs, outputs());
330 IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
332 std::vector<UserBundleInfo> new_list;
334 for (std::vector<UserBundleInfo>::iterator i = list.begin(); i != list.end(); ++i) {
336 uint32_t const N = i->bundle->nchannels ();
338 if (ports.num_ports (default_type()) < N) {
344 for (uint32_t j = 0; j < N; ++j) {
345 /* Every port on bundle channel j must be connected to our input j */
346 Bundle::PortList const pl = i->bundle->channel_ports (j);
347 for (uint32_t k = 0; k < pl.size(); ++k) {
348 if (ports.port(j)->connected_to (pl[k]) == false) {
360 new_list.push_back (*i);
362 i->changed.disconnect ();
371 IO::disconnect_input (Port* our_port, string other_port, void* src)
373 if (other_port.length() == 0 || our_port == 0) {
378 BLOCK_PROCESS_CALLBACK ();
381 Glib::Mutex::Lock lm (io_lock);
383 /* check that our_port is really one of ours */
385 if ( ! _inputs.contains(our_port)) {
389 /* disconnect it from the source */
391 if (our_port->disconnect (other_port)) {
392 error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
396 check_bundles_connected_to_inputs ();
400 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
401 _session.set_dirty ();
407 IO::connect_input (Port* our_port, string other_port, void* src)
409 if (other_port.length() == 0 || our_port == 0) {
414 BLOCK_PROCESS_CALLBACK ();
417 Glib::Mutex::Lock lm (io_lock);
419 /* check that our_port is really one of ours */
421 if ( ! _inputs.contains(our_port) ) {
425 /* connect it to the source */
427 if (our_port->connect (other_port)) {
433 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
434 _session.set_dirty ();
439 IO::disconnect_output (Port* our_port, string other_port, void* src)
441 if (other_port.length() == 0 || our_port == 0) {
446 BLOCK_PROCESS_CALLBACK ();
449 Glib::Mutex::Lock lm (io_lock);
451 /* check that our_port is really one of ours */
453 if ( ! _outputs.contains(our_port) ) {
457 /* disconnect it from the destination */
459 if (our_port->disconnect (other_port)) {
460 error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
464 check_bundles_connected_to_outputs ();
468 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
469 _session.set_dirty ();
474 IO::connect_output (Port* our_port, string other_port, void* src)
476 if (other_port.length() == 0 || our_port == 0) {
481 BLOCK_PROCESS_CALLBACK ();
485 Glib::Mutex::Lock lm (io_lock);
487 /* check that our_port is really one of ours */
489 if ( ! _outputs.contains(our_port) ) {
493 /* connect it to the destination */
495 if (our_port->connect (other_port)) {
501 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
502 _session.set_dirty ();
507 IO::set_input (Port* other_port, void* src)
509 /* this removes all but one ports, and connects that one port
510 to the specified source.
517 if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
521 return connect_input (_inputs.port(0), other_port->name(), src);
525 IO::remove_output_port (Port* port, void* src)
527 IOChange change (NoChange);
530 BLOCK_PROCESS_CALLBACK ();
534 Glib::Mutex::Lock lm (io_lock);
536 if (_outputs.remove(port)) {
537 change = IOChange (change|ConfigurationChanged);
539 if (port->connected()) {
540 change = IOChange (change|ConnectionsChanged);
543 _session.engine().unregister_port (*port);
544 check_bundles_connected_to_outputs ();
546 setup_peak_meters ();
551 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
554 if (change == ConfigurationChanged) {
555 setup_bundle_for_outputs ();
558 if (change != NoChange) {
559 output_changed (change, src);
560 _session.set_dirty ();
567 /** Add an output port.
569 * @param destination Name of input port to connect new port to.
570 * @param src Source for emitted ConfigurationChanged signal.
571 * @param type Data type of port. Default value (NIL) will use this IO's default type.
574 IO::add_output_port (string destination, void* src, DataType type)
578 if (type == DataType::NIL)
579 type = _default_type;
582 BLOCK_PROCESS_CALLBACK ();
586 Glib::Mutex::Lock lm (io_lock);
588 /* Create a new output port */
590 string portname = build_legal_port_name (type, false);
592 if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
593 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
597 _outputs.add (our_port);
598 setup_peak_meters ();
602 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
605 if (destination.length()) {
606 if (our_port->connect (destination)) {
611 // pan_changed (src); /* EMIT SIGNAL */
612 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
613 setup_bundle_for_outputs ();
614 _session.set_dirty ();
620 IO::remove_input_port (Port* port, void* src)
622 IOChange change (NoChange);
625 BLOCK_PROCESS_CALLBACK ();
629 Glib::Mutex::Lock lm (io_lock);
631 if (_inputs.remove(port)) {
632 change = IOChange (change|ConfigurationChanged);
634 if (port->connected()) {
635 change = IOChange (change|ConnectionsChanged);
638 _session.engine().unregister_port (*port);
639 check_bundles_connected_to_inputs ();
641 setup_peak_meters ();
646 PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
649 if (change == ConfigurationChanged) {
650 setup_bundle_for_inputs ();
653 if (change != NoChange) {
654 input_changed (change, src);
655 _session.set_dirty ();
663 /** Add an input port.
665 * @param type Data type of port. The appropriate port type, and @ref Port will be created.
666 * @param destination Name of input port to connect new port to.
667 * @param src Source for emitted ConfigurationChanged signal.
670 IO::add_input_port (string source, void* src, DataType type)
674 if (type == DataType::NIL)
675 type = _default_type;
678 BLOCK_PROCESS_CALLBACK ();
681 Glib::Mutex::Lock lm (io_lock);
683 /* Create a new input port */
685 string portname = build_legal_port_name (type, true);
687 if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
688 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
692 _inputs.add (our_port);
693 setup_peak_meters ();
697 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
700 if (source.length()) {
702 if (our_port->connect (source)) {
707 // pan_changed (src); /* EMIT SIGNAL */
708 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
709 setup_bundle_for_inputs ();
710 _session.set_dirty ();
716 IO::disconnect_inputs (void* src)
719 BLOCK_PROCESS_CALLBACK ();
722 Glib::Mutex::Lock lm (io_lock);
724 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
725 i->disconnect_all ();
728 check_bundles_connected_to_inputs ();
732 input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
738 IO::disconnect_outputs (void* src)
741 BLOCK_PROCESS_CALLBACK ();
744 Glib::Mutex::Lock lm (io_lock);
746 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
747 i->disconnect_all ();
750 check_bundles_connected_to_outputs ();
754 output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
755 _session.set_dirty ();
761 IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
763 Port* input_port = 0;
764 bool changed = false;
766 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
768 const size_t n = count.get(*t);
770 /* remove unused ports */
771 for (size_t i = n_inputs().get(*t); i > n; --i) {
772 input_port = _inputs.port(*t, i-1);
775 _inputs.remove(input_port);
776 _session.engine().unregister_port (*input_port);
781 /* create any necessary new ports */
782 while (n_inputs().get(*t) < n) {
784 string portname = build_legal_port_name (*t, true);
788 if ((input_port = _session.engine().register_input_port (*t, portname)) == 0) {
789 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
794 catch (AudioEngine::PortRegistrationFailure& err) {
795 setup_peak_meters ();
798 throw AudioEngine::PortRegistrationFailure();
801 _inputs.add (input_port);
807 check_bundles_connected_to_inputs ();
808 setup_peak_meters ();
810 PortCountChanged (n_inputs()); /* EMIT SIGNAL */
811 _session.set_dirty ();
815 /* disconnect all existing ports so that we get a fresh start */
816 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
817 i->disconnect_all ();
825 IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
827 bool in_changed = false;
828 bool out_changed = false;
830 assert(in != ChanCount::INFINITE);
831 assert(out != ChanCount::INFINITE);
833 if (in == n_inputs() && out == n_outputs() && !clear) {
838 BLOCK_PROCESS_CALLBACK ();
839 Glib::Mutex::Lock lm (io_lock);
843 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
845 const size_t nin = in.get(*t);
846 const size_t nout = out.get(*t);
848 Port* output_port = 0;
849 Port* input_port = 0;
851 /* remove unused output ports */
852 for (size_t i = n_outputs().get(*t); i > nout; --i) {
853 output_port = _outputs.port(*t, i-1);
856 _outputs.remove(output_port);
857 _session.engine().unregister_port (*output_port);
862 /* remove unused input ports */
863 for (size_t i = n_inputs().get(*t); i > nin; --i) {
864 input_port = _inputs.port(*t, i-1);
867 _inputs.remove(input_port);
868 _session.engine().unregister_port (*input_port);
873 /* create any necessary new input ports */
874 while (n_inputs().get(*t) < nin) {
875 string portname = build_legal_port_name (*t, true);
878 if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
879 error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
884 catch (AudioEngine::PortRegistrationFailure& err) {
885 setup_peak_meters ();
895 /* create any necessary new output ports */
897 while (n_outputs().get(*t) < nout) {
899 string portname = build_legal_port_name (*t, false);
902 if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
903 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
908 catch (AudioEngine::PortRegistrationFailure& err) {
909 setup_peak_meters ();
922 /* disconnect all existing ports so that we get a fresh start */
924 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
925 i->disconnect_all ();
928 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
929 i->disconnect_all ();
933 if (in_changed || out_changed) {
934 setup_peak_meters ();
940 check_bundles_connected_to_outputs ();
941 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
942 setup_bundle_for_outputs ();
946 check_bundles_connected_to_inputs ();
947 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
948 setup_bundle_for_inputs ();
951 if (in_changed || out_changed) {
952 PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
953 _session.set_dirty ();
960 IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
962 bool changed = false;
964 if (count == n_inputs() && !clear) {
969 BLOCK_PROCESS_CALLBACK ();
970 Glib::Mutex::Lock im (io_lock);
971 changed = ensure_inputs_locked (count, clear, src);
973 changed = ensure_inputs_locked (count, clear, src);
977 input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
978 setup_bundle_for_inputs ();
979 _session.set_dirty ();
985 IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
987 Port* output_port = 0;
988 bool changed = false;
989 bool need_pan_reset = false;
991 if (n_outputs() != count) {
992 need_pan_reset = true;
995 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
997 const size_t n = count.get(*t);
999 /* remove unused ports */
1000 for (size_t i = n_outputs().get(*t); i > n; --i) {
1001 output_port = _outputs.port(*t, i-1);
1003 assert(output_port);
1004 _outputs.remove(output_port);
1005 _session.engine().unregister_port (*output_port);
1010 /* create any necessary new ports */
1011 while (n_outputs().get(*t) < n) {
1013 string portname = build_legal_port_name (*t, false);
1015 if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
1016 error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
1020 _outputs.add (output_port);
1022 setup_peak_meters ();
1024 if (need_pan_reset) {
1031 check_bundles_connected_to_outputs ();
1032 PortCountChanged (n_outputs()); /* EMIT SIGNAL */
1033 _session.set_dirty ();
1037 /* disconnect all existing ports so that we get a fresh start */
1038 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1039 i->disconnect_all ();
1047 IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
1049 bool changed = false;
1051 /* XXX caller should hold io_lock, but generally doesn't */
1054 BLOCK_PROCESS_CALLBACK ();
1055 Glib::Mutex::Lock im (io_lock);
1056 changed = ensure_outputs_locked (count, clear, src);
1058 changed = ensure_outputs_locked (count, clear, src);
1062 output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
1063 setup_bundle_for_outputs ();
1070 IO::effective_gain () const
1072 return _gain_control->get_value();
1078 if (panners_legal) {
1079 if (!no_panner_reset) {
1080 _panner->reset (n_outputs().n_audio(), pans_required());
1083 panner_legal_c.disconnect ();
1084 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1089 IO::panners_became_legal ()
1091 _panner->reset (n_outputs().n_audio(), pans_required());
1092 _panner->load (); // automation
1093 panner_legal_c.disconnect ();
1098 IO::defer_pan_reset ()
1100 no_panner_reset = true;
1104 IO::allow_pan_reset ()
1106 no_panner_reset = false;
1112 IO::get_state (void)
1114 return state (true);
1118 IO::state (bool full_state)
1120 XMLNode* node = new XMLNode (state_node_name);
1123 vector<string>::iterator ci;
1125 LocaleGuard lg (X_("POSIX"));
1126 Glib::Mutex::Lock lm (io_lock);
1128 node->add_property("name", _name);
1129 id().print (buf, sizeof (buf));
1130 node->add_property("id", buf);
1133 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1134 i != _bundles_connected_to_inputs.end();
1138 XMLNode* n = new XMLNode ("InputBundle");
1139 n->add_property ("name", i->bundle->name ());
1140 node->add_child_nocopy (*n);
1144 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
1145 i != _bundles_connected_to_outputs.end();
1149 XMLNode* n = new XMLNode ("OutputBundle");
1150 n->add_property ("name", i->bundle->name ());
1151 node->add_child_nocopy (*n);
1156 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1158 vector<string> connections;
1160 if (i->get_connections (connections)) {
1164 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1169 /* if its a connection to our own port,
1170 return only the port name, not the
1171 whole thing. this allows connections
1172 to be re-established even when our
1173 client name is different.
1176 str += _session.engine().make_port_name_relative (*ci);
1186 node->add_property ("inputs", str);
1190 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1192 vector<string> connections;
1194 if (i->get_connections (connections)) {
1198 for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
1203 str += _session.engine().make_port_name_relative (*ci);
1213 node->add_property ("outputs", str);
1215 node->add_child_nocopy (_panner->state (full_state));
1216 node->add_child_nocopy (_gain_control->get_state ());
1218 snprintf (buf, sizeof(buf), "%2.12f", gain());
1219 node->add_property ("gain", buf);
1223 node->add_child_nocopy(*n_inputs().state("Inputs"));
1224 node->add_child_nocopy(*n_outputs().state("Outputs"));
1229 node->add_child_nocopy (get_automation_state());
1235 IO::set_state (const XMLNode& node)
1237 const XMLProperty* prop;
1238 XMLNodeConstIterator iter;
1239 LocaleGuard lg (X_("POSIX"));
1241 /* force use of non-localized representation of decimal point,
1242 since we use it a lot in XML files and so forth.
1245 if (node.name() != state_node_name) {
1246 error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
1250 if ((prop = node.property ("name")) != 0) {
1251 _name = prop->value();
1252 /* used to set panner name with this, but no more */
1255 if ((prop = node.property ("id")) != 0) {
1256 _id = prop->value ();
1259 if ((prop = node.property ("gain")) != 0) {
1260 set_gain (atof (prop->value().c_str()), this);
1261 _gain = _gain_control->user_float();
1264 if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
1265 /* old school automation handling */
1268 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1270 // Old school Panner.
1271 if ((*iter)->name() == "Panner") {
1273 _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
1275 _panner->set_state (**iter);
1278 if ((*iter)->name() == "Processor") {
1279 if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
1281 _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
1283 _panner->set_state (**iter);
1287 if ((*iter)->name() == X_("Automation")) {
1289 set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
1292 if ((*iter)->name() == X_("Controllable")) {
1293 if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
1294 _gain_control->set_state (**iter);
1301 if (create_ports (node)) {
1307 port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
1311 _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
1314 if (panners_legal) {
1317 panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
1320 if (connecting_legal) {
1322 if (make_connections (node)) {
1328 connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
1331 if (!ports_legal || !connecting_legal) {
1332 pending_state_node = new XMLNode (node);
1339 IO::load_automation (string path)
1344 uint32_t linecnt = 0;
1346 LocaleGuard lg (X_("POSIX"));
1348 fullpath = Glib::build_filename(_session.automation_dir(), path);
1350 in.open (fullpath.c_str());
1353 fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
1355 in.open (fullpath.c_str());
1358 error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
1363 clear_automation ();
1365 while (in.getline (line, sizeof(line), '\n')) {
1370 if (++linecnt == 1) {
1371 if (memcmp (line, "version", 7) == 0) {
1372 if (sscanf (line, "version %f", &version) != 1) {
1373 error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
1377 error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
1384 if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
1385 warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
1391 _gain_control->list()->fast_simple_add (when, value);
1401 /* older (pre-1.0) versions of ardour used this */
1405 warning << _("dubious automation event found (and ignored)") << endmsg;
1413 IO::connecting_became_legal ()
1417 if (pending_state_node == 0) {
1418 fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
1423 connection_legal_c.disconnect ();
1425 ret = make_connections (*pending_state_node);
1428 delete pending_state_node;
1429 pending_state_node = 0;
1435 IO::ports_became_legal ()
1439 if (pending_state_node == 0) {
1440 fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
1445 port_legal_c.disconnect ();
1447 ret = create_ports (*pending_state_node);
1449 if (connecting_legal) {
1450 delete pending_state_node;
1451 pending_state_node = 0;
1457 boost::shared_ptr<Bundle>
1458 IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
1460 static const string digits = "0123456789";
1462 boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
1465 int bundle_number, mask;
1466 string possible_name;
1467 bool stereo = false;
1468 string::size_type last_non_digit_pos;
1470 error << string_compose(_("Unknown bundle \"%1\" listed for %2 of %3"), desired_name, bundle_type_name, _name)
1473 // find numeric suffix of desired name
1476 last_non_digit_pos = desired_name.find_last_not_of(digits);
1478 if (last_non_digit_pos != string::npos) {
1480 s << desired_name.substr(last_non_digit_pos);
1484 // see if it's a stereo connection e.g. "in 3+4"
1486 if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') {
1487 int left_bundle_number = 0;
1488 string::size_type left_last_non_digit_pos;
1490 left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1);
1492 if (left_last_non_digit_pos != string::npos) {
1494 s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1);
1495 s >> left_bundle_number;
1497 if (left_bundle_number > 0 && left_bundle_number + 1 == bundle_number) {
1508 // find highest set bit
1510 while ((mask <= bundle_number) && (mask <<= 1)) {}
1512 // "wrap" bundle number into largest possible power of 2
1517 if (bundle_number & mask) {
1518 bundle_number &= ~mask;
1521 s << default_name << " " << bundle_number + 1;
1524 s << "+" << bundle_number + 2;
1527 possible_name = s.str();
1529 if ((c = _session.bundle_by_name (possible_name)) != 0) {
1536 info << string_compose (_("Bundle %1 was not available - \"%2\" used instead"), desired_name, possible_name)
1539 error << string_compose(_("No %1 bundles available as a replacement"), bundle_type_name)
1550 IO::get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
1551 boost::shared_ptr<Bundle>& ic, boost::shared_ptr<Bundle>& oc)
1553 XMLProperty const * prop;
1554 XMLNodeConstIterator iter;
1559 for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
1560 if ((*iter)->name() == X_("Inputs")) {
1561 in = ChanCount::max(in, ChanCount(**iter));
1562 } else if ((*iter)->name() == X_("Outputs")) {
1563 out = ChanCount::max(out, ChanCount(**iter));
1567 if ((prop = node.property ("input-connection")) != 0) {
1569 ic = find_possible_bundle (prop->value(), _("in"), _("input"));
1571 in = ChanCount::max(in, ChanCount(ic->type(), ic->nchannels()));
1574 } else if ((prop = node.property ("inputs")) != 0) {
1576 in = ChanCount::max(in, ChanCount(_default_type,
1577 count (prop->value().begin(), prop->value().end(), '{')));
1580 if ((prop = node.property ("output-connection")) != 0) {
1582 oc = find_possible_bundle (prop->value(), _("out"), _("output"));
1584 out = ChanCount::max(out, ChanCount(oc->type(), oc->nchannels()));
1587 } else if ((prop = node.property ("outputs")) != 0) {
1589 out = ChanCount::max(out, ChanCount(_default_type,
1590 count (prop->value().begin(), prop->value().end(), '{')));
1597 IO::create_ports (const XMLNode& node)
1599 if (pending_state_node) {
1603 boost::shared_ptr<Bundle> ic;
1604 boost::shared_ptr<Bundle> oc;
1606 no_panner_reset = true;
1608 get_port_counts (*pending_state_node, in, out, ic, oc);
1610 if (ensure_io (in, out, true, this)) {
1611 error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
1615 /* XXX use ic and oc if relevant */
1617 no_panner_reset = false;
1620 set_deferred_state ();
1625 IO::make_connections (const XMLNode& node)
1627 const XMLProperty* prop;
1629 if ((prop = node.property ("input-connection")) != 0) {
1630 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
1636 if (n_inputs().get(c->type()) == c->nchannels() && c->ports_are_outputs()) {
1637 connect_input_ports_to_bundle (c, this);
1640 } else if ((prop = node.property ("inputs")) != 0) {
1641 if (set_inputs (prop->value())) {
1642 error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
1647 if ((prop = node.property ("output-connection")) != 0) {
1648 boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
1654 if (n_outputs().get(c->type()) == c->nchannels() && c->ports_are_inputs()) {
1655 connect_output_ports_to_bundle (c, this);
1658 } else if ((prop = node.property ("outputs")) != 0) {
1659 if (set_outputs (prop->value())) {
1660 error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
1665 for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
1667 if ((*i)->name() == "InputBundle") {
1668 XMLProperty const * prop = (*i)->property ("name");
1670 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
1672 connect_input_ports_to_bundle (b, this);
1676 } else if ((*i)->name() == "OutputBundle") {
1677 XMLProperty const * prop = (*i)->property ("name");
1679 boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
1681 connect_output_ports_to_bundle (b, this);
1691 IO::set_inputs (const string& str)
1693 vector<string> ports;
1698 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1702 // FIXME: audio-only
1703 if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1707 string::size_type start, end, ostart;
1714 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1717 if ((end = str.find_first_of ('}', start)) == string::npos) {
1718 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
1722 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1723 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
1729 for (int x = 0; x < n; ++x) {
1730 connect_input (input (i), ports[x], this);
1742 IO::set_outputs (const string& str)
1744 vector<string> ports;
1749 if ((nports = count (str.begin(), str.end(), '{')) == 0) {
1753 // FIXME: audio-only - need a way to identify port types from XML/string
1754 if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
1758 string::size_type start, end, ostart;
1765 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
1768 if ((end = str.find_first_of ('}', start)) == string::npos) {
1769 error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
1773 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
1774 error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
1780 for (int x = 0; x < n; ++x) {
1781 connect_output (output (i), ports[x], this);
1793 IO::parse_io_string (const string& str, vector<string>& ports)
1795 string::size_type pos, opos;
1797 if (str.length() == 0) {
1806 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1807 ports.push_back (str.substr (opos, pos - opos));
1811 if (opos < str.length()) {
1812 ports.push_back (str.substr(opos));
1815 return ports.size();
1819 IO::parse_gain_string (const string& str, vector<string>& ports)
1821 string::size_type pos, opos;
1827 while ((pos = str.find_first_of (',', opos)) != string::npos) {
1828 ports.push_back (str.substr (opos, pos - opos));
1832 if (opos < str.length()) {
1833 ports.push_back (str.substr(opos));
1836 return ports.size();
1840 IO::set_name (const string& requested_name)
1842 if (requested_name == _name) {
1848 if ( (rt = dynamic_cast<Route *>(this))) {
1849 name = Route::ensure_track_or_route_name(requested_name, _session);
1851 name = requested_name;
1855 /* replace all colons in the name. i wish we didn't have to do this */
1857 if (replace_all (name, ":", "-")) {
1858 warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
1861 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1862 string current_name = i->name();
1863 current_name.replace (current_name.find (_name), _name.length(), name);
1864 i->set_name (current_name);
1867 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1868 string current_name = i->name();
1869 current_name.replace (current_name.find (_name), _name.length(), name);
1870 i->set_name (current_name);
1873 bool const r = SessionObject::set_name(name);
1875 setup_bundles_for_inputs_and_outputs ();
1881 IO::set_port_latency (nframes_t nframes)
1883 Glib::Mutex::Lock lm (io_lock);
1885 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1886 i->set_latency (nframes);
1891 IO::output_latency () const
1893 nframes_t max_latency;
1898 /* io lock not taken - must be protected by other means */
1900 for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
1901 if ((latency = i->total_latency ()) > max_latency) {
1902 max_latency = latency;
1910 IO::input_latency () const
1912 nframes_t max_latency;
1917 /* io lock not taken - must be protected by other means */
1919 for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
1920 if ((latency = i->total_latency ()) > max_latency) {
1921 max_latency = latency;
1929 IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1932 BLOCK_PROCESS_CALLBACK ();
1933 Glib::Mutex::Lock lm2 (io_lock);
1935 c->connect (_bundle_for_inputs, _session.engine());
1937 /* If this is a UserBundle, make a note of what we've done */
1939 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1942 /* See if we already know about this one */
1943 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1944 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
1948 if (i == _bundles_connected_to_inputs.end()) {
1949 /* We don't, so make a note */
1950 _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
1955 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
1960 IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
1963 BLOCK_PROCESS_CALLBACK ();
1964 Glib::Mutex::Lock lm2 (io_lock);
1966 c->disconnect (_bundle_for_inputs, _session.engine());
1968 /* If this is a UserBundle, make a note of what we've done */
1970 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
1973 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
1974 while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
1978 if (i != _bundles_connected_to_inputs.end()) {
1979 _bundles_connected_to_inputs.erase (i);
1984 input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
1989 IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
1992 BLOCK_PROCESS_CALLBACK ();
1993 Glib::Mutex::Lock lm2 (io_lock);
1995 c->connect (_bundle_for_outputs, _session.engine());
1997 /* If this is a UserBundle, make a note of what we've done */
1999 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2002 /* See if we already know about this one */
2003 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2004 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2008 if (i == _bundles_connected_to_outputs.end()) {
2009 /* We don't, so make a note */
2010 _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
2015 output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
2021 IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
2024 BLOCK_PROCESS_CALLBACK ();
2025 Glib::Mutex::Lock lm2 (io_lock);
2027 c->disconnect (_bundle_for_outputs, _session.engine());
2029 /* If this is a UserBundle, make a note of what we've done */
2031 boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
2034 std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
2035 while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
2039 if (i != _bundles_connected_to_outputs.end()) {
2040 _bundles_connected_to_outputs.erase (i);
2045 output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
2051 IO::disable_connecting ()
2053 connecting_legal = false;
2058 IO::enable_connecting ()
2060 connecting_legal = true;
2061 return ConnectingLegal ();
2065 IO::disable_ports ()
2067 ports_legal = false;
2075 return PortsLegal ();
2079 IO::disable_panners (void)
2081 panners_legal = false;
2086 IO::reset_panners ()
2088 panners_legal = true;
2089 return PannersLegal ();
2093 IO::bundle_changed (Bundle::Change c)
2096 // connect_input_ports_to_bundle (_input_bundle, this);
2100 IO::GainControl::set_value (float val)
2102 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2103 if (val > 1.99526231f)
2106 _io->set_gain (val, this);
2108 AutomationControl::set_value(val);
2112 IO::GainControl::get_value (void) const
2114 return AutomationControl::get_value();
2118 IO::setup_peak_meters()
2120 ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
2121 _meter->configure_io (max_streams, max_streams);
2125 Update the peak meters.
2127 The meter signal lock is taken to prevent modification of the
2128 Meter signal while updating the meters, taking the meter signal
2129 lock prior to taking the io_lock ensures that all IO will remain
2130 valid while metering.
2135 Glib::Mutex::Lock guard (m_meter_signal_lock);
2136 Meter(); /* EMIT SIGNAL */
2142 // FIXME: Ugly. Meter should manage the lock, if it's necessary
2144 Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
2149 IO::clear_automation ()
2151 data().clear_controls (); // clears gain automation
2152 _panner->data().clear_controls ();
2156 IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
2158 // XXX: would be nice to get rid of this special hack
2160 if (param.type() == GainAutomation) {
2162 bool changed = false;
2165 Glib::Mutex::Lock lm (control_lock());
2167 boost::shared_ptr<AutomationList> gain_auto
2168 = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
2170 if (state != gain_auto->automation_state()) {
2172 _last_automation_snapshot = 0;
2173 gain_auto->set_automation_state (state);
2176 // FIXME: shouldn't this use Curve?
2177 set_gain (gain_auto->eval (_session.transport_frame()), this);
2183 _session.set_dirty ();
2187 AutomatableControls::set_parameter_automation_state(param, state);
2192 IO::inc_gain (gain_t factor, void *src)
2194 float desired_gain = _gain_control->user_float();
2195 if (desired_gain == 0.0f) {
2196 set_gain (0.000001f + (0.000001f * factor), src);
2198 set_gain (desired_gain + (desired_gain * factor), src);
2203 IO::set_gain (gain_t val, void *src)
2205 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2206 if (val > 1.99526231f) {
2210 //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
2212 if (src != _gain_control.get()) {
2213 _gain_control->set_value(val);
2214 // bit twisty, this will come back and call us again
2215 // (this keeps control in sync with reality)
2220 Glib::Mutex::Lock dm (declick_lock);
2221 _gain_control->set_float(val, false);
2224 if (_session.transport_stopped()) {
2229 if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
2230 _gain_control->list()->add (_session.transport_frame(), val);
2235 _session.set_dirty();
2239 IO::start_pan_touch (uint32_t which)
2241 if (which < _panner->npanners()) {
2242 (*_panner).pan_control(which)->start_touch();
2247 IO::end_pan_touch (uint32_t which)
2249 if (which < _panner->npanners()) {
2250 (*_panner).pan_control(which)->stop_touch();
2256 IO::automation_snapshot (nframes_t now, bool force)
2258 AutomatableControls::automation_snapshot (now, force);
2259 // XXX: This seems to be wrong.
2260 // drobilla: shouldnt automation_snapshot for panner be called
2261 // "automagically" because its an Automatable now ?
2263 // we could dump this whole method then. <3
2265 if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
2266 _panner->automation_snapshot (now, force);
2269 _panner->automation_snapshot (now, force);
2270 _last_automation_snapshot = now;
2274 IO::transport_stopped (nframes_t frame)
2276 _gain_control->list()->reposition_for_rt_add (frame);
2278 if (_gain_control->automation_state() != Off) {
2280 /* the src=0 condition is a special signal to not propagate
2281 automation gain changes into the mix group when locating.
2284 // FIXME: shouldn't this use Curve?
2285 set_gain (_gain_control->list()->eval (frame), 0);
2288 _panner->transport_stopped (frame);
2292 IO::build_legal_port_name (DataType type, bool in)
2294 const int name_size = jack_port_name_size();
2298 if (type == DataType::AUDIO) {
2299 suffix = _("audio");
2300 } else if (type == DataType::MIDI) {
2303 throw unknown_type();
2309 suffix += _("_out");
2312 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2314 limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
2316 char buf1[name_size+1];
2317 char buf2[name_size+1];
2319 snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
2324 port_number = find_input_port_hole (buf1);
2326 port_number = find_output_port_hole (buf1);
2329 snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
2331 return string (buf2);
2335 IO::find_input_port_hole (const char* base)
2337 /* CALLER MUST HOLD IO LOCK */
2341 if (_inputs.empty()) {
2345 /* we only allow up to 4 characters for the port number
2348 for (n = 1; n < 9999; ++n) {
2349 char buf[jack_port_name_size()];
2350 PortSet::iterator i = _inputs.begin();
2352 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2354 for ( ; i != _inputs.end(); ++i) {
2355 if (i->name() == buf) {
2360 if (i == _inputs.end()) {
2368 IO::find_output_port_hole (const char* base)
2370 /* CALLER MUST HOLD IO LOCK */
2374 if (_outputs.empty()) {
2378 /* we only allow up to 4 characters for the port number
2381 for (n = 1; n < 9999; ++n) {
2382 char buf[jack_port_name_size()];
2383 PortSet::iterator i = _outputs.begin();
2385 snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
2387 for ( ; i != _outputs.end(); ++i) {
2388 if (i->name() == buf) {
2393 if (i == _outputs.end()) {
2402 IO::set_active (bool yn)
2405 active_changed(); /* EMIT SIGNAL */
2409 IO::audio_input(uint32_t n) const
2411 return dynamic_cast<AudioPort*>(input(n));
2415 IO::audio_output(uint32_t n) const
2417 return dynamic_cast<AudioPort*>(output(n));
2421 IO::midi_input(uint32_t n) const
2423 return dynamic_cast<MidiPort*>(input(n));
2427 IO::midi_output(uint32_t n) const
2429 return dynamic_cast<MidiPort*>(output(n));
2433 IO::set_phase_invert (bool yn, void *src)
2435 if (_phase_invert != yn) {
2437 // phase_invert_changed (src); /* EMIT SIGNAL */
2442 IO::set_denormal_protection (bool yn, void *src)
2444 if (_denormal_protection != yn) {
2445 _denormal_protection = yn;
2446 // denormal_protection_changed (src); /* EMIT SIGNAL */
2451 IO::update_port_total_latencies ()
2453 /* io_lock, not taken: function must be called from Session::process() calltree */
2455 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2456 _session.engine().update_total_latency (*i);
2459 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2460 _session.engine().update_total_latency (*i);
2466 * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
2470 IO::setup_bundles_for_inputs_and_outputs ()
2472 setup_bundle_for_inputs ();
2473 setup_bundle_for_outputs ();
2478 IO::setup_bundle_for_inputs ()
2482 if (!_bundle_for_inputs) {
2483 _bundle_for_inputs.reset (new Bundle (true));
2486 _bundle_for_inputs->suspend_signals ();
2488 _bundle_for_inputs->set_type (default_type ());
2490 _bundle_for_inputs->remove_channels ();
2492 snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
2493 _bundle_for_inputs->set_name (buf);
2494 uint32_t const ni = inputs().num_ports();
2495 for (uint32_t i = 0; i < ni; ++i) {
2496 _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
2497 _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
2500 _bundle_for_inputs->resume_signals ();
2505 IO::setup_bundle_for_outputs ()
2509 if (!_bundle_for_outputs) {
2510 _bundle_for_outputs.reset (new Bundle (false));
2513 _bundle_for_outputs->suspend_signals ();
2515 _bundle_for_outputs->set_type (default_type ());
2517 _bundle_for_outputs->remove_channels ();
2519 snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
2520 _bundle_for_outputs->set_name (buf);
2521 uint32_t const no = outputs().num_ports();
2522 for (uint32_t i = 0; i < no; ++i) {
2523 _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
2524 _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
2527 _bundle_for_outputs->resume_signals ();
2531 /** @return Bundles connected to our inputs */
2533 IO::bundles_connected_to_inputs ()
2538 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
2539 bundles.push_back (i->bundle);
2542 /* Session bundles */
2543 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2544 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2545 if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
2546 bundles.push_back (*i);
2551 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2552 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2553 if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
2554 bundles.push_back ((*i)->bundle_for_outputs());
2562 /* @return Bundles connected to our outputs */
2564 IO::bundles_connected_to_outputs ()
2569 for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
2570 bundles.push_back (i->bundle);
2573 /* Session bundles */
2574 boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
2575 for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
2576 if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
2577 bundles.push_back (*i);
2582 boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
2583 for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2584 if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
2585 bundles.push_back ((*i)->bundle_for_inputs());
2593 IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
2596 changed = b->Changed.connect (
2597 sigc::mem_fun (*io, &IO::bundle_changed)
2602 IO::prepare_inputs (nframes_t nframes)
2604 /* io_lock, not taken: function must be called from Session::process() calltree */
2608 IO::flush_outputs (nframes_t nframes)
2610 /* io_lock, not taken: function must be called from Session::process() calltree */
2612 for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
2613 (*i).flush_buffers (nframes, _output_offset);
2618 IO::bundle_channel_name (uint32_t c, uint32_t n) const
2626 return c == 0 ? _("L") : _("R");
2628 snprintf (buf, sizeof(buf), _("%d"), (c + 1));
2636 IO::name_from_state (const XMLNode& node)
2638 const XMLProperty* prop;
2640 if ((prop = node.property ("name")) != 0) {
2641 return prop->value();
2648 IO::set_name_in_state (XMLNode& node, const string& new_name)
2650 const XMLProperty* prop;
2652 if ((prop = node.property ("name")) != 0) {
2653 node.add_property ("name", new_name);
2658 IO::cycle_start (nframes_t nframes)
2664 IO::increment_output_offset (nframes_t n)
2666 _output_offset += n;
2670 IO::connected_to (boost::shared_ptr<const IO> other) const
2674 uint32_t no = n_outputs().n_total();
2675 uint32_t ni = other->n_inputs ().n_total();
2677 for (i = 0; i < no; ++i) {
2678 for (j = 0; j < ni; ++j) {
2679 if (output(i)->connected_to (other->input(j)->name())) {