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