Fix another thinko in 9581cb26 + 02b087c5 (VCA gain automation)
[ardour.git] / libs / ardour / slavable_automation_control.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 #ifndef __libardour_slavable_automation_control_h__
20 #define __libardour_slavable_automation_control_h__
21
22 #include "pbd/enumwriter.h"
23 #include "pbd/error.h"
24 #include "pbd/types_convert.h"
25 #include "pbd/i18n.h"
26
27 #include "evoral/Curve.hpp"
28
29 #include "ardour/audioengine.h"
30 #include "ardour/runtime_functions.h"
31 #include "ardour/slavable_automation_control.h"
32 #include "ardour/session.h"
33
34 using namespace std;
35 using namespace ARDOUR;
36 using namespace PBD;
37
38 SlavableAutomationControl::SlavableAutomationControl(ARDOUR::Session& s,
39                                                      const Evoral::Parameter&                  parameter,
40                                                      const ParameterDescriptor&                desc,
41                                                      boost::shared_ptr<ARDOUR::AutomationList> l,
42                                                      const std::string&                        name,
43                                                      Controllable::Flag                        flags)
44         : AutomationControl (s, parameter, desc, l, name, flags)
45         , _masters_node (0)
46 {
47 }
48
49 SlavableAutomationControl::~SlavableAutomationControl ()
50 {
51         if (_masters_node) {
52                 delete _masters_node;
53                 _masters_node = 0;
54         }
55 }
56
57 double
58 SlavableAutomationControl::get_masters_value_locked () const
59 {
60         if (_desc.toggled) {
61                 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
62                         if (mr->second.master()->get_value()) {
63                                 return _desc.upper;
64                         }
65                 }
66                 return _desc.lower;
67         } else {
68
69                 double v = 1.0; /* the masters function as a scaling factor */
70
71                 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
72                         v *= mr->second.master_ratio ();
73                 }
74
75                 return v;
76         }
77 }
78
79 double
80 SlavableAutomationControl::get_value_locked() const
81 {
82         /* read or write masters lock must be held */
83
84         if (_masters.empty()) {
85                 return Control::get_double (false, _session.transport_frame());
86         }
87
88         if (_desc.toggled) {
89                 /* for boolean/toggle controls, if this slave OR any master is
90                  * enabled, this slave is enabled. So check our own value
91                  * first, because if we are enabled, we can return immediately.
92                  */
93                 if (Control::get_double (false, _session.transport_frame())) {
94                         return _desc.upper;
95                 }
96         }
97
98         return Control::get_double() * get_masters_value_locked ();
99 }
100
101 /** Get the current effective `user' value based on automation state */
102 double
103 SlavableAutomationControl::get_value() const
104 {
105         bool from_list = _list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback();
106
107         Glib::Threads::RWLock::ReaderLock lm (master_lock);
108         if (!from_list) {
109                 return get_value_locked ();
110         } else {
111                 return Control::get_double (true, _session.transport_frame()) * get_masters_value_locked();
112         }
113 }
114
115 bool
116 SlavableAutomationControl::get_masters_curve_locked (framepos_t, framepos_t, float*, framecnt_t) const
117 {
118         /* Every AutomationControl needs to implement this as-needed.
119          *
120          * This class also provides some convenient methods which
121          * could be used as defaults here (depending on  AutomationType)
122          * e.g. masters_curve_multiply()
123          */
124         return false;
125 }
126
127 bool
128 SlavableAutomationControl::masters_curve_multiply (framepos_t start, framepos_t end, float* vec, framecnt_t veclen) const
129 {
130         gain_t* scratch = _session.scratch_automation_buffer ();
131         bool from_list = _list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback();
132         bool rv = from_list && list()->curve().rt_safe_get_vector (start, end, scratch, veclen);
133         if (rv) {
134                 for (framecnt_t i = 0; i < veclen; ++i) {
135                         vec[i] *= scratch[i];
136                 }
137         } else {
138                 apply_gain_to_buffer (vec, veclen, Control::get_double ());
139         }
140         if (_masters.empty()) {
141                 return rv;
142         }
143
144         for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
145                 boost::shared_ptr<SlavableAutomationControl> sc
146                         = boost::dynamic_pointer_cast<SlavableAutomationControl>(mr->second.master());
147                 assert (sc);
148                 rv |= sc->masters_curve_multiply (start, end, vec, veclen);
149                 if (mr->second.val_master () != 0) {
150                         apply_gain_to_buffer (vec, veclen, 1.f / mr->second.val_master ());
151                 }
152         }
153         return rv;
154 }
155
156 void
157 SlavableAutomationControl::actually_set_value (double value, PBD::Controllable::GroupControlDisposition gcd)
158 {
159         if (!_desc.toggled) {
160
161                 Glib::Threads::RWLock::WriterLock lm (master_lock);
162
163                 if (!_masters.empty()) {
164                         /* need to scale given value by current master's scaling */
165                         const double masters_value = get_masters_value_locked();
166                         if (masters_value == 0.0) {
167                                 value = 0.0;
168                         } else {
169                                 value /= masters_value;
170                                 value = std::max (lower(), std::min(upper(), value));
171                         }
172                 }
173         }
174
175         /* this will call Control::set_double() and emit Changed signals as appropriate */
176         AutomationControl::actually_set_value (value, gcd);
177 }
178
179 void
180 SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m, bool loading)
181 {
182         std::pair<Masters::iterator,bool> res;
183
184         {
185                 const double master_value = m->get_value();
186                 Glib::Threads::RWLock::WriterLock lm (master_lock);
187
188                 pair<PBD::ID,MasterRecord> newpair (m->id(), MasterRecord (boost::weak_ptr<AutomationControl> (m), get_value_locked(), master_value));
189                 res = _masters.insert (newpair);
190
191                 if (res.second) {
192
193                         /* note that we bind @param m as a weak_ptr<AutomationControl>, thus
194                            avoiding holding a reference to the control in the binding
195                            itself.
196                         */
197                         m->DropReferences.connect_same_thread (res.first->second.dropped_connection, boost::bind (&SlavableAutomationControl::master_going_away, this, boost::weak_ptr<AutomationControl>(m)));
198
199                         /* Store the connection inside the MasterRecord, so
200                            that when we destroy it, the connection is destroyed
201                            and we no longer hear about changes to the
202                            AutomationControl.
203
204                            Note that this also makes it safe to store a
205                            boost::shared_ptr<AutomationControl> in the functor,
206                            since we know we will destroy the functor when the
207                            connection is destroyed, which happens when we
208                            disconnect from the master (for any reason).
209
210                            Note that we fix the "from_self" argument that will
211                            be given to our own Changed signal to "false",
212                            because the change came from the master.
213                         */
214
215                         m->Changed.connect_same_thread (res.first->second.changed_connection, boost::bind (&SlavableAutomationControl::master_changed, this, _1, _2, boost::weak_ptr<AutomationControl>(m)));
216                 }
217         }
218
219         if (res.second) {
220                 /* this will notify everyone that we're now slaved to the master */
221                 MasterStatusChange (); /* EMIT SIGNAL */
222         }
223
224         post_add_master (m);
225
226         update_boolean_masters_records (m);
227 }
228
229 int32_t
230 SlavableAutomationControl::get_boolean_masters () const
231 {
232         int32_t n = 0;
233
234         if (_desc.toggled) {
235                 Glib::Threads::RWLock::ReaderLock lm (master_lock);
236                 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
237                         if (mr->second.yn()) {
238                                 ++n;
239                         }
240                 }
241         }
242
243         return n;
244 }
245
246 void
247 SlavableAutomationControl::update_boolean_masters_records (boost::shared_ptr<AutomationControl> m)
248 {
249         if (_desc.toggled) {
250                 /* We may modify a MasterRecord, but we not modify the master
251                  * map, so we use a ReaderLock
252                  */
253                 Glib::Threads::RWLock::ReaderLock lm (master_lock);
254                 Masters::iterator mi = _masters.find (m->id());
255                 if (mi != _masters.end()) {
256                         /* update MasterRecord to show whether the master is
257                            on/off. We need to store this because the master
258                            may change (in the sense of emitting Changed())
259                            several times without actually changing the result
260                            of ::get_value(). This is a feature of
261                            AutomationControls (or even just Controllables,
262                            really) which have more than a simple scalar
263                            value. For example, the master may be a mute control
264                            which can be muted_by_self() and/or
265                            muted_by_masters(). When either of those two
266                            conditions changes, Changed() will be emitted, even
267                            though ::get_value() will return the same value each
268                            time (1.0 if either are true, 0.0 if neither is).
269
270                            This provides a way for derived types to check
271                            the last known state of a Master when the Master
272                            changes. We update it after calling
273                            ::master_changed() (though derived types must do
274                            this themselves).
275                         */
276                         mi->second.set_yn (m->get_value());
277                 }
278         }
279 }
280
281 void
282 SlavableAutomationControl::master_changed (bool /*from_self*/, GroupControlDisposition gcd, boost::weak_ptr<AutomationControl> wm)
283 {
284         boost::shared_ptr<AutomationControl> m = wm.lock ();
285         assert (m);
286         Glib::Threads::RWLock::ReaderLock lm (master_lock, Glib::Threads::TRY_LOCK);
287         if (!lm.locked ()) {
288                 /* boolean_automation_run_locked () special case */
289                 return;
290         }
291         bool send_signal = handle_master_change (m);
292         lm.release (); // update_boolean_masters_records() takes lock
293
294         update_boolean_masters_records (m);
295         if (send_signal) {
296                 Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
297         }
298 }
299
300 void
301 SlavableAutomationControl::master_going_away (boost::weak_ptr<AutomationControl> wm)
302 {
303         boost::shared_ptr<AutomationControl> m = wm.lock();
304         if (m) {
305                 remove_master (m);
306         }
307 }
308
309 void
310 SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
311 {
312         if (_session.deletion_in_progress()) {
313                 /* no reason to care about new values or sending signals */
314                 return;
315         }
316
317         pre_remove_master (m);
318         double new_val = AutomationControl::get_double();
319         const double old_val = new_val;
320
321         {
322                 Glib::Threads::RWLock::WriterLock lm (master_lock);
323
324                 Masters::const_iterator mi = _masters.find (m->id ());
325
326                 /* when un-assigning we apply the master-value permanently */
327                 if (mi != _masters.end()) {
328                         new_val *= mi->second.master_ratio ();
329                 }
330
331                 if (!_masters.erase (m->id())) {
332                         return;
333                 }
334         }
335
336         if (old_val != new_val) {
337                 AutomationControl::set_double (new_val, Controllable::NoGroup);
338         }
339
340         MasterStatusChange (); /* EMIT SIGNAL */
341
342         /* no need to update boolean masters records, since the MR will have
343          * been removed already.
344          */
345 }
346
347 void
348 SlavableAutomationControl::clear_masters ()
349 {
350         if (_session.deletion_in_progress()) {
351                 /* no reason to care about new values or sending signals */
352                 return;
353         }
354
355         double new_val = AutomationControl::get_double();
356         const double old_val = new_val;
357
358         /* null ptr means "all masters */
359         pre_remove_master (boost::shared_ptr<AutomationControl>());
360
361         {
362                 Glib::Threads::RWLock::WriterLock lm (master_lock);
363                 if (_masters.empty()) {
364                         return;
365                 }
366                 /* permanently apply masters value */
367                 new_val *= get_masters_value_locked ();
368
369                 _masters.clear ();
370         }
371
372         if (old_val != new_val) {
373                 AutomationControl::set_double (new_val, Controllable::NoGroup);
374         }
375         MasterStatusChange (); /* EMIT SIGNAL */
376
377         /* no need to update boolean masters records, since all MRs will have
378          * been removed already.
379          */
380 }
381
382 bool
383 SlavableAutomationControl::find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const
384 {
385         if (_masters.empty()) {
386                 return false;
387         }
388         bool rv = false;
389         /* iterate over all masters check their automation lists
390          * for any event between "now" and "end" which is earlier than
391          * next_event.when. If found, set next_event.when and return true.
392          * (see also Automatable::find_next_event)
393          */
394         for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
395                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
396
397                 boost::shared_ptr<SlavableAutomationControl> sc
398                         = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
399
400                 if (sc && sc->find_next_event_locked (now, end, next_event)) {
401                         rv = true;
402                 }
403
404                 Evoral::ControlList::const_iterator i;
405                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
406                 Evoral::ControlEvent cp (now, 0.0f);
407                 if (!alist) {
408                         continue;
409                 }
410
411                 for (i = lower_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator);
412                      i != alist->end() && (*i)->when < end; ++i) {
413                         if ((*i)->when > now) {
414                                 break;
415                         }
416                 }
417
418                 if (i != alist->end() && (*i)->when < end) {
419                         if ((*i)->when < next_event.when) {
420                                 next_event.when = (*i)->when;
421                                 rv = true;
422                         }
423                 }
424         }
425
426         return rv;
427 }
428
429 bool
430 SlavableAutomationControl::handle_master_change (boost::shared_ptr<AutomationControl>)
431 {
432         /* Derived classes can implement this for special cases (e.g. mute).
433          * This method is called with a ReaderLock (master_lock) held.
434          *
435          * return true if the changed master value resulted
436          * in a change of the control itself. */
437         return true; // emit Changed
438 }
439
440 bool
441 SlavableAutomationControl::boolean_automation_run_locked (framepos_t start, pframes_t len)
442 {
443         bool rv = false;
444         if (!_desc.toggled) {
445                 return false;
446         }
447         for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
448                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
449                 if (!ac->automation_playback ()) {
450                         continue;
451                 }
452                 if (!ac->toggled ()) {
453                         continue;
454                 }
455                 boost::shared_ptr<SlavableAutomationControl> sc = boost::dynamic_pointer_cast<MuteControl>(ac);
456                 if (sc) {
457                         rv |= sc->boolean_automation_run (start, len);
458                 }
459                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
460                 bool valid = false;
461                 const bool yn = alist->rt_safe_eval (start, valid) >= 0.5;
462                 if (!valid) {
463                         continue;
464                 }
465                 /* ideally we'd call just master_changed() which calls update_boolean_masters_records()
466                  * but that takes the master_lock, which is already locked */
467                 if (mr->second.yn() != yn) {
468                         rv |= handle_master_change (ac);
469                         mr->second.set_yn (yn);
470                         /* notify the GUI, without recursion:
471                          * master_changed() above will ignore the change if the lock is held.
472                          */
473                         ac->set_value_unchecked (yn ? 1. : 0.);
474                         ac->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
475                 }
476         }
477         return rv;
478 }
479
480 bool
481 SlavableAutomationControl::boolean_automation_run (framepos_t start, pframes_t len)
482 {
483         bool change = false;
484         {
485                  Glib::Threads::RWLock::ReaderLock lm (master_lock);
486                  change = boolean_automation_run_locked (start, len);
487         }
488         if (change) {
489                 Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
490         }
491         return change;
492 }
493
494 bool
495 SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
496 {
497         Glib::Threads::RWLock::ReaderLock lm (master_lock);
498         return _masters.find (m->id()) != _masters.end();
499 }
500
501 bool
502 SlavableAutomationControl::slaved () const
503 {
504         Glib::Threads::RWLock::ReaderLock lm (master_lock);
505         return !_masters.empty();
506 }
507
508 int
509 SlavableAutomationControl::MasterRecord::set_state (XMLNode const& n, int)
510 {
511         n.get_property (X_("yn"), _yn);
512         n.get_property (X_("val-ctrl"), _val_ctrl);
513         n.get_property (X_("val-master"), _val_master);
514         return 0;
515 }
516
517 void
518 SlavableAutomationControl::use_saved_master_ratios ()
519 {
520         if (!_masters_node) {
521                 return;
522         }
523
524         Glib::Threads::RWLock::ReaderLock lm (master_lock);
525
526         XMLNodeList nlist = _masters_node->children();
527         XMLNodeIterator niter;
528
529         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
530                 ID id_val;
531                 if (!(*niter)->get_property (X_("id"), id_val)) {
532                         continue;
533                 }
534                 Masters::iterator mi = _masters.find (id_val);
535                 if (mi == _masters.end()) {
536                         continue;
537                 }
538                 mi->second.set_state (**niter, Stateful::loading_state_version);
539         }
540
541         delete _masters_node;
542         _masters_node = 0;
543
544         return;
545 }
546
547
548 XMLNode&
549 SlavableAutomationControl::get_state ()
550 {
551         XMLNode& node (AutomationControl::get_state());
552
553         /* store VCA master ratios */
554
555         {
556                 Glib::Threads::RWLock::ReaderLock lm (master_lock);
557                 if (!_masters.empty()) {
558                         XMLNode* masters_node = new XMLNode (X_("masters"));
559                         for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
560                                 XMLNode* mnode = new XMLNode (X_("master"));
561                                 mnode->set_property (X_("id"), mr->second.master()->id());
562
563                                 if (_desc.toggled) {
564                                         mnode->set_property (X_("yn"), mr->second.yn());
565                                 } else {
566                                         mnode->set_property (X_("val-ctrl"), mr->second.val_ctrl());
567                                         mnode->set_property (X_("val-master"), mr->second.val_master());
568                                 }
569                                 masters_node->add_child_nocopy (*mnode);
570                         }
571                         node.add_child_nocopy (*masters_node);
572                 }
573         }
574
575         return node;
576 }
577
578 int
579 SlavableAutomationControl::set_state (XMLNode const& node, int version)
580 {
581         XMLNodeList nlist = node.children();
582         XMLNodeIterator niter;
583
584         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
585                 if ((*niter)->name() == X_("masters")) {
586                         _masters_node = new XMLNode (**niter);
587                 }
588         }
589
590         return AutomationControl::set_state (node, version);
591 }
592
593
594 #endif /* __libardour_slavable_automation_control_h__ */