#include <sigc++/bind.h>
-#include <pbd/lockmonitor.h>
+#include <glibmm/thread.h>
+
#include <pbd/xml++.h>
#include <ardour/audioengine.h>
bool IO::connecting_legal = false;
bool IO::ports_legal = false;
bool IO::panners_legal = false;
-sigc::signal<void> IO::GrabPeakPower;
+sigc::signal<void> IO::Meter;
sigc::signal<int> IO::ConnectingLegal;
sigc::signal<int> IO::PortsLegal;
sigc::signal<int> IO::PannersLegal;
sigc::signal<void,uint32_t> IO::MoreOutputs;
sigc::signal<int> IO::PortsCreated;
+Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
+
/* this is a default mapper of MIDI control values to a gain coefficient.
others can be imagined. see IO::set_midi_to_gain_function().
*/
_gain_automation_state = Off;
_gain_automation_style = Absolute;
-
- GrabPeakPower.connect (mem_fun (*this, &IO::grab_peak_power));
+
+ {
+ // IO::Meter is emitted from another thread so the
+ // Meter signal must be protected.
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+ m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
+ }
}
IO::~IO ()
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+ Glib::Mutex::Lock lm (io_lock);
vector<Port *>::iterator i;
for (i = _inputs.begin(); i != _inputs.end(); ++i) {
for (i = _outputs.begin(); i != _outputs.end(); ++i) {
_session.engine().unregister_port (*i);
}
+
+ m_meter_connection.disconnect();
}
void
double fractional_shift;
double fractional_pos;
gain_t polscale = invert_polarity ? -1.0f : 1.0f;
+
+ if (nframes == 0) return;
fractional_shift = -1.0/declick;
gain_t pangain = _gain;
{
- TentativeLockMonitor dm (declick_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
if (dm.locked()) {
dg = _desired_gain;
} else {
- TentativeLockMonitor dm (declick_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
if (dm.locked()) {
dg = _desired_gain;
}
{
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
/* check that our_port is really one of ours */
}
{
- LockMonitor em(_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em(_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
/* check that our_port is really one of ours */
}
{
- LockMonitor em(_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em(_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
return -1;
}
{
- LockMonitor em(_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em(_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
/* check that our_port is really one of ours */
IOChange change (NoChange);
{
- LockMonitor em(_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em(_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
if (_noutputs - 1 == (uint32_t) _output_minimum) {
/* sorry, you can't do this */
char buf[64];
{
- LockMonitor em(_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em(_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
if (_output_maximum >= 0 && (int) _noutputs == _output_maximum) {
return -1;
IOChange change (NoChange);
{
- LockMonitor em(_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em(_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
if (((int)_ninputs - 1) < _input_minimum) {
/* sorry, you can't do this */
char buf[64];
{
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
if (_input_maximum >= 0 && (int) _ninputs == _input_maximum) {
return -1;
IO::disconnect_inputs (void* src)
{
{
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
for (vector<Port *>::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
_session.engine().disconnect (*i);
IO::disconnect_outputs (void* src)
{
{
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
_session.engine().disconnect (*i);
}
{
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
+ Glib::Mutex::Lock lm (io_lock);
Port* port;
_session.engine().disconnect (*i);
}
}
- }
-
- if (in_changed || out_changed) {
- setup_peak_meters ();
- reset_panner ();
+
+ if (in_changed || out_changed) {
+ setup_peak_meters ();
+ reset_panner ();
+ }
}
if (out_changed) {
}
if (lockit) {
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
+ Glib::Mutex::Lock im (io_lock);
changed = ensure_inputs_locked (n, clear, src);
} else {
changed = ensure_inputs_locked (n, clear, src);
/* XXX caller should hold io_lock, but generally doesn't */
if (lockit) {
- LockMonitor em (_session.engine().process_lock(), __LINE__, __FILE__);
+ Glib::Mutex::Lock em (_session.engine().process_lock());
+ Glib::Mutex::Lock im (io_lock);
changed = ensure_outputs_locked (n, clear, src);
} else {
changed = ensure_outputs_locked (n, clear, src);
bool need_ins = true;
bool need_outs = true;
LocaleGuard lg (X_("POSIX"));
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
node->add_property("name", _name);
snprintf (buf, sizeof(buf), "%" PRIu64, id());
void
IO::set_port_latency (jack_nframes_t nframes)
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (io_lock);
for (vector<Port *>::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
(*i)->set_latency (nframes);
uint32_t limit;
{
- LockMonitor lm (_session.engine().process_lock(), __LINE__, __FILE__);
- LockMonitor lm2 (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (_session.engine().process_lock());
+ Glib::Mutex::Lock lm2 (io_lock);
limit = c.nports();
uint32_t limit;
{
- LockMonitor lm (_session.engine().process_lock(), __LINE__, __FILE__);
- LockMonitor lm2 (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (_session.engine().process_lock());
+ Glib::Mutex::Lock lm2 (io_lock);
limit = c.nports();
while (_peak_power.size() < limit) {
_peak_power.push_back (0);
- _stored_peak_power.push_back (0);
+ _visible_peak_power.push_back (0);
}
}
return;
}
+/**
+ Update the peak meters.
+
+ The meter signal lock is taken to prevent modification of the
+ Meter signal while updating the meters, taking the meter signal
+ lock prior to taking the io_lock ensures that all IO will remain
+ valid while metering.
+*/
void
-IO::grab_peak_power ()
+IO::update_meters()
{
- LockMonitor lm (io_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+
+ Meter();
+}
+void
+IO::meter ()
+{
+ Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
uint32_t limit = max (_ninputs, _noutputs);
-
+
for (uint32_t n = 0; n < limit; ++n) {
- /* XXX should we use atomic exchange here ? */
- _stored_peak_power[n] = _peak_power[n];
+
+ /* XXX we should use atomic exchange here */
+
+ /* grab peak since last read */
+
+ float new_peak = _peak_power[n];
_peak_power[n] = 0;
+
+ /* compute new visible value using falloff */
+
+ if (new_peak > 0.0) {
+ new_peak = coefficient_to_dB (new_peak);
+ } else {
+ new_peak = minus_infinity();
+ }
+
+ if (_session.meter_falloff() == 0.0f || new_peak > _visible_peak_power[n]) {
+ _visible_peak_power[n] = new_peak;
+ } else {
+ // do falloff
+ new_peak = _visible_peak_power[n] - _session.meter_falloff();
+ _visible_peak_power[n] = max (new_peak, -200.0f);
+ }
}
}
void
IO::clear_automation ()
{
- LockMonitor lm (automation_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (automation_lock);
_gain_automation_curve.clear ();
_panner->clear_automation ();
}
bool changed = false;
{
- LockMonitor lm (automation_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (automation_lock);
if (state != _gain_automation_curve.automation_state()) {
changed = true;
bool changed = false;
{
- LockMonitor lm (automation_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (automation_lock);
if (style != _gain_automation_curve.automation_style()) {
changed = true;
if (val>1.99526231f) val=1.99526231f;
{
- LockMonitor dm (declick_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock dm (declick_lock);
_desired_gain = val;
}