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