3021151bdc6491b4f51472fa8a2801b5350eb4a0
[ardour.git] / libs / ardour / gain_control.cc
1 /*
2     Copyright (C) 2006-2016 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU General Public License as published by the Free
6     Software Foundation; either version 2 of the License, or (at your option)
7     any later version.
8
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12     for more details.
13
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "ardour/dB.h"
20 #include "ardour/gain_control.h"
21 #include "ardour/session.h"
22
23 #include "i18n.h"
24
25 using namespace ARDOUR;
26 using namespace std;
27
28 GainControl::GainControl (Session& session, const Evoral::Parameter &param, boost::shared_ptr<AutomationList> al)
29         : AutomationControl (session, param, ParameterDescriptor(param),
30                              al ? al : boost::shared_ptr<AutomationList> (new AutomationList (param)),
31                              param.type() == GainAutomation ? X_("gaincontrol") : X_("trimcontrol")) {
32
33         alist()->reset_default (1.0);
34
35         lower_db = accurate_coefficient_to_dB (_desc.lower);
36         range_db = accurate_coefficient_to_dB (_desc.upper) - lower_db;
37 }
38
39 double
40 GainControl::get_value() const
41 {
42         Glib::Threads::Mutex::Lock sm (master_lock, Glib::Threads::TRY_LOCK);
43
44         if (sm.locked()) {
45                 if (_masters.empty()) {
46                         return AutomationControl::get_value();
47                 }
48                 return AutomationControl::get_value() * get_master_gain ();
49         } else {
50                 /* could not take lock */
51                 return AutomationControl::get_value ();
52         }
53 }
54
55 void
56 GainControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
57 {
58         if (writable()) {
59                 _set_value (val, group_override);
60         }
61 }
62
63 void
64 GainControl::set_value_unchecked (double val)
65 {
66         /* used only automation playback */
67         _set_value (val, Controllable::NoGroup);
68 }
69
70 void
71 GainControl::_set_value (double val, Controllable::GroupControlDisposition group_override)
72 {
73         AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower), group_override);
74         _session.set_dirty ();
75 }
76
77 double
78 GainControl::internal_to_interface (double v) const
79 {
80         if (_desc.type == GainAutomation) {
81                 return gain_to_slider_position (v);
82         } else {
83                 return (accurate_coefficient_to_dB (v) - lower_db) / range_db;
84         }
85 }
86
87 double
88 GainControl::interface_to_internal (double v) const
89 {
90         if (_desc.type == GainAutomation) {
91                 return slider_position_to_gain (v);
92         } else {
93                 return dB_to_coefficient (lower_db + v * range_db);
94         }
95 }
96
97 double
98 GainControl::internal_to_user (double v) const
99 {
100         return accurate_coefficient_to_dB (v);
101 }
102
103 double
104 GainControl::user_to_internal (double u) const
105 {
106         return dB_to_coefficient (u);
107 }
108
109 std::string
110 GainControl::get_user_string () const
111 {
112         char theBuf[32]; sprintf( theBuf, _("%3.1f dB"), accurate_coefficient_to_dB (get_value()));
113         return std::string(theBuf);
114 }
115
116 gain_t
117 GainControl::get_master_gain () const
118 {
119         /* Master lock MUST be held */
120
121         gain_t g = 1.0;
122
123         for (Masters::const_iterator m = _masters.begin(); m != _masters.end(); ++m) {
124                 g *= (*m)->get_value ();
125         }
126
127         return g;
128 }
129
130 void
131 GainControl::add_master (boost::shared_ptr<GainControl> m)
132 {
133         gain_t old_master_val;
134         gain_t new_master_val;
135
136         {
137                 Glib::Threads::Mutex::Lock lm (master_lock);
138                 old_master_val = get_master_gain ();
139                 _masters.push_back (m);
140                 new_master_val = get_master_gain ();
141         }
142
143         if (old_master_val != new_master_val) {
144                 Changed(); /* EMIT SIGNAL */
145         }
146 }
147
148 void
149 GainControl::remove_master (boost::shared_ptr<GainControl> m)
150 {
151         gain_t old_master_val;
152         gain_t new_master_val;
153
154         {
155                 Glib::Threads::Mutex::Lock lm (master_lock);
156                 old_master_val = get_master_gain ();
157                 _masters.remove (m);
158                 new_master_val = get_master_gain ();
159         }
160
161         if (old_master_val != new_master_val) {
162                 Changed(); /* EMIT SIGNAL */
163         }
164 }
165
166 void
167 GainControl::clear_masters ()
168 {
169         gain_t old_master_val;
170         gain_t new_master_val;
171
172         {
173                 Glib::Threads::Mutex::Lock lm (master_lock);
174                 old_master_val = get_master_gain ();
175                 _masters.clear ();
176                 new_master_val = get_master_gain ();
177         }
178
179         if (old_master_val != new_master_val) {
180                 Changed(); /* EMIT SIGNAL */
181         }
182 }