2 Copyright (C) 2000 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.
26 #include <sigc++/bind.h>
29 #include <glibmm/thread.h>
31 #include <pbd/xml++.h>
32 #include <pbd/replace_all.h>
33 #include <pbd/localeguard.h>
35 #include <ardour/audioengine.h>
36 #include <ardour/io.h>
37 #include <ardour/route.h>
38 #include <ardour/port.h>
39 #include <ardour/connection.h>
40 #include <ardour/session.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/panner.h>
43 #include <ardour/dB.h>
52 A bug in OS X's cmath that causes isnan() and isinf() to be
53 "undeclared". the following works around that
56 #if defined(__APPLE__) && defined(__MACH__)
57 extern "C" int isnan (double);
58 extern "C" int isinf (double);
61 #define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock())
64 using namespace ARDOUR
;
67 nframes_t
IO::_automation_interval
= 0;
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,uint32_t> IO::MoreOutputs
;
77 sigc::signal
<int> IO::PortsCreated
;
78 sigc::signal
<void,nframes_t
> IO::CycleStart
;
80 Glib::StaticMutex
IO::m_meter_signal_lock
= GLIBMM_STATIC_MUTEX_INIT
;
82 /* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
83 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);
99 static bool sort_ports_by_name (Port
* a
, Port
* b
) {
101 std::string
const a_name
= a
->name();
102 unsigned int last_digit_position_a
= a_name
.size();
103 std::string::const_reverse_iterator r_iterator
= a_name
.rbegin();
105 while (r_iterator
!= a_name
.rend() and Glib::Unicode::isdigit(*r_iterator
)) {
106 r_iterator
++; last_digit_position_a
--;
109 std::string
const b_name
= b
->name();
110 unsigned int last_digit_position_b
= b_name
.size();
111 r_iterator
= b_name
.rbegin();
113 while (r_iterator
!= b_name
.rend() and Glib::Unicode::isdigit(*r_iterator
)) {
114 r_iterator
++; last_digit_position_b
--;
117 // if some of the names don't have a number as posfix, compare as strings
118 if (last_digit_position_a
== a_name
.size() or last_digit_position_b
== b_name
.size()) {
119 return a_name
< b_name
;
122 const std::string prefix_a
= a_name
.substr(0, last_digit_position_a
- 1);
123 const unsigned int posfix_a
= std::atoi(a_name
.substr(last_digit_position_a
, a_name
.size() - last_digit_position_a
).c_str());
124 const std::string prefix_b
= b_name
.substr(0, last_digit_position_b
- 1);
125 const unsigned int posfix_b
= std::atoi(b_name
.substr(last_digit_position_b
, b_name
.size() - last_digit_position_b
).c_str());
127 if (prefix_a
!= prefix_b
) {
128 return a_name
< b_name
;
130 return posfix_a
< posfix_b
;
135 /** @param default_type The type of port that will be created by ensure_io
136 * and friends if no type is explicitly requested (to avoid breakage).
138 IO::IO (Session
& s
, string name
,
139 int input_min
, int input_max
, int output_min
, int output_max
,
140 DataType default_type
)
143 _default_type(default_type
),
144 _gain_control (X_("gaincontrol"), *this),
145 _gain_automation_curve (0.0, 2.0, 1.0),
146 _input_minimum (input_min
),
147 _input_maximum (input_max
),
148 _output_minimum (output_min
),
149 _output_maximum (output_max
)
151 _panner
= new Panner (name
, _session
);
155 _input_connection
= 0;
156 _output_connection
= 0;
157 pending_state_node
= 0;
160 no_panner_reset
= false;
163 apply_gain_automation
= false;
164 _ignore_gain_on_deliver
= false;
166 last_automation_snapshot
= 0;
168 _gain_automation_state
= Auto_Off
;
169 _gain_automation_style
= Auto_Absolute
;
172 // IO::Meter is emitted from another thread so the
173 // Meter signal must be protected.
174 Glib::Mutex::Lock
guard (m_meter_signal_lock
);
175 m_meter_connection
= Meter
.connect (mem_fun (*this, &IO::meter
));
179 CycleStart
.connect (mem_fun (*this, &IO::cycle_start
));
181 _session
.add_controllable (&_gain_control
);
184 IO::IO (Session
& s
, const XMLNode
& node
, DataType dt
)
187 _gain_control (X_("gaincontrol"), *this),
188 _gain_automation_curve (0, 0, 0) // all reset in set_state()
193 no_panner_reset
= false;
196 _input_connection
= 0;
197 _output_connection
= 0;
201 apply_gain_automation
= false;
202 _ignore_gain_on_deliver
= false;
207 // IO::Meter is emitted from another thread so the
208 // Meter signal must be protected.
209 Glib::Mutex::Lock
guard (m_meter_signal_lock
);
210 m_meter_connection
= Meter
.connect (mem_fun (*this, &IO::meter
));
214 CycleStart
.connect (mem_fun (*this, &IO::cycle_start
));
216 _session
.add_controllable (&_gain_control
);
221 Glib::Mutex::Lock
guard (m_meter_signal_lock
);
223 Glib::Mutex::Lock
lm (io_lock
);
224 vector
<Port
*>::iterator i
;
227 BLOCK_PROCESS_CALLBACK ();
229 for (i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
230 _session
.engine().unregister_port (*i
);
233 for (i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
234 _session
.engine().unregister_port (*i
);
238 m_meter_connection
.disconnect();
242 IO::silence (nframes_t nframes
)
244 /* io_lock, not taken: function must be called from Session::process() calltree */
246 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
247 (*i
)->silence (nframes
);
252 IO::apply_declick (vector
<Sample
*>& bufs
, uint32_t nbufs
, nframes_t nframes
, gain_t initial
, gain_t target
, bool invert_polarity
)
254 nframes_t declick
= min ((nframes_t
)128, nframes
);
257 double fractional_shift
;
258 double fractional_pos
;
259 gain_t polscale
= invert_polarity
? -1.0f
: 1.0f
;
261 if (nframes
== 0) return;
263 fractional_shift
= -1.0/declick
;
265 if (target
< initial
) {
266 /* fade out: remove more and more of delta from initial */
267 delta
= -(initial
- target
);
269 /* fade in: add more and more of delta from initial */
270 delta
= target
- initial
;
273 for (uint32_t n
= 0; n
< nbufs
; ++n
) {
276 fractional_pos
= 1.0;
278 for (nframes_t nx
= 0; nx
< declick
; ++nx
) {
279 buffer
[nx
] *= polscale
* (initial
+ (delta
* (0.5 + 0.5 * cos (M_PI
* fractional_pos
))));
280 fractional_pos
+= fractional_shift
;
283 /* now ensure the rest of the buffer has the target value
284 applied, if necessary.
287 if (declick
!= nframes
) {
290 if (invert_polarity
) {
291 this_target
= -target
;
293 this_target
= target
;
296 if (this_target
== 0.0) {
297 memset (&buffer
[declick
], 0, sizeof (Sample
) * (nframes
- declick
));
298 } else if (this_target
!= 1.0) {
299 for (nframes_t nx
= declick
; nx
< nframes
; ++nx
) {
300 buffer
[nx
] *= this_target
;
308 IO::pan_automated (vector
<Sample
*>& bufs
, uint32_t nbufs
, nframes_t start
, nframes_t end
, nframes_t nframes
)
312 /* io_lock, not taken: function must be called from Session::process() calltree */
314 if (_noutputs
== 0) {
318 if (_noutputs
== 1) {
320 dst
= get_output_buffer (0, nframes
);
322 for (uint32_t n
= 0; n
< nbufs
; ++n
) {
323 if (bufs
[n
] != dst
) {
324 memcpy (dst
, bufs
[n
], sizeof (Sample
) * nframes
);
328 output(0)->mark_silence (false);
334 vector
<Port
*>::iterator out
;
335 vector
<Sample
*>::iterator in
;
336 Panner::iterator pan
;
337 Sample
* obufs
[_noutputs
];
339 /* the terrible silence ... */
341 for (out
= _outputs
.begin(), o
= 0; out
!= _outputs
.end(); ++out
, ++o
) {
342 obufs
[o
] = get_output_buffer (o
, nframes
);
343 memset (obufs
[o
], 0, sizeof (Sample
) * nframes
);
344 (*out
)->mark_silence (false);
349 for (pan
= _panner
->begin(), n
= 0; n
< nbufs
; ++n
, ++pan
) {
350 (*pan
)->distribute_automated (bufs
[n
], obufs
, start
, end
, nframes
, _session
.pan_automation_buffer());
355 IO::pan (vector
<Sample
*>& bufs
, uint32_t nbufs
, nframes_t nframes
, gain_t gain_coeff
)
360 /* io_lock, not taken: function must be called from Session::process() calltree */
362 if (_noutputs
== 0) {
366 /* the panner can be empty if there are no inputs to the
367 route, but still outputs
370 if (_panner
->bypassed() || _panner
->empty()) {
371 deliver_output_no_pan (bufs
, nbufs
, nframes
);
375 if (_noutputs
== 1) {
377 dst
= get_output_buffer (0, nframes
);
379 if (gain_coeff
== 0.0f
) {
381 /* only one output, and gain was zero, so make it silent */
383 memset (dst
, 0, sizeof (Sample
) * nframes
);
385 } else if (gain_coeff
== 1.0f
){
387 /* mix all buffers into the output */
391 memcpy (dst
, bufs
[0], sizeof (Sample
) * nframes
);
393 for (n
= 1; n
< nbufs
; ++n
) {
394 Session::mix_buffers_no_gain(dst
,bufs
[n
],nframes
);
397 output(0)->mark_silence (false);
401 /* mix all buffers into the output, scaling them all by the gain */
407 for (nframes_t n
= 0; n
< nframes
; ++n
) {
408 dst
[n
] = src
[n
] * gain_coeff
;
411 for (n
= 1; n
< nbufs
; ++n
) {
412 Session::mix_buffers_with_gain(dst
,bufs
[n
],nframes
,gain_coeff
);
415 output(0)->mark_silence (false);
422 vector
<Port
*>::iterator out
;
423 vector
<Sample
*>::iterator in
;
424 Panner::iterator pan
;
425 Sample
* obufs
[_noutputs
];
427 /* the terrible silence ... */
429 /* XXX this is wasteful but i see no way to avoid it */
431 for (out
= _outputs
.begin(), o
= 0; out
!= _outputs
.end(); ++out
, ++o
) {
432 obufs
[o
] = get_output_buffer (o
, nframes
);
433 memset (obufs
[o
], 0, sizeof (Sample
) * nframes
);
434 (*out
)->mark_silence (false);
439 for (pan
= _panner
->begin(), n
= 0; n
< nbufs
; ++n
) {
440 Panner::iterator tmp
;
445 (*pan
)->distribute (bufs
[n
], obufs
, gain_coeff
, nframes
);
447 if (tmp
!= _panner
->end()) {
454 IO::deliver_output (vector
<Sample
*>& bufs
, uint32_t nbufs
, nframes_t nframes
)
456 /* io_lock, not taken: function must be called from Session::process() calltree */
458 if (_noutputs
== 0) {
462 if (_panner
->bypassed() || _panner
->empty()) {
463 deliver_output_no_pan (bufs
, nbufs
, nframes
);
469 gain_t pangain
= _gain
;
472 Glib::Mutex::Lock
dm (declick_lock
, Glib::TRY_LOCK
);
482 apply_declick (bufs
, nbufs
, nframes
, _gain
, dg
, false);
487 /* simple, non-automation panning to outputs */
489 if (_session
.transport_speed() > 1.5f
|| _session
.transport_speed() < -1.5f
) {
490 pan (bufs
, nbufs
, nframes
, pangain
* speed_quietning
);
492 pan (bufs
, nbufs
, nframes
, pangain
);
497 IO::deliver_output_no_pan (vector
<Sample
*>& bufs
, uint32_t nbufs
, nframes_t nframes
)
499 /* io_lock, not taken: function must be called from Session::process() calltree */
501 if (_noutputs
== 0) {
506 gain_t old_gain
= _gain
;
508 if (apply_gain_automation
|| _ignore_gain_on_deliver
) {
510 /* gain has already been applied by automation code. do nothing here except
519 Glib::Mutex::Lock
dm (declick_lock
, Glib::TRY_LOCK
);
531 vector
<Port
*>::iterator o
;
532 vector
<Sample
*> outs
;
535 /* reduce nbufs to the index of the last input buffer */
539 if (_session
.transport_speed() > 1.5f
|| _session
.transport_speed() < -1.5f
) {
540 actual_gain
= _gain
* speed_quietning
;
545 for (o
= _outputs
.begin(), i
= 0; o
!= _outputs
.end(); ++o
, ++i
) {
547 dst
= get_output_buffer (i
, nframes
);
548 src
= bufs
[min(nbufs
,i
)];
551 /* unlikely condition */
552 outs
.push_back (dst
);
555 if (dg
!= _gain
|| actual_gain
== 1.0f
) {
556 memcpy (dst
, src
, sizeof (Sample
) * nframes
);
557 } else if (actual_gain
== 0.0f
) {
558 memset (dst
, 0, sizeof (Sample
) * nframes
);
560 for (nframes_t x
= 0; x
< nframes
; ++x
) {
561 dst
[x
] = src
[x
] * actual_gain
;
565 (*o
)->mark_silence (false);
569 apply_declick (outs
, i
, nframes
, _gain
, dg
, false);
573 if (apply_gain_automation
|| _ignore_gain_on_deliver
) {
579 IO::collect_input (vector
<Sample
*>& bufs
, uint32_t nbufs
, nframes_t nframes
)
581 /* io_lock, not taken: function must be called from Session::process() calltree */
583 vector
<Port
*>::iterator i
;
587 /* we require that bufs.size() >= 1 */
589 for (n
= 0, i
= _inputs
.begin(); n
< nbufs
; ++i
, ++n
) {
590 if (i
== _inputs
.end()) {
594 last
= get_input_buffer (n
, nframes
);
595 memcpy (bufs
[n
], last
, sizeof (Sample
) * nframes
);
598 /* fill any excess outputs with the last input */
602 memcpy (bufs
[n
], last
, sizeof (Sample
) * nframes
);
607 memset (bufs
[n
], 0, sizeof (Sample
) * nframes
);
614 IO::just_meter_input (nframes_t start_frame
, nframes_t end_frame
, nframes_t nframes
)
616 vector
<Sample
*>& bufs
= _session
.get_passthru_buffers ();
617 uint32_t nbufs
= n_process_buffers ();
619 collect_input (bufs
, nbufs
, nframes
);
621 for (uint32_t n
= 0; n
< nbufs
; ++n
) {
622 _peak_power
[n
] = Session::compute_peak (bufs
[n
], nframes
, _peak_power
[n
]);
627 IO::drop_input_connection ()
629 _input_connection
= 0;
630 input_connection_configuration_connection
.disconnect();
631 input_connection_connection_connection
.disconnect();
632 _session
.set_dirty ();
636 IO::drop_output_connection ()
638 _output_connection
= 0;
639 output_connection_configuration_connection
.disconnect();
640 output_connection_connection_connection
.disconnect();
641 _session
.set_dirty ();
645 IO::disconnect_input (Port
* our_port
, string other_port
, void* src
)
647 if (other_port
.length() == 0 || our_port
== 0) {
652 BLOCK_PROCESS_CALLBACK ();
655 Glib::Mutex::Lock
lm (io_lock
);
657 /* check that our_port is really one of ours */
659 if (find (_inputs
.begin(), _inputs
.end(), our_port
) == _inputs
.end()) {
663 /* disconnect it from the source */
665 if (_session
.engine().disconnect (other_port
, our_port
->name())) {
666 error
<< string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port
->name(), other_port
) << endmsg
;
670 drop_input_connection();
674 input_changed (ConnectionsChanged
, src
); /* EMIT SIGNAL */
675 _session
.set_dirty ();
681 IO::connect_input (Port
* our_port
, string other_port
, void* src
)
683 if (other_port
.length() == 0 || our_port
== 0) {
688 BLOCK_PROCESS_CALLBACK ();
691 Glib::Mutex::Lock
lm (io_lock
);
693 /* check that our_port is really one of ours */
695 if (find (_inputs
.begin(), _inputs
.end(), our_port
) == _inputs
.end()) {
699 /* connect it to the source */
701 if (_session
.engine().connect (other_port
, our_port
->name())) {
705 drop_input_connection ();
709 input_changed (ConnectionsChanged
, src
); /* EMIT SIGNAL */
710 _session
.set_dirty ();
715 IO::disconnect_output (Port
* our_port
, string other_port
, void* src
)
717 if (other_port
.length() == 0 || our_port
== 0) {
722 BLOCK_PROCESS_CALLBACK ();
725 Glib::Mutex::Lock
lm (io_lock
);
727 if (find (_outputs
.begin(), _outputs
.end(), our_port
) == _outputs
.end()) {
731 /* disconnect it from the destination */
733 if (_session
.engine().disconnect (our_port
->name(), other_port
)) {
734 error
<< string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port
->name(), other_port
) << endmsg
;
738 drop_output_connection ();
742 output_changed (ConnectionsChanged
, src
); /* EMIT SIGNAL */
743 _session
.set_dirty ();
748 IO::connect_output (Port
* our_port
, string other_port
, void* src
)
750 if (other_port
.length() == 0 || our_port
== 0) {
755 BLOCK_PROCESS_CALLBACK ();
759 Glib::Mutex::Lock
lm (io_lock
);
761 /* check that our_port is really one of ours */
763 if (find (_outputs
.begin(), _outputs
.end(), our_port
) == _outputs
.end()) {
767 /* connect it to the destination */
769 if (_session
.engine().connect (our_port
->name(), other_port
)) {
773 drop_output_connection ();
777 output_changed (ConnectionsChanged
, src
); /* EMIT SIGNAL */
778 _session
.set_dirty ();
783 IO::set_input (Port
* other_port
, void* src
)
785 /* this removes all but one ports, and connects that one port
786 to the specified source.
789 if (_input_minimum
> 1 || _input_minimum
== 0) {
790 /* sorry, you can't do this */
794 if (other_port
== 0) {
795 if (_input_minimum
< 0) {
796 return ensure_inputs (0, false, true, src
);
802 if (ensure_inputs (1, true, true, src
)) {
806 return connect_input (_inputs
.front(), other_port
->name(), src
);
810 IO::remove_output_port (Port
* port
, void* src
)
812 IOChange
change (NoChange
);
815 BLOCK_PROCESS_CALLBACK ();
819 Glib::Mutex::Lock
lm (io_lock
);
821 if (_noutputs
- 1 == (uint32_t) _output_minimum
) {
822 /* sorry, you can't do this */
826 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
828 change
= IOChange (change
|ConfigurationChanged
);
829 if (port
->connected()) {
830 change
= IOChange (change
|ConnectionsChanged
);
833 _session
.engine().unregister_port (*i
);
836 drop_output_connection ();
842 if (change
!= NoChange
) {
843 setup_peak_meters ();
849 if (change
!= NoChange
) {
850 output_changed (change
, src
); /* EMIT SIGNAL */
851 _session
.set_dirty ();
858 /** Add an output port.
860 * @param destination Name of input port to connect new port to.
861 * @param src Source for emitted ConfigurationChanged signal.
862 * @param type Data type of port. Default value (NIL) will use this IO's default type.
865 IO::add_output_port (string destination
, void* src
, DataType type
)
869 if (type
== DataType::NIL
)
870 type
= _default_type
;
873 BLOCK_PROCESS_CALLBACK ();
877 Glib::Mutex::Lock
lm (io_lock
);
879 if (_output_maximum
>= 0 && (int) _noutputs
== _output_maximum
) {
883 /* Create a new output port */
885 string portname
= build_legal_port_name (false);
887 if ((our_port
= _session
.engine().register_output_port (type
, portname
)) == 0) {
888 error
<< string_compose(_("IO: cannot register output port %1"), portname
) << endmsg
;
892 _outputs
.push_back (our_port
);
893 sort (_outputs
.begin(), _outputs
.end(), sort_ports_by_name
);
895 drop_output_connection ();
896 setup_peak_meters ();
900 MoreOutputs (_noutputs
); /* EMIT SIGNAL */
903 if (destination
.length()) {
904 if (_session
.engine().connect (our_port
->name(), destination
)) {
909 // pan_changed (src); /* EMIT SIGNAL */
910 output_changed (ConfigurationChanged
, src
); /* EMIT SIGNAL */
911 _session
.set_dirty ();
916 IO::remove_input_port (Port
* port
, void* src
)
918 IOChange
change (NoChange
);
921 BLOCK_PROCESS_CALLBACK ();
925 Glib::Mutex::Lock
lm (io_lock
);
927 if (((int)_ninputs
- 1) < _input_minimum
) {
928 /* sorry, you can't do this */
931 for (vector
<Port
*>::iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
934 change
= IOChange (change
|ConfigurationChanged
);
936 if (port
->connected()) {
937 change
= IOChange (change
|ConnectionsChanged
);
940 _session
.engine().unregister_port (*i
);
943 drop_input_connection ();
949 if (change
!= NoChange
) {
950 setup_peak_meters ();
956 if (change
!= NoChange
) {
957 input_changed (change
, src
);
958 _session
.set_dirty ();
966 /** Add an input port.
968 * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created.
969 * @param destination Name of input port to connect new port to.
970 * @param src Source for emitted ConfigurationChanged signal.
973 IO::add_input_port (string source
, void* src
, DataType type
)
977 if (type
== DataType::NIL
)
978 type
= _default_type
;
981 BLOCK_PROCESS_CALLBACK ();
984 Glib::Mutex::Lock
lm (io_lock
);
986 if (_input_maximum
>= 0 && (int) _ninputs
== _input_maximum
) {
990 /* Create a new input port */
992 string portname
= build_legal_port_name (true);
994 if ((our_port
= _session
.engine().register_input_port (type
, portname
)) == 0) {
995 error
<< string_compose(_("IO: cannot register input port %1"), portname
) << endmsg
;
999 _inputs
.push_back (our_port
);
1000 sort (_inputs
.begin(), _inputs
.end(), sort_ports_by_name
);
1002 drop_input_connection ();
1003 setup_peak_meters ();
1007 MoreOutputs (_ninputs
); /* EMIT SIGNAL */
1010 if (source
.length()) {
1012 if (_session
.engine().connect (source
, our_port
->name())) {
1017 // pan_changed (src); /* EMIT SIGNAL */
1018 input_changed (ConfigurationChanged
, src
); /* EMIT SIGNAL */
1019 _session
.set_dirty ();
1025 IO::disconnect_inputs (void* src
)
1028 BLOCK_PROCESS_CALLBACK ();
1031 Glib::Mutex::Lock
lm (io_lock
);
1033 for (vector
<Port
*>::iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
1034 _session
.engine().disconnect (*i
);
1037 drop_input_connection ();
1040 input_changed (ConnectionsChanged
, src
); /* EMIT SIGNAL */
1045 IO::disconnect_outputs (void* src
)
1048 BLOCK_PROCESS_CALLBACK ();
1051 Glib::Mutex::Lock
lm (io_lock
);
1053 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
1054 _session
.engine().disconnect (*i
);
1057 drop_output_connection ();
1061 output_changed (ConnectionsChanged
, src
); /* EMIT SIGNAL */
1062 _session
.set_dirty ();
1067 IO::ensure_inputs_locked (uint32_t n
, bool clear
, void* src
)
1070 bool changed
= false;
1071 bool reduced
= false;
1073 /* remove unused ports */
1075 while (_ninputs
> n
) {
1076 _session
.engine().unregister_port (_inputs
.back());
1083 /* create any necessary new ports */
1085 while (_ninputs
< n
) {
1087 /* Create a new input port (of the default type) */
1089 string portname
= build_legal_port_name (true);
1093 if ((input_port
= _session
.engine().register_input_port (_default_type
, portname
)) == 0) {
1094 error
<< string_compose(_("IO: cannot register input port %1"), portname
) << endmsg
;
1099 catch (AudioEngine::PortRegistrationFailure
& err
) {
1100 setup_peak_meters ();
1106 _inputs
.push_back (input_port
);
1107 sort (_inputs
.begin(), _inputs
.end(), sort_ports_by_name
);
1113 drop_input_connection ();
1114 setup_peak_meters ();
1116 MoreOutputs (_ninputs
); /* EMIT SIGNAL */
1117 _session
.set_dirty ();
1121 /* disconnect all existing ports so that we get a fresh start */
1123 for (vector
<Port
*>::iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
1124 _session
.engine().disconnect (*i
);
1132 IO::ensure_io (uint32_t nin
, uint32_t nout
, bool clear
, void* src
)
1134 bool in_changed
= false;
1135 bool out_changed
= false;
1136 bool in_reduced
= false;
1137 bool out_reduced
= false;
1138 bool need_pan_reset
;
1140 if (_input_maximum
>= 0) {
1141 nin
= min (_input_maximum
, (int) nin
);
1144 if (_output_maximum
>= 0) {
1145 nout
= min (_output_maximum
, (int) nout
);
1148 if (nin
== _ninputs
&& nout
== _noutputs
&& !clear
) {
1153 BLOCK_PROCESS_CALLBACK ();
1154 Glib::Mutex::Lock
lm (io_lock
);
1158 if (_noutputs
== nout
) {
1159 need_pan_reset
= false;
1161 need_pan_reset
= true;
1164 /* remove unused ports */
1166 while (_ninputs
> nin
) {
1167 _session
.engine().unregister_port (_inputs
.back());
1174 while (_noutputs
> nout
) {
1175 _session
.engine().unregister_port (_outputs
.back());
1176 _outputs
.pop_back();
1182 /* create any necessary new ports (of the default type) */
1184 while (_ninputs
< nin
) {
1186 /* Create a new input port */
1188 string portname
= build_legal_port_name (true);
1191 if ((port
= _session
.engine().register_input_port (_default_type
, portname
)) == 0) {
1192 error
<< string_compose(_("IO: cannot register input port %1"), portname
) << endmsg
;
1197 catch (AudioEngine::PortRegistrationFailure
& err
) {
1198 setup_peak_meters ();
1204 _inputs
.push_back (port
);
1209 /* create any necessary new ports */
1211 while (_noutputs
< nout
) {
1213 string portname
= build_legal_port_name (false);
1216 if ((port
= _session
.engine().register_output_port (_default_type
, portname
)) == 0) {
1217 error
<< string_compose(_("IO: cannot register output port %1"), portname
) << endmsg
;
1222 catch (AudioEngine::PortRegistrationFailure
& err
) {
1223 setup_peak_meters ();
1229 _outputs
.push_back (port
);
1236 /* disconnect all existing ports so that we get a fresh start */
1238 for (vector
<Port
*>::iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
1239 _session
.engine().disconnect (*i
);
1242 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
1243 _session
.engine().disconnect (*i
);
1247 if (in_changed
|| out_changed
) {
1248 setup_peak_meters ();
1254 sort (_outputs
.begin(), _outputs
.end(), sort_ports_by_name
);
1255 drop_output_connection ();
1256 output_changed (ConfigurationChanged
, src
); /* EMIT SIGNAL */
1260 sort (_inputs
.begin(), _inputs
.end(), sort_ports_by_name
);
1261 drop_input_connection ();
1262 input_changed (ConfigurationChanged
, src
); /* EMIT SIGNAL */
1265 if (in_changed
|| out_changed
) {
1266 MoreOutputs (max (_noutputs
, _ninputs
)); /* EMIT SIGNAL */
1267 _session
.set_dirty ();
1274 IO::ensure_inputs (uint32_t n
, bool clear
, bool lockit
, void* src
)
1276 bool changed
= false;
1278 if (_input_maximum
>= 0) {
1279 n
= min (_input_maximum
, (int) n
);
1281 if (n
== _ninputs
&& !clear
) {
1287 BLOCK_PROCESS_CALLBACK ();
1288 Glib::Mutex::Lock
im (io_lock
);
1289 changed
= ensure_inputs_locked (n
, clear
, src
);
1291 changed
= ensure_inputs_locked (n
, clear
, src
);
1295 input_changed (ConfigurationChanged
, src
); /* EMIT SIGNAL */
1296 _session
.set_dirty ();
1303 IO::ensure_outputs_locked (uint32_t n
, bool clear
, void* src
)
1306 bool changed
= false;
1307 bool reduced
= false;
1308 bool need_pan_reset
;
1310 if (_noutputs
== n
) {
1311 need_pan_reset
= false;
1313 need_pan_reset
= true;
1316 /* remove unused ports */
1318 while (_noutputs
> n
) {
1320 _session
.engine().unregister_port (_outputs
.back());
1321 _outputs
.pop_back();
1327 /* create any necessary new ports */
1329 while (_noutputs
< n
) {
1331 /* Create a new output port */
1333 string portname
= build_legal_port_name (false);
1335 if ((output_port
= _session
.engine().register_output_port (_default_type
, portname
)) == 0) {
1336 error
<< string_compose(_("IO: cannot register output port %1"), portname
) << endmsg
;
1340 _outputs
.push_back (output_port
);
1341 sort (_outputs
.begin(), _outputs
.end(), sort_ports_by_name
);
1344 setup_peak_meters ();
1346 if (need_pan_reset
) {
1352 drop_output_connection ();
1353 MoreOutputs (_noutputs
); /* EMIT SIGNAL */
1354 _session
.set_dirty ();
1358 /* disconnect all existing ports so that we get a fresh start */
1360 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
1361 _session
.engine().disconnect (*i
);
1369 IO::ensure_outputs (uint32_t n
, bool clear
, bool lockit
, void* src
)
1371 bool changed
= false;
1373 if (_output_maximum
>= 0) {
1374 n
= min (_output_maximum
, (int) n
);
1375 if (n
== _noutputs
&& !clear
) {
1380 /* XXX caller should hold io_lock, but generally doesn't */
1383 BLOCK_PROCESS_CALLBACK ();
1384 Glib::Mutex::Lock
im (io_lock
);
1385 changed
= ensure_outputs_locked (n
, clear
, src
);
1387 changed
= ensure_outputs_locked (n
, clear
, src
);
1391 output_changed (ConfigurationChanged
, src
); /* EMIT SIGNAL */
1398 IO::effective_gain () const
1400 if (gain_automation_playback()) {
1401 return _effective_gain
;
1403 return _desired_gain
;
1410 if (panners_legal
) {
1411 if (!no_panner_reset
) {
1412 _panner
->reset (_noutputs
, pans_required());
1415 panner_legal_c
.disconnect ();
1416 panner_legal_c
= PannersLegal
.connect (mem_fun (*this, &IO::panners_became_legal
));
1421 IO::panners_became_legal ()
1423 _panner
->reset (_noutputs
, pans_required());
1424 _panner
->load (); // automation
1425 panner_legal_c
.disconnect ();
1430 IO::defer_pan_reset ()
1432 no_panner_reset
= true;
1436 IO::allow_pan_reset ()
1438 no_panner_reset
= false;
1444 IO::get_state (void)
1446 return state (true);
1450 IO::state (bool full_state
)
1452 XMLNode
* node
= new XMLNode (state_node_name
);
1455 bool need_ins
= true;
1456 bool need_outs
= true;
1457 LocaleGuard
lg (X_("POSIX"));
1458 Glib::Mutex::Lock
lm (io_lock
);
1460 node
->add_property("name", _name
);
1461 id().print (buf
, sizeof (buf
));
1462 node
->add_property("id", buf
);
1463 node
->add_property("active", _active
? "yes" : "no");
1467 if (_input_connection
) {
1468 node
->add_property ("input-connection", _input_connection
->name());
1472 if (_output_connection
) {
1473 node
->add_property ("output-connection", _output_connection
->name());
1478 for (vector
<Port
*>::iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
1480 const char **connections
= (*i
)->get_connections();
1482 if (connections
&& connections
[0]) {
1485 for (int n
= 0; connections
&& connections
[n
]; ++n
) {
1490 /* if its a connection to our own port,
1491 return only the port name, not the
1492 whole thing. this allows connections
1493 to be re-established even when our
1494 client name is different.
1497 str
+= _session
.engine().make_port_name_relative (connections
[n
]);
1509 node
->add_property ("inputs", str
);
1515 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
1517 const char **connections
= (*i
)->get_connections();
1519 if (connections
&& connections
[0]) {
1523 for (int n
= 0; connections
[n
]; ++n
) {
1528 str
+= _session
.engine().make_port_name_relative (connections
[n
]);
1540 node
->add_property ("outputs", str
);
1543 node
->add_child_nocopy (_panner
->state (full_state
));
1544 node
->add_child_nocopy (_gain_control
.get_state ());
1546 snprintf (buf
, sizeof(buf
), "%2.12f", gain());
1547 node
->add_property ("gain", buf
);
1549 snprintf (buf
, sizeof(buf
)-1, "%d,%d,%d,%d",
1555 node
->add_property ("iolimits", buf
);
1561 XMLNode
* autonode
= new XMLNode (X_("Automation"));
1562 autonode
->add_child_nocopy (get_automation_state());
1563 node
->add_child_nocopy (*autonode
);
1565 snprintf (buf
, sizeof (buf
), "0x%x", (int) _gain_automation_curve
.automation_state());
1567 /* never store anything except Off for automation state in a template */
1568 snprintf (buf
, sizeof (buf
), "0x%x", ARDOUR::Auto_Off
);
1575 IO::set_state (const XMLNode
& node
)
1577 const XMLProperty
* prop
;
1578 XMLNodeConstIterator iter
;
1579 LocaleGuard
lg (X_("POSIX"));
1581 /* force use of non-localized representation of decimal point,
1582 since we use it a lot in XML files and so forth.
1585 if (node
.name() != state_node_name
) {
1586 error
<< string_compose(_("incorrect XML node \"%1\" passed to IO object"), node
.name()) << endmsg
;
1590 if ((prop
= node
.property ("name")) != 0) {
1591 _name
= prop
->value();
1592 /* used to set panner name with this, but no more */
1595 if ((prop
= node
.property ("id")) != 0) {
1596 _id
= prop
->value ();
1599 if ((prop
= node
.property ("iolimits")) != 0) {
1600 sscanf (prop
->value().c_str(), "%d,%d,%d,%d",
1607 if ((prop
= node
.property ("gain")) != 0) {
1608 set_gain (atof (prop
->value().c_str()), this);
1609 _gain
= _desired_gain
;
1612 if ((prop
= node
.property ("automation-state")) != 0 || (prop
= node
.property ("automation-style")) != 0) {
1613 /* old school automation handling */
1616 if ((prop
= node
.property (X_("active"))) != 0) {
1617 set_active (string_is_affirmative (prop
->value()));
1620 for (iter
= node
.children().begin(); iter
!= node
.children().end(); ++iter
) {
1622 if ((*iter
)->name() == "Panner") {
1624 _panner
= new Panner (_name
, _session
);
1626 _panner
->set_state (**iter
);
1629 if ((*iter
)->name() == X_("Automation")) {
1631 set_automation_state (*(*iter
)->children().front());
1634 if ((*iter
)->name() == X_("controllable")) {
1635 if ((prop
= (*iter
)->property("name")) != 0 && prop
->value() == "gaincontrol") {
1636 _gain_control
.set_state (**iter
);
1643 if (create_ports (node
)) {
1649 port_legal_c
= PortsLegal
.connect (mem_fun (*this, &IO::ports_became_legal
));
1652 if (panners_legal
) {
1655 panner_legal_c
= PannersLegal
.connect (mem_fun (*this, &IO::panners_became_legal
));
1658 if (connecting_legal
) {
1660 if (make_connections (node
)) {
1666 connection_legal_c
= ConnectingLegal
.connect (mem_fun (*this, &IO::connecting_became_legal
));
1669 if (!ports_legal
|| !connecting_legal
) {
1670 pending_state_node
= new XMLNode (node
);
1673 last_automation_snapshot
= 0;
1679 IO::set_automation_state (const XMLNode
& node
)
1681 return _gain_automation_curve
.set_state (node
);
1685 IO::get_automation_state ()
1687 return (_gain_automation_curve
.get_state ());
1691 IO::load_automation (string path
)
1696 uint32_t linecnt
= 0;
1698 LocaleGuard
lg (X_("POSIX"));
1700 fullpath
= Glib::build_filename(_session
.automation_dir(), path
);
1702 in
.open (fullpath
.c_str());
1705 fullpath
= Glib::build_filename(_session
.automation_dir(), _session
.snap_name() + '-' + path
);
1707 in
.open (fullpath
.c_str());
1710 error
<< string_compose(_("%1: cannot open automation event file \"%2\""), _name
, fullpath
) << endmsg
;
1715 clear_automation ();
1717 while (in
.getline (line
, sizeof(line
), '\n')) {
1719 jack_nframes_t when
;
1722 if (++linecnt
== 1) {
1723 if (memcmp (line
, "version", 7) == 0) {
1724 if (sscanf (line
, "version %f", &version
) != 1) {
1725 error
<< string_compose(_("badly formed version number in automation event file \"%1\""), path
) << endmsg
;
1729 error
<< string_compose(_("no version information in automation event file \"%1\""), path
) << endmsg
;
1736 if (sscanf (line
, "%c %" PRIu32
" %lf", &type
, &when
, &value
) != 3) {
1737 warning
<< string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt
, path
) << endmsg
;
1743 _gain_automation_curve
.fast_simple_add (when
, value
);
1753 /* older (pre-1.0) versions of ardour used this */
1757 warning
<< _("dubious automation event found (and ignored)") << endmsg
;
1765 IO::connecting_became_legal ()
1769 if (pending_state_node
== 0) {
1770 fatal
<< _("IO::connecting_became_legal() called without a pending state node") << endmsg
;
1775 connection_legal_c
.disconnect ();
1777 ret
= make_connections (*pending_state_node
);
1780 delete pending_state_node
;
1781 pending_state_node
= 0;
1787 IO::ports_became_legal ()
1791 if (pending_state_node
== 0) {
1792 fatal
<< _("IO::ports_became_legal() called without a pending state node") << endmsg
;
1797 port_legal_c
.disconnect ();
1799 ret
= create_ports (*pending_state_node
);
1801 if (connecting_legal
) {
1802 delete pending_state_node
;
1803 pending_state_node
= 0;
1810 IO::find_possible_connection(const string
&desired_name
, const string
&default_name
, const string
&connection_type_name
)
1812 static const string digits
= "0123456789";
1814 Connection
* c
= _session
.connection_by_name (desired_name
);
1817 int connection_number
, mask
;
1818 string possible_name
;
1819 bool stereo
= false;
1820 string::size_type last_non_digit_pos
;
1822 error
<< string_compose(_("Unknown connection \"%1\" listed for %2 of %3"), desired_name
, connection_type_name
, _name
)
1825 // find numeric suffix of desired name
1826 connection_number
= 0;
1828 last_non_digit_pos
= desired_name
.find_last_not_of(digits
);
1830 if (last_non_digit_pos
!= string::npos
) {
1832 s
<< desired_name
.substr(last_non_digit_pos
);
1833 s
>> connection_number
;
1836 // see if it's a stereo connection e.g. "in 3+4"
1838 if (last_non_digit_pos
> 1 && desired_name
[last_non_digit_pos
] == '+') {
1839 int left_connection_number
= 0;
1840 string::size_type left_last_non_digit_pos
;
1842 left_last_non_digit_pos
= desired_name
.find_last_not_of(digits
, last_non_digit_pos
-1);
1844 if (left_last_non_digit_pos
!= string::npos
) {
1846 s
<< desired_name
.substr(left_last_non_digit_pos
, last_non_digit_pos
-1);
1847 s
>> left_connection_number
;
1849 if (left_connection_number
> 0 && left_connection_number
+ 1 == connection_number
) {
1850 connection_number
--;
1857 if (connection_number
)
1858 connection_number
--;
1860 // find highest set bit
1862 while ((mask
<= connection_number
) && (mask
<<= 1));
1864 // "wrap" connection number into largest possible power of 2
1869 if (connection_number
& mask
) {
1870 connection_number
&= ~mask
;
1873 s
<< default_name
<< " " << connection_number
+ 1;
1876 s
<< "+" << connection_number
+ 2;
1879 possible_name
= s
.str();
1881 if ((c
= _session
.connection_by_name (possible_name
)) != 0) {
1888 info
<< string_compose (_("Connection %1 was not available - \"%2\" used instead"), desired_name
, possible_name
)
1891 error
<< string_compose(_("No %1 connections available as a replacement"), connection_type_name
)
1902 IO::create_ports (const XMLNode
& node
)
1904 const XMLProperty
* prop
;
1906 int num_outputs
= 0;
1908 if ((prop
= node
.property ("input-connection")) != 0) {
1910 Connection
* c
= find_possible_connection(prop
->value(), _("in"), _("input"));
1916 num_inputs
= c
->nports();
1918 } else if ((prop
= node
.property ("inputs")) != 0) {
1920 num_inputs
= count (prop
->value().begin(), prop
->value().end(), '{');
1923 if ((prop
= node
.property ("output-connection")) != 0) {
1924 Connection
* c
= find_possible_connection(prop
->value(), _("out"), _("output"));
1930 num_outputs
= c
->nports ();
1932 } else if ((prop
= node
.property ("outputs")) != 0) {
1933 num_outputs
= count (prop
->value().begin(), prop
->value().end(), '{');
1936 no_panner_reset
= true;
1938 if (ensure_io (num_inputs
, num_outputs
, true, this)) {
1939 error
<< string_compose(_("%1: cannot create I/O ports"), _name
) << endmsg
;
1943 no_panner_reset
= false;
1945 set_deferred_state ();
1953 IO::make_connections (const XMLNode
& node
)
1955 const XMLProperty
* prop
;
1957 if ((prop
= node
.property ("input-connection")) != 0) {
1958 Connection
* c
= find_possible_connection (prop
->value(), _("in"), _("input"));
1964 use_input_connection (*c
, this);
1966 } else if ((prop
= node
.property ("inputs")) != 0) {
1967 if (set_inputs (prop
->value())) {
1968 error
<< string_compose(_("improper input channel list in XML node (%1)"), prop
->value()) << endmsg
;
1973 if ((prop
= node
.property ("output-connection")) != 0) {
1974 Connection
* c
= find_possible_connection (prop
->value(), _("out"), _("output"));
1980 use_output_connection (*c
, this);
1982 } else if ((prop
= node
.property ("outputs")) != 0) {
1983 if (set_outputs (prop
->value())) {
1984 error
<< string_compose(_("improper output channel list in XML node (%1)"), prop
->value()) << endmsg
;
1993 IO::set_inputs (const string
& str
)
1995 vector
<string
> ports
;
2000 if ((nports
= count (str
.begin(), str
.end(), '{')) == 0) {
2004 if (ensure_inputs (nports
, true, true, this)) {
2008 string::size_type start
, end
, ostart
;
2015 while ((start
= str
.find_first_of ('{', ostart
)) != string::npos
) {
2018 if ((end
= str
.find_first_of ('}', start
)) == string::npos
) {
2019 error
<< string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str
) << endmsg
;
2023 if ((n
= parse_io_string (str
.substr (start
, end
- start
), ports
)) < 0) {
2024 error
<< string_compose(_("bad input string in XML node \"%1\""), str
) << endmsg
;
2030 for (int x
= 0; x
< n
; ++x
) {
2031 connect_input (input (i
), ports
[x
], this);
2043 IO::set_outputs (const string
& str
)
2045 vector
<string
> ports
;
2050 if ((nports
= count (str
.begin(), str
.end(), '{')) == 0) {
2054 if (ensure_outputs (nports
, true, true, this)) {
2058 string::size_type start
, end
, ostart
;
2065 while ((start
= str
.find_first_of ('{', ostart
)) != string::npos
) {
2068 if ((end
= str
.find_first_of ('}', start
)) == string::npos
) {
2069 error
<< string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str
) << endmsg
;
2073 if ((n
= parse_io_string (str
.substr (start
, end
- start
), ports
)) < 0) {
2074 error
<< string_compose(_("IO: bad output string in XML node \"%1\""), str
) << endmsg
;
2080 for (int x
= 0; x
< n
; ++x
) {
2081 connect_output (output (i
), ports
[x
], this);
2093 IO::parse_io_string (const string
& str
, vector
<string
>& ports
)
2095 string::size_type pos
, opos
;
2097 if (str
.length() == 0) {
2106 while ((pos
= str
.find_first_of (',', opos
)) != string::npos
) {
2107 ports
.push_back (str
.substr (opos
, pos
- opos
));
2111 if (opos
< str
.length()) {
2112 ports
.push_back (str
.substr(opos
));
2115 return ports
.size();
2119 IO::parse_gain_string (const string
& str
, vector
<string
>& ports
)
2121 string::size_type pos
, opos
;
2127 while ((pos
= str
.find_first_of (',', opos
)) != string::npos
) {
2128 ports
.push_back (str
.substr (opos
, pos
- opos
));
2132 if (opos
< str
.length()) {
2133 ports
.push_back (str
.substr(opos
));
2136 return ports
.size();
2140 IO::set_name (string requested_name
, void* src
)
2142 if (requested_name
== _name
) {
2148 if ( (rt
= dynamic_cast<Route
*>(this))) {
2149 name
= Route::ensure_track_or_route_name(requested_name
, _session
);
2151 name
= requested_name
;
2155 /* replace all colons in the name. i wish we didn't have to do this */
2157 if (replace_all (name
, ":", "-")) {
2158 warning
<< _("you cannot use colons to name objects with I/O connections") << endmsg
;
2161 for (vector
<Port
*>::iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
2162 string current_name
= (*i
)->short_name();
2163 current_name
.replace (current_name
.find (_name
), _name
.length(), name
);
2164 (*i
)->set_name (current_name
);
2167 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
2168 string current_name
= (*i
)->short_name();
2169 current_name
.replace (current_name
.find (_name
), _name
.length(), name
);
2170 (*i
)->set_name (current_name
);
2174 name_changed (src
); /* EMIT SIGNAL */
2180 IO::set_input_minimum (int n
)
2186 IO::set_input_maximum (int n
)
2192 IO::set_output_minimum (int n
)
2194 _output_minimum
= n
;
2198 IO::set_output_maximum (int n
)
2200 _output_maximum
= n
;
2204 IO::set_port_latency (nframes_t nframes
)
2206 Glib::Mutex::Lock
lm (io_lock
);
2208 for (vector
<Port
*>::iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
2209 (*i
)->set_latency (nframes
);
2214 IO::output_latency () const
2216 nframes_t max_latency
;
2221 /* io lock not taken - must be protected by other means */
2223 for (vector
<Port
*>::const_iterator i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
2224 if ((latency
= _session
.engine().get_port_total_latency (*(*i
))) > max_latency
) {
2225 max_latency
= latency
;
2233 IO::input_latency () const
2235 nframes_t max_latency
;
2240 /* io lock not taken - must be protected by other means */
2242 for (vector
<Port
*>::const_iterator i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
2243 if ((latency
= _session
.engine().get_port_total_latency (*(*i
))) > max_latency
) {
2244 max_latency
= latency
;
2252 IO::use_input_connection (Connection
& c
, void* src
)
2257 BLOCK_PROCESS_CALLBACK ();
2258 Glib::Mutex::Lock
lm2 (io_lock
);
2262 drop_input_connection ();
2264 if (ensure_inputs (limit
, false, false, src
)) {
2268 /* first pass: check the current state to see what's correctly
2269 connected, and drop anything that we don't want.
2272 for (uint32_t n
= 0; n
< limit
; ++n
) {
2273 const Connection::PortList
& pl
= c
.port_connections (n
);
2275 for (Connection::PortList::const_iterator i
= pl
.begin(); i
!= pl
.end(); ++i
) {
2277 if (!_inputs
[n
]->connected_to ((*i
))) {
2279 /* clear any existing connections */
2281 _session
.engine().disconnect (_inputs
[n
]);
2283 } else if (_inputs
[n
]->connected() > 1) {
2285 /* OK, it is connected to the port we want,
2286 but its also connected to other ports.
2287 Change that situation.
2290 /* XXX could be optimized to not drop
2294 _session
.engine().disconnect (_inputs
[n
]);
2300 /* second pass: connect all requested ports where necessary */
2302 for (uint32_t n
= 0; n
< limit
; ++n
) {
2303 const Connection::PortList
& pl
= c
.port_connections (n
);
2305 for (Connection::PortList::const_iterator i
= pl
.begin(); i
!= pl
.end(); ++i
) {
2307 if (!_inputs
[n
]->connected_to ((*i
))) {
2309 if (_session
.engine().connect (*i
, _inputs
[n
]->name())) {
2317 _input_connection
= &c
;
2319 input_connection_configuration_connection
= c
.ConfigurationChanged
.connect
2320 (mem_fun (*this, &IO::input_connection_configuration_changed
));
2321 input_connection_connection_connection
= c
.ConnectionsChanged
.connect
2322 (mem_fun (*this, &IO::input_connection_connection_changed
));
2325 input_changed (IOChange (ConfigurationChanged
|ConnectionsChanged
), src
); /* EMIT SIGNAL */
2330 IO::use_output_connection (Connection
& c
, void* src
)
2335 BLOCK_PROCESS_CALLBACK ();
2336 Glib::Mutex::Lock
lm2 (io_lock
);
2340 drop_output_connection ();
2342 if (ensure_outputs (limit
, false, false, src
)) {
2346 /* first pass: check the current state to see what's correctly
2347 connected, and drop anything that we don't want.
2350 for (uint32_t n
= 0; n
< limit
; ++n
) {
2352 const Connection::PortList
& pl
= c
.port_connections (n
);
2354 for (Connection::PortList::const_iterator i
= pl
.begin(); i
!= pl
.end(); ++i
) {
2356 if (!_outputs
[n
]->connected_to ((*i
))) {
2358 /* clear any existing connections */
2360 _session
.engine().disconnect (_outputs
[n
]);
2362 } else if (_outputs
[n
]->connected() > 1) {
2364 /* OK, it is connected to the port we want,
2365 but its also connected to other ports.
2366 Change that situation.
2369 /* XXX could be optimized to not drop
2373 _session
.engine().disconnect (_outputs
[n
]);
2378 /* second pass: connect all requested ports where necessary */
2380 for (uint32_t n
= 0; n
< limit
; ++n
) {
2382 const Connection::PortList
& pl
= c
.port_connections (n
);
2384 for (Connection::PortList::const_iterator i
= pl
.begin(); i
!= pl
.end(); ++i
) {
2386 if (!_outputs
[n
]->connected_to ((*i
))) {
2388 if (_session
.engine().connect (_outputs
[n
]->name(), *i
)) {
2395 _output_connection
= &c
;
2397 output_connection_configuration_connection
= c
.ConfigurationChanged
.connect
2398 (mem_fun (*this, &IO::output_connection_configuration_changed
));
2399 output_connection_connection_connection
= c
.ConnectionsChanged
.connect
2400 (mem_fun (*this, &IO::output_connection_connection_changed
));
2403 output_changed (IOChange (ConnectionsChanged
|ConfigurationChanged
), src
); /* EMIT SIGNAL */
2409 IO::disable_connecting ()
2411 connecting_legal
= false;
2416 IO::enable_connecting ()
2418 connecting_legal
= true;
2419 return ConnectingLegal ();
2423 IO::disable_ports ()
2425 ports_legal
= false;
2433 return PortsLegal ();
2437 IO::disable_panners (void)
2439 panners_legal
= false;
2444 IO::reset_panners ()
2446 panners_legal
= true;
2447 return PannersLegal ();
2451 IO::input_connection_connection_changed (int ignored
)
2453 use_input_connection (*_input_connection
, this);
2457 IO::input_connection_configuration_changed ()
2459 use_input_connection (*_input_connection
, this);
2463 IO::output_connection_connection_changed (int ignored
)
2465 use_output_connection (*_output_connection
, this);
2469 IO::output_connection_configuration_changed ()
2471 use_output_connection (*_output_connection
, this);
2475 IO::GainControllable::set_value (float val
)
2477 io
.set_gain (direct_control_to_gain (val
), this);
2481 IO::GainControllable::get_value (void) const
2483 return direct_gain_to_control (io
.effective_gain());
2487 IO::reset_peak_meters ()
2489 uint32_t limit
= max (_ninputs
, _noutputs
);
2491 for (uint32_t i
= 0; i
< limit
; ++i
) {
2497 IO::reset_max_peak_meters ()
2499 uint32_t limit
= max (_ninputs
, _noutputs
);
2501 for (uint32_t i
= 0; i
< limit
; ++i
) {
2502 _max_peak_power
[i
] = -INFINITY
;
2507 IO::setup_peak_meters ()
2509 uint32_t limit
= max (_ninputs
, _noutputs
);
2511 while (_peak_power
.size() < limit
) {
2512 _peak_power
.push_back (0);
2513 _visible_peak_power
.push_back (-INFINITY
);
2514 _max_peak_power
.push_back (-INFINITY
);
2519 Update the peak meters.
2521 The meter signal lock is taken to prevent modification of the
2522 Meter signal while updating the meters, taking the meter signal
2523 lock prior to taking the io_lock ensures that all IO will remain
2524 valid while metering.
2529 Glib::Mutex::Lock
guard (m_meter_signal_lock
);
2536 Glib::Mutex::Lock
lm (io_lock
); // READER: meter thread.
2537 uint32_t limit
= max (_ninputs
, _noutputs
);
2539 for (uint32_t n
= 0; n
< limit
; ++n
) {
2541 /* XXX we should use atomic exchange here */
2543 /* grab peak since last read */
2545 float new_peak
= _peak_power
[n
];
2548 /* compute new visible value using falloff */
2550 if (new_peak
> 0.0f
) {
2551 new_peak
= fast_coefficient_to_dB (new_peak
);
2553 new_peak
= -INFINITY
;
2556 /* update max peak */
2558 _max_peak_power
[n
] = max (new_peak
, _max_peak_power
[n
]);
2560 if (Config
->get_meter_falloff() == 0.0f
|| new_peak
> _visible_peak_power
[n
]) {
2561 _visible_peak_power
[n
] = new_peak
;
2563 // do falloff, the config value is in dB/sec, we get updated at 100/sec currently (should be a var somewhere)
2564 new_peak
= _visible_peak_power
[n
] - (Config
->get_meter_falloff() * 0.01f
);
2565 _visible_peak_power
[n
] = max (new_peak
, -INFINITY
);
2571 IO::gain_automation_recording ()
2573 return (_session
.transport_rolling() && _gain_automation_curve
.automation_write() );
2578 IO::clear_automation ()
2580 Glib::Mutex::Lock
lm (automation_lock
);
2581 _gain_automation_curve
.clear ();
2582 _panner
->clear_automation ();
2586 IO::set_gain_automation_state (AutoState state
)
2588 bool changed
= false;
2591 Glib::Mutex::Lock
lm (automation_lock
);
2593 if (state
!= _gain_automation_curve
.automation_state()) {
2595 last_automation_snapshot
= 0;
2596 _gain_automation_curve
.set_automation_state (state
);
2598 /* don't reset gain if we're moving to Off or Write mode;
2599 if we're moving to Write, the user may have manually set up gains
2600 that they don't want to lose */
2601 if (state
!= Auto_Off
&& state
!= Auto_Write
) {
2602 set_gain (_gain_automation_curve
.eval (_session
.transport_frame()), this);
2608 _session
.set_dirty ();
2609 gain_automation_state_changed (); /* EMIT SIGNAL */
2614 IO::set_gain_automation_style (AutoStyle style
)
2616 bool changed
= false;
2619 Glib::Mutex::Lock
lm (automation_lock
);
2621 if (style
!= _gain_automation_curve
.automation_style()) {
2623 _gain_automation_curve
.set_automation_style (style
);
2628 gain_automation_style_changed (); /* EMIT SIGNAL */
2632 IO::inc_gain (gain_t factor
, void *src
)
2634 if (_desired_gain
== 0.0f
)
2635 set_gain (0.000001f
+ (0.000001f
* factor
), src
);
2637 set_gain (_desired_gain
+ (_desired_gain
* factor
), src
);
2641 IO::set_gain (gain_t val
, void *src
)
2643 // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
2645 if (val
> 1.99526231f
) {
2650 Glib::Mutex::Lock
dm (declick_lock
);
2651 _desired_gain
= val
;
2654 if (_session
.transport_stopped()) {
2655 _effective_gain
= val
;
2660 _gain_control
.Changed (); /* EMIT SIGNAL */
2662 if (_session
.transport_stopped() && src
!= 0 && src
!= this && gain_automation_recording()) {
2663 _gain_automation_curve
.add (_session
.transport_frame(), val
);
2666 _session
.set_dirty();
2670 IO::start_gain_touch ()
2672 _gain_automation_curve
.start_touch (_session
.transport_frame());
2676 IO::end_gain_touch ()
2681 if (_session
.transport_rolling() && _gain_automation_curve
.automation_state() == Auto_Touch
) {
2683 when
= _session
.transport_frame();
2686 _gain_automation_curve
.stop_touch (mark
, when
);
2690 IO::start_pan_touch (uint32_t which
)
2692 if (which
< _panner
->size()) {
2693 (*_panner
)[which
]->automation().start_touch (_session
.transport_frame());
2698 IO::end_pan_touch (uint32_t which
)
2700 if (which
< _panner
->size()) {
2704 if (_session
.transport_rolling() && (*_panner
)[which
]->automation().automation_state() == Auto_Touch
) {
2706 when
= _session
.transport_frame();
2709 (*_panner
)[which
]->automation().stop_touch(mark
, when
);
2714 IO::automation_snapshot (nframes_t now
, bool force
)
2716 if (gain_automation_recording()) {
2717 _gain_automation_curve
.rt_add (now
, gain());
2720 _panner
->snapshot (now
);
2721 last_automation_snapshot
= now
;
2725 IO::transport_stopped (nframes_t frame
)
2727 _gain_automation_curve
.write_pass_finished (frame
);
2729 if (_gain_automation_curve
.automation_state() == Auto_Touch
|| _gain_automation_curve
.automation_state() == Auto_Play
) {
2731 /* the src=0 condition is a special signal to not propagate
2732 automation gain changes into the mix group when locating.
2735 set_gain (_gain_automation_curve
.eval (frame
), 0);
2738 _panner
->transport_stopped (frame
);
2742 IO::build_legal_port_name (bool in
)
2744 const int name_size
= jack_port_name_size();
2749 /* note that if "in" or "out" are translated it will break a session
2750 across locale switches because a port's connection list will
2751 show (old) translated names, but the current port name will
2752 use the (new) translated name.
2756 if (getenv ("ARDOUR_RETAIN_PORT_NAME_SUFFIX_TRANSLATION") != 0) {
2761 maxports
= _input_maximum
;
2763 if (getenv ("ARDOUR_RETAIN_PORT_NAME_SUFFIX_TRANSLATION") != 0) {
2768 maxports
= _output_maximum
;
2771 if (maxports
== 1) {
2772 // allow space for the slash + the suffix
2773 limit
= name_size
- _session
.engine().client_name().length() - (strlen (suffix
) + 1);
2774 char buf
[name_size
+1];
2775 snprintf (buf
, name_size
+1, ("%.*s/%s"), limit
, _name
.c_str(), suffix
);
2776 return string (buf
);
2779 // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
2781 limit
= name_size
- _session
.engine().client_name().length() - (strlen (suffix
) + 5);
2783 char buf1
[name_size
+1];
2784 char buf2
[name_size
+1];
2786 snprintf (buf1
, name_size
+1, ("%.*s/%s"), limit
, _name
.c_str(), suffix
);
2791 port_number
= find_input_port_hole (buf1
);
2793 port_number
= find_output_port_hole (buf1
);
2796 snprintf (buf2
, name_size
+1, "%s %d", buf1
, port_number
);
2798 return string (buf2
);
2802 IO::find_input_port_hole (const char* base
)
2804 /* CALLER MUST HOLD IO LOCK */
2808 if (_inputs
.empty()) {
2812 /* we only allow up to 4 characters for the port number
2815 for (n
= 1; n
< 9999; ++n
) {
2816 char buf
[jack_port_name_size()];
2817 vector
<Port
*>::iterator i
;
2819 snprintf (buf
, jack_port_name_size(), _("%s %u"), base
, n
);
2821 for (i
= _inputs
.begin(); i
!= _inputs
.end(); ++i
) {
2822 if ((*i
)->short_name() == buf
) {
2827 if (i
== _inputs
.end()) {
2835 IO::find_output_port_hole (const char* base
)
2837 /* CALLER MUST HOLD IO LOCK */
2841 if (_outputs
.empty()) {
2845 /* we only allow up to 4 characters for the port number
2848 for (n
= 1; n
< 9999; ++n
) {
2849 char buf
[jack_port_name_size()];
2850 vector
<Port
*>::iterator i
;
2852 snprintf (buf
, jack_port_name_size(), _("%s %u"), base
, n
);
2854 for (i
= _outputs
.begin(); i
!= _outputs
.end(); ++i
) {
2855 if ((*i
)->short_name() == buf
) {
2860 if (i
== _outputs
.end()) {
2869 IO::set_active (bool yn
)
2872 active_changed(); /* EMIT SIGNAL */
2876 IO::name_from_state (const XMLNode
& node
)
2878 const XMLProperty
* prop
;
2880 if ((prop
= node
.property ("name")) != 0) {
2881 return prop
->value();
2888 IO::set_name_in_state (XMLNode
& node
, const string
& new_name
)
2890 const XMLProperty
* prop
;
2892 if ((prop
= node
.property ("name")) != 0) {
2893 node
.add_property ("name", new_name
);
2898 IO::cycle_start (nframes_t nframes
)
2904 IO::increment_output_offset (nframes_t n
)
2906 _output_offset
+= n
;
2910 IO::get_input_buffer (int n
, nframes_t nframes
)
2914 if (!(port
= input (n
))) {
2918 return port
->get_buffer (nframes
);
2922 IO::get_output_buffer (int n
, nframes_t nframes
)
2926 if (!(port
= output (n
))) {
2930 return port
->get_buffer (nframes
) + _output_offset
;