Fixed i18n system.
[ardour.git] / libs / ardour / io.cc
index 6b6773c49d85139c49761e06486eba12c9624dab..87c03c6b70fafe56440cc694af29a188dcc697ea 100644 (file)
@@ -25,7 +25,8 @@
 
 #include <sigc++/bind.h>
 
-#include <pbd/lockmonitor.h>
+#include <glibmm/thread.h>
+
 #include <pbd/xml++.h>
 
 #include <ardour/audioengine.h>
@@ -54,7 +55,8 @@ extern "C" int isinf (double);
 
 using namespace std;
 using namespace ARDOUR;
-//using namespace sigc;
+using namespace PBD;
+
 
 static float current_automation_version_number = 1.0;
 
@@ -63,13 +65,15 @@ const string IO::state_node_name = "IO";
 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().
 */
@@ -126,13 +130,20 @@ IO::IO (Session& s, string name,
 
        _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) {
@@ -142,6 +153,8 @@ IO::~IO ()
        for (i = _outputs.begin(); i != _outputs.end(); ++i) {
                _session.engine().unregister_port (*i);
        }
+
+    m_meter_connection.disconnect();
 }
 
 void
@@ -162,7 +175,10 @@ IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframe
        Sample *buffer;
        double fractional_shift;
        double fractional_pos;
+       gain_t polscale = invert_polarity ? -1.0f : 1.0f;
 
+       if (nframes == 0) return;
+       
        fractional_shift = -1.0/declick;
 
        if (target < initial) {
@@ -178,16 +194,9 @@ IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nframe
                buffer = bufs[n];
                fractional_pos = 1.0;
 
-               if (invert_polarity) {
-                       for (jack_nframes_t nx = 0; nx < declick; ++nx) {
-                               buffer[nx] *= -(initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
-                               fractional_pos += fractional_shift;
-                       }
-               } else {
-                       for (jack_nframes_t nx = 0; nx < declick; ++nx) {
-                               buffer[nx] *= (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
-                               fractional_pos += fractional_shift;
-                       }
+               for (jack_nframes_t nx = 0; nx < declick; ++nx) {
+                       buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
+                       fractional_pos += fractional_shift;
                }
                
                /* now ensure the rest of the buffer has the target value
@@ -374,16 +383,17 @@ IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nfram
                return;
        }
        
-       if (_panner->bypassed()) {
+       if (_panner->bypassed() || _panner->empty()) {
                deliver_output_no_pan (bufs, nbufs, nframes, offset);
                return;
        }
 
 
        gain_t dg;
-
+       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;
@@ -395,14 +405,15 @@ IO::deliver_output (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_t nfram
        if (dg != _gain) {
                apply_declick (bufs, nbufs, nframes, _gain, dg, false);
                _gain = dg;
+               pangain = 1.0f;
        } 
 
        /* simple, non-automation panning to outputs */
 
        if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
-               pan (bufs, nbufs, nframes, offset, _gain * speed_quietning);
+               pan (bufs, nbufs, nframes, offset, pangain * speed_quietning);
        } else {
-               pan (bufs, nbufs, nframes, offset, _gain);
+               pan (bufs, nbufs, nframes, offset, pangain);
        }
 }
 
@@ -429,7 +440,7 @@ IO::deliver_output_no_pan (vector<Sample *>& bufs, uint32_t nbufs, jack_nframes_
                
        } else {
 
-               TentativeLockMonitor dm (declick_lock, __LINE__, __FILE__);
+               Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
                
                if (dm.locked()) {
                        dg = _desired_gain;
@@ -570,10 +581,10 @@ IO::disconnect_input (Port* our_port, string other_port, 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);
                        
                        /* check that our_port is really one of ours */
                        
@@ -606,10 +617,10 @@ IO::connect_input (Port* our_port, string other_port, 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);
                        
                        /* check that our_port is really one of ours */
                        
@@ -640,10 +651,10 @@ IO::disconnect_output (Port* our_port, string other_port, 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);
                        
                        if (find (_outputs.begin(), _outputs.end(), our_port) == _outputs.end()) {
                                return -1;
@@ -673,10 +684,10 @@ IO::connect_output (Port* our_port, string other_port, 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);
                        
                        /* check that our_port is really one of ours */
                        
@@ -732,10 +743,10 @@ IO::remove_output_port (Port* port, void* src)
        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 */
@@ -781,10 +792,10 @@ IO::add_output_port (string destination, void* src)
        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;
@@ -832,10 +843,10 @@ IO::remove_input_port (Port* port, void* src)
        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 */
@@ -882,10 +893,10 @@ IO::add_input_port (string source, void* src)
        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;
@@ -933,10 +944,10 @@ int
 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);
@@ -953,10 +964,10 @@ int
 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);
@@ -1065,8 +1076,8 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
        }
 
        {
-               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;
                
@@ -1173,11 +1184,11 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src)
                                _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) {
@@ -1214,7 +1225,8 @@ IO::ensure_inputs (uint32_t n, bool clear, bool lockit, void* src)
        }
        
        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);
@@ -1315,7 +1327,8 @@ IO::ensure_outputs (uint32_t n, bool clear, bool lockit, void* 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);
@@ -1389,7 +1402,7 @@ IO::state (bool full_state)
        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());
@@ -2058,7 +2071,7 @@ IO::set_output_maximum (int n)
 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);
@@ -2109,8 +2122,8 @@ IO::use_input_connection (Connection& c, void* src)
        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();
                
@@ -2187,8 +2200,8 @@ IO::use_output_connection (Connection& c, void* src)
        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();
                        
@@ -2408,7 +2421,7 @@ IO::setup_peak_meters ()
 
        while (_peak_power.size() < limit) {
                _peak_power.push_back (0);
-               _stored_peak_power.push_back (0);
+               _visible_peak_power.push_back (0);
        }
 }
 
@@ -2431,23 +2444,52 @@ IO::state_factory (std::string why) const
        return state;
 }
 
+/**
+    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::send_state_changed ()
+IO::update_meters()
 {
-       return;
+    Glib::Mutex::Lock guard (m_meter_signal_lock);
+    
+    Meter();
 }
 
 void
-IO::grab_peak_power ()
+IO::meter ()
 {
-       LockMonitor lm (io_lock, __LINE__, __FILE__);
-
+       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, -INFINITY);
+               }
        }
 }
 
@@ -2583,7 +2625,7 @@ IO::load_automation (const string& path)
 void
 IO::clear_automation ()
 {
-       LockMonitor lm (automation_lock, __LINE__, __FILE__);
+       Glib::Mutex::Lock lm (automation_lock);
        _gain_automation_curve.clear ();
        _panner->clear_automation ();
 }
@@ -2594,7 +2636,7 @@ IO::set_gain_automation_state (AutoState state)
        bool changed = false;
 
        {
-               LockMonitor lm (automation_lock, __LINE__, __FILE__);
+               Glib::Mutex::Lock lm (automation_lock);
 
                if (state != _gain_automation_curve.automation_state()) {
                        changed = true;
@@ -2619,7 +2661,7 @@ IO::set_gain_automation_style (AutoStyle style)
        bool changed = false;
 
        {
-               LockMonitor lm (automation_lock, __LINE__, __FILE__);
+               Glib::Mutex::Lock lm (automation_lock);
 
                if (style != _gain_automation_curve.automation_style()) {
                        changed = true;
@@ -2647,7 +2689,7 @@ IO::set_gain (gain_t val, void *src)
        if (val>1.99526231f) val=1.99526231f;
 
        {
-               LockMonitor dm (declick_lock, __LINE__, __FILE__);
+               Glib::Mutex::Lock dm (declick_lock);
                _desired_gain = val;
        }