ensure that GainControl::get_value() never returns > Config->get_max_gain()
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 4 Mar 2016 16:42:43 +0000 (11:42 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 31 May 2016 19:30:39 +0000 (15:30 -0400)
libs/ardour/ardour/gain_control.h
libs/ardour/gain_control.cc

index f8331633833a33f256306897ac0bbc4f5e867b31..c44a76dd04bd0a4ad70f27afea16e77239fabc8f 100644 (file)
@@ -93,6 +93,7 @@ class LIBARDOUR_API GainControl : public AutomationControl {
        PBD::ScopedConnectionList masters_connections;
        std::string _masters_state_string ();
 
+       gain_t get_value_locked () const;
        gain_t get_master_gain_locked () const;
        void master_going_away (boost::weak_ptr<VCA>);
        void recompute_masters_ratios (double val);
index 52752dcdda51a2f9a8f781ef5287f0da40ae591f..b9c381c406eda2acc272e350ac55e3d59e69a93f 100644 (file)
@@ -43,10 +43,10 @@ GainControl::GainControl (Session& session, const Evoral::Parameter &param, boos
        range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db;
 }
 
-double
-GainControl::get_value () const
-{
-       Glib::Threads::RWLock::ReaderLock lm (master_lock);
+gain_t
+GainControl::get_value_locked () const {
+
+       /* read or write masters lock must be held */
 
        if (_masters.empty()) {
                return AutomationControl::get_value();
@@ -59,7 +59,14 @@ GainControl::get_value () const
                g *= mr->second.master()->get_value () * mr->second.ratio();
        }
 
-       return g;
+       return min (Config->get_max_gain(), g);
+}
+
+double
+GainControl::get_value () const
+{
+       Glib::Threads::RWLock::ReaderLock lm (master_lock);
+       return get_value_locked ();
 }
 
 void
@@ -164,19 +171,20 @@ GainControl::get_master_gain_locked () const
 void
 GainControl::add_master (boost::shared_ptr<VCA> vca)
 {
-       gain_t old_master_val;
+       gain_t current_value;
        std::pair<Masters::iterator,bool> res;
 
        {
                Glib::Threads::RWLock::WriterLock lm (master_lock);
-               old_master_val = get_master_gain_locked ();
+               current_value = get_value_locked ();
 
                /* ratio will be recomputed below */
 
                res = _masters.insert (make_pair<uint32_t,MasterRecord> (vca->number(), MasterRecord (vca->control(), 0.0)));
 
                if (res.second) {
-                       recompute_masters_ratios (old_master_val);
+
+                       recompute_masters_ratios (current_value);
 
                        /* note that we bind @param m as a weak_ptr<GainControl>, thus
                           avoiding holding a reference to the control in the binding
@@ -210,15 +218,15 @@ GainControl::master_going_away (boost::weak_ptr<VCA> wv)
 void
 GainControl::remove_master (boost::shared_ptr<VCA> vca)
 {
-       gain_t old_master_val;
+       gain_t current_value;
        Masters::size_type erased = 0;
 
        {
                Glib::Threads::RWLock::WriterLock lm (master_lock);
-               old_master_val = get_master_gain_locked ();
+               current_value = get_value_locked ();
                erased = _masters.erase (vca->number());
                if (erased) {
-                       recompute_masters_ratios (old_master_val);
+                       recompute_masters_ratios (current_value);
                }
        }