save+restore VCA counter value across instances
[ardour.git] / libs / ardour / vca.cc
1 /*
2   Copyright (C) 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 "pbd/convert.h"
20
21 #include "ardour/automation_control.h"
22 #include "ardour/gain_control.h"
23 #include "ardour/rc_configuration.h"
24 #include "ardour/route.h"
25 #include "ardour/session.h"
26 #include "ardour/vca.h"
27
28 #include "i18n.h"
29
30 using namespace ARDOUR;
31 using namespace PBD;
32 using std::string;
33
34 gint VCA::next_number = 1;
35 string VCA::xml_node_name (X_("VCA"));
36
37 string
38 VCA::default_name_template ()
39 {
40         return _("VCA %n");
41 }
42
43 int
44 VCA::next_vca_number ()
45 {
46         /* recall that atomic_int_add() returns the value before the add. We
47          * start at one, then next one will be two etc.
48          */
49         return g_atomic_int_add (&next_number, 1);
50 }
51
52 void
53 VCA::set_next_vca_number (uint32_t n)
54 {
55         g_atomic_int_set (&next_number, n);
56 }
57
58 VCA::VCA (Session& s,  uint32_t num, const string& name)
59         : Stripable (s, name)
60         , Automatable (s)
61         , _number (num)
62         , _gain_control (new GainControl (s, Evoral::Parameter (GainAutomation), boost::shared_ptr<AutomationList> ()))
63         , _solo_requested (false)
64         , _mute_requested (false)
65 {
66 }
67
68 int
69 VCA::init ()
70 {
71         _solo_control.reset (new VCASoloControllable (X_("solo"), shared_from_this()));
72         _mute_control.reset (new VCAMuteControllable (X_("mute"), shared_from_this()));
73
74         add_control (_gain_control);
75         add_control (_solo_control);
76         add_control (_mute_control);
77
78         return 0;
79 }
80
81 VCA::~VCA ()
82 {
83         DropReferences (); /* emit signal */
84 }
85
86 uint32_t
87 VCA::remote_control_id () const
88 {
89         return 9999999 + _number;
90 }
91
92 XMLNode&
93 VCA::get_state ()
94 {
95         XMLNode* node = new XMLNode (xml_node_name);
96         node->add_property (X_("name"), _name);
97         node->add_property (X_("number"), _number);
98         node->add_property (X_("soloed"), (_solo_requested ? X_("yes") : X_("no")));
99         node->add_property (X_("muted"), (_mute_requested ? X_("yes") : X_("no")));
100
101         node->add_child_nocopy (_gain_control->get_state());
102         node->add_child_nocopy (get_automation_xml_state());
103
104         return *node;
105 }
106
107 int
108 VCA::set_state (XMLNode const& node, int version)
109 {
110         XMLProperty const* prop;
111
112         if ((prop = node.property ("name")) != 0) {
113                 set_name (prop->value());
114         }
115
116         if ((prop = node.property ("number")) != 0) {
117                 _number = atoi (prop->value());
118         }
119
120         XMLNodeList const &children (node.children());
121         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
122                 if ((*i)->name() == Controllable::xml_node_name) {
123                         XMLProperty* prop = (*i)->property ("name");
124                         if (prop && prop->value() == X_("gaincontrol")) {
125                                 _gain_control->set_state (**i, version);
126                         }
127                 }
128         }
129
130         return 0;
131 }
132
133 void
134 VCA::add_solo_mute_target (boost::shared_ptr<Route> r)
135 {
136         Glib::Threads::RWLock::WriterLock lm (solo_mute_lock);
137         solo_mute_targets.push_back (r);
138         r->DropReferences.connect_same_thread (solo_mute_connections, boost::bind (&VCA::solo_mute_target_going_away, this, boost::weak_ptr<Route> (r)));
139 }
140
141 void
142 VCA::remove_solo_mute_target (boost::shared_ptr<Route> r)
143 {
144         Glib::Threads::RWLock::WriterLock lm (solo_mute_lock);
145         solo_mute_targets.remove (r);
146 }
147
148 void
149 VCA::solo_mute_target_going_away (boost::weak_ptr<Route> wr)
150 {
151         boost::shared_ptr<Route> r (wr.lock());
152         if (!r) {
153                 return;
154         }
155
156         Glib::Threads::RWLock::WriterLock lm (solo_mute_lock);
157         solo_mute_targets.remove (r);
158 }
159
160 void
161 VCA::set_solo (bool yn)
162 {
163         {
164                 Glib::Threads::RWLock::ReaderLock lm (solo_mute_lock);
165
166                 if (yn == _solo_requested) {
167                         return;
168                 }
169
170                 if (solo_mute_targets.empty()) {
171                         return;
172                 }
173
174                 boost::shared_ptr<RouteList> rl (new RouteList (solo_mute_targets));
175
176                 if (Config->get_solo_control_is_listen_control()) {
177                         _session.set_listen (rl, yn, Session::rt_cleanup, Controllable::NoGroup);
178                 } else {
179                         _session.set_solo (rl, yn, Session::rt_cleanup, Controllable::NoGroup);
180                 }
181         }
182
183         _solo_requested = yn;
184 }
185
186 void
187 VCA::set_mute (bool yn)
188 {
189         {
190                 Glib::Threads::RWLock::ReaderLock lm (solo_mute_lock);
191                 if (yn == _mute_requested) {
192                         return;
193                 }
194
195                 boost::shared_ptr<RouteList> rl (new RouteList (solo_mute_targets));
196                 _session.set_mute (rl, yn, Session::rt_cleanup, Controllable::NoGroup);
197         }
198
199         _mute_requested = yn;
200 }
201
202 bool
203 VCA::soloed () const
204 {
205         return _solo_requested;
206 }
207
208 bool
209 VCA::muted () const
210 {
211         return _mute_requested;
212 }
213
214 VCA::VCASoloControllable::VCASoloControllable (string const & name, boost::shared_ptr<VCA> vca)
215         : AutomationControl (vca->session(), Evoral::Parameter (SoloAutomation), ParameterDescriptor (Evoral::Parameter (SoloAutomation)),
216                              boost::shared_ptr<AutomationList>(), name)
217         , _vca (vca)
218 {
219 }
220
221 void
222 VCA::VCASoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
223 {
224         if (writable()) {
225                 _set_value (val, gcd);
226         }
227 }
228
229 void
230 VCA::VCASoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
231 {
232         boost::shared_ptr<VCA> vca = _vca.lock();
233         if (!vca) {
234                 return;
235         }
236
237         vca->set_solo (val >= 0.5);
238
239         AutomationControl::set_value (val, gcd);
240 }
241
242 void
243 VCA::VCASoloControllable::set_value_unchecked (double val)
244 {
245         /* used only by automation playback */
246         _set_value (val, Controllable::NoGroup);
247 }
248
249 double
250 VCA::VCASoloControllable::get_value() const
251 {
252         boost::shared_ptr<VCA> vca = _vca.lock();
253         if (!vca) {
254                 return 0.0;
255         }
256
257         return vca->soloed() ? 1.0 : 0.0;
258 }
259
260 /*----*/
261
262 VCA::VCAMuteControllable::VCAMuteControllable (string const & name, boost::shared_ptr<VCA> vca)
263         : AutomationControl (vca->session(), Evoral::Parameter (MuteAutomation), ParameterDescriptor (Evoral::Parameter (MuteAutomation)),
264                              boost::shared_ptr<AutomationList>(), name)
265         , _vca (vca)
266 {
267 }
268
269 void
270 VCA::VCAMuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
271 {
272         if (writable()) {
273                 _set_value (val, gcd);
274         }
275 }
276
277 void
278 VCA::VCAMuteControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
279 {
280         boost::shared_ptr<VCA> vca = _vca.lock();
281
282         if (!vca) {
283                 return;
284         }
285
286         vca->set_mute (val >= 0.5);
287
288         AutomationControl::set_value (val, gcd);
289 }
290
291 void
292 VCA::VCAMuteControllable::set_value_unchecked (double val)
293 {
294         /* used only by automation playback */
295         _set_value (val, Controllable::NoGroup);
296 }
297
298 double
299 VCA::VCAMuteControllable::get_value() const
300 {
301         boost::shared_ptr<VCA> vca = _vca.lock();
302         if (!vca) {
303                 return 0.0;
304         }
305
306         return vca->muted() ? 1.0 : 0.0;
307 }