start shaping up VCA assign process
[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 void
40 GainControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
41 {
42         if (writable()) {
43                 _set_value (val, group_override);
44         }
45 }
46
47 void
48 GainControl::set_value_unchecked (double val)
49 {
50         /* used only automation playback */
51         _set_value (val, Controllable::NoGroup);
52 }
53
54 void
55 GainControl::_set_value (double val, Controllable::GroupControlDisposition group_override)
56 {
57         AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower), group_override);
58         _session.set_dirty ();
59 }
60
61 double
62 GainControl::internal_to_interface (double v) const
63 {
64         if (_desc.type == GainAutomation) {
65                 return gain_to_slider_position (v);
66         } else {
67                 return (accurate_coefficient_to_dB (v) - lower_db) / range_db;
68         }
69 }
70
71 double
72 GainControl::interface_to_internal (double v) const
73 {
74         if (_desc.type == GainAutomation) {
75                 return slider_position_to_gain (v);
76         } else {
77                 return dB_to_coefficient (lower_db + v * range_db);
78         }
79 }
80
81 double
82 GainControl::internal_to_user (double v) const
83 {
84         return accurate_coefficient_to_dB (v);
85 }
86
87 double
88 GainControl::user_to_internal (double u) const
89 {
90         return dB_to_coefficient (u);
91 }
92
93 std::string
94 GainControl::get_user_string () const
95 {
96         char theBuf[32]; sprintf( theBuf, _("%3.1f dB"), accurate_coefficient_to_dB (get_value()));
97         return std::string(theBuf);
98 }
99
100 gain_t
101 GainControl::get_master_gain () const
102 {
103         Glib::Threads::Mutex::Lock sm (master_lock, Glib::Threads::TRY_LOCK);
104
105         if (sm.locked()) {
106                 return get_master_gain_locked ();
107         }
108
109         return 1.0;
110 }
111
112 gain_t
113 GainControl::get_master_gain_locked () const
114 {
115         /* Master lock MUST be held */
116
117         gain_t g = 1.0;
118
119         for (Masters::const_iterator m = _masters.begin(); m != _masters.end(); ++m) {
120                 g *= (*m)->get_value ();
121         }
122
123         return g;
124 }
125
126 void
127 GainControl::add_master (boost::shared_ptr<GainControl> m)
128 {
129         gain_t old_master_val;
130         gain_t new_master_val;
131
132         {
133                 Glib::Threads::Mutex::Lock lm (master_lock);
134                 old_master_val = get_master_gain_locked ();
135                 _masters.push_back (m);
136                 new_master_val = get_master_gain_locked ();
137         }
138
139         if (old_master_val != new_master_val) {
140                 Changed(); /* EMIT SIGNAL */
141         }
142 }
143
144 void
145 GainControl::remove_master (boost::shared_ptr<GainControl> m)
146 {
147         gain_t old_master_val;
148         gain_t new_master_val;
149
150         {
151                 Glib::Threads::Mutex::Lock lm (master_lock);
152                 old_master_val = get_master_gain_locked ();
153                 _masters.remove (m);
154                 new_master_val = get_master_gain_locked ();
155         }
156
157         if (old_master_val != new_master_val) {
158                 Changed(); /* EMIT SIGNAL */
159         }
160 }
161
162 void
163 GainControl::clear_masters ()
164 {
165         gain_t old_master_val;
166         gain_t new_master_val;
167
168         {
169                 Glib::Threads::Mutex::Lock lm (master_lock);
170                 old_master_val = get_master_gain_locked ();
171                 _masters.clear ();
172                 new_master_val = get_master_gain_locked ();
173         }
174
175         if (old_master_val != new_master_val) {
176                 Changed(); /* EMIT SIGNAL */
177         }
178 }
179
180 bool
181 GainControl::slaved_to (boost::shared_ptr<GainControl> gc) const
182 {
183         Glib::Threads::Mutex::Lock lm (master_lock);
184         return find (_masters.begin(), _masters.end(), gc) != _masters.end();
185 }