remove debug output
[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         if (toggled ()) {
317                 // XXX we should use the master's upper/lower as threshold
318                 if (ratio >= 0.5 * (upper () - lower ())) {
319                         value = upper ();
320                 }
321         } else {
322                 value *= ratio;
323         }
324         value = std::max (lower(), std::min(upper(), value));
325         return value;
326 }
327
328 void
329 SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
330 {
331         if (_session.deletion_in_progress()) {
332                 /* no reason to care about new values or sending signals */
333                 return;
334         }
335
336         pre_remove_master (m);
337
338         const double old_val = AutomationControl::get_double();
339
340         bool update_value = false;
341         double master_ratio = 0;
342         double list_ratio = toggled () ? 0 : 1;
343
344         boost::shared_ptr<AutomationControl> master;
345
346         {
347                 Glib::Threads::RWLock::WriterLock lm (master_lock);
348
349                 Masters::const_iterator mi = _masters.find (m->id ());
350
351                 if (mi != _masters.end()) {
352                         master_ratio = mi->second.master_ratio ();
353                         update_value = true;
354                         master = mi->second.master();
355                         list_ratio *= mi->second.val_master_inv ();
356                 }
357
358                 if (!_masters.erase (m->id())) {
359                         return;
360                 }
361         }
362
363         if (update_value) {
364                 /* when un-assigning we apply the master-value permanently */
365                 double new_val = old_val * master_ratio;
366
367                 if (old_val != new_val) {
368                         AutomationControl::set_double (new_val, Controllable::NoGroup);
369                 }
370
371                 /* ..and update automation */
372                 if (_list) {
373                         XMLNode* before = &alist ()->get_state ();
374                         if (master->automation_playback () && master->list()) {
375                                 _list->list_merge (*master->list().get(), boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, _2));
376                                 printf ("y-t %s  %f\n", name().c_str(), list_ratio);
377                                 _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, list_ratio));
378                         } else {
379                                 // do we need to freeze/thaw the list? probably no: iterators & positions don't change
380                                 _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
381                         }
382                         XMLNode* after = &alist ()->get_state ();
383                         if (*before != *after) {
384                                 _session.begin_reversible_command (string_compose (_("Merge VCA automation into %1"), name ()));
385                                 _session.commit_reversible_command (alist()->memento_command (before, after));
386                         }
387                 }
388         }
389
390         MasterStatusChange (); /* EMIT SIGNAL */
391
392         /* no need to update boolean masters records, since the MR will have
393          * been removed already.
394          */
395 }
396
397 void
398 SlavableAutomationControl::clear_masters ()
399 {
400         if (_session.deletion_in_progress()) {
401                 /* no reason to care about new values or sending signals */
402                 return;
403         }
404
405         const double old_val = AutomationControl::get_double();
406
407         ControlList masters;
408         bool update_value = false;
409         double master_ratio = 0;
410         double list_ratio = toggled () ? 0 : 1;
411
412         /* null ptr means "all masters */
413         pre_remove_master (boost::shared_ptr<AutomationControl>());
414
415         {
416                 Glib::Threads::RWLock::WriterLock lm (master_lock);
417                 if (_masters.empty()) {
418                         return;
419                 }
420
421                 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
422                         boost::shared_ptr<AutomationControl> master = mr->second.master();
423                         if (master->automation_playback () && master->list()) {
424                                 masters.push_back (mr->second.master());
425                                 list_ratio *= mr->second.val_master_inv ();
426                         } else {
427                                 list_ratio *= mr->second.master_ratio ();
428                         }
429                 }
430
431                 master_ratio = get_masters_value_locked ();
432                 update_value = true;
433                 _masters.clear ();
434         }
435
436         if (update_value) {
437                 /* permanently apply masters value */
438                         double new_val = old_val * master_ratio;
439
440                         if (old_val != new_val) {
441                                 AutomationControl::set_double (new_val, Controllable::NoGroup);
442                         }
443
444                         /* ..and update automation */
445                         if (_list) {
446                                 XMLNode* before = &alist ()->get_state ();
447                                 if (!masters.empty()) {
448                                         for (ControlList::const_iterator m = masters.begin(); m != masters.end(); ++m) {
449                                                 _list->list_merge (*(*m)->list().get(), boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, _2));
450                                         }
451                                         _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, list_ratio));
452                                 } else {
453                                         _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
454                                 }
455                                 XMLNode* after = &alist ()->get_state ();
456                                 if (*before != *after) {
457                                         _session.begin_reversible_command (string_compose (_("Merge VCA automation into %1"), name ()));
458                                         _session.commit_reversible_command (alist()->memento_command (before, after));
459                                 }
460                         }
461         }
462
463         MasterStatusChange (); /* EMIT SIGNAL */
464
465         /* no need to update boolean masters records, since all MRs will have
466          * been removed already.
467          */
468 }
469
470 bool
471 SlavableAutomationControl::find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const
472 {
473         if (_masters.empty()) {
474                 return false;
475         }
476         bool rv = false;
477         /* iterate over all masters check their automation lists
478          * for any event between "now" and "end" which is earlier than
479          * next_event.when. If found, set next_event.when and return true.
480          * (see also Automatable::find_next_event)
481          */
482         for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
483                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
484
485                 boost::shared_ptr<SlavableAutomationControl> sc
486                         = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
487
488                 if (sc && sc->find_next_event_locked (now, end, next_event)) {
489                         rv = true;
490                 }
491
492                 Evoral::ControlList::const_iterator i;
493                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
494                 Evoral::ControlEvent cp (now, 0.0f);
495                 if (!alist) {
496                         continue;
497                 }
498
499                 for (i = lower_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator);
500                      i != alist->end() && (*i)->when < end; ++i) {
501                         if ((*i)->when > now) {
502                                 break;
503                         }
504                 }
505
506                 if (i != alist->end() && (*i)->when < end) {
507                         if ((*i)->when < next_event.when) {
508                                 next_event.when = (*i)->when;
509                                 rv = true;
510                         }
511                 }
512         }
513
514         return rv;
515 }
516
517 bool
518 SlavableAutomationControl::handle_master_change (boost::shared_ptr<AutomationControl>)
519 {
520         /* Derived classes can implement this for special cases (e.g. mute).
521          * This method is called with a ReaderLock (master_lock) held.
522          *
523          * return true if the changed master value resulted
524          * in a change of the control itself. */
525         return true; // emit Changed
526 }
527
528 void
529 SlavableAutomationControl::automation_run (framepos_t start, pframes_t nframes)
530 {
531         if (!automation_playback ()) {
532                 return;
533         }
534
535         assert (_list);
536         bool valid = false;
537         double val = _list->rt_safe_eval (start, valid);
538         if (!valid) {
539                 return;
540         }
541         if (toggled ()) {
542                 const double thresh = .5 * (_desc.upper - _desc.lower);
543                 bool on = (val >= thresh) || (get_masters_value () >= thresh);
544                 set_value_unchecked (on ? _desc.upper : _desc.lower);
545         } else {
546                 set_value_unchecked (val * get_masters_value ());
547         }
548 }
549
550 bool
551 SlavableAutomationControl::boolean_automation_run_locked (framepos_t start, pframes_t len)
552 {
553         bool rv = false;
554         if (!_desc.toggled) {
555                 return false;
556         }
557         for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
558                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
559                 if (!ac->automation_playback ()) {
560                         continue;
561                 }
562                 if (!ac->toggled ()) {
563                         continue;
564                 }
565                 boost::shared_ptr<SlavableAutomationControl> sc = boost::dynamic_pointer_cast<MuteControl>(ac);
566                 if (sc) {
567                         rv |= sc->boolean_automation_run (start, len);
568                 }
569                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
570                 bool valid = false;
571                 const bool yn = alist->rt_safe_eval (start, valid) >= 0.5;
572                 if (!valid) {
573                         continue;
574                 }
575                 /* ideally we'd call just master_changed() which calls update_boolean_masters_records()
576                  * but that takes the master_lock, which is already locked */
577                 if (mr->second.yn() != yn) {
578                         rv |= handle_master_change (ac);
579                         mr->second.set_yn (yn);
580                 }
581         }
582         return rv;
583 }
584
585 bool
586 SlavableAutomationControl::boolean_automation_run (framepos_t start, pframes_t len)
587 {
588         bool change = false;
589         {
590                  Glib::Threads::RWLock::ReaderLock lm (master_lock);
591                  change = boolean_automation_run_locked (start, len);
592         }
593         if (change) {
594                 Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
595         }
596         return change;
597 }
598
599 bool
600 SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
601 {
602         Glib::Threads::RWLock::ReaderLock lm (master_lock);
603         return _masters.find (m->id()) != _masters.end();
604 }
605
606 bool
607 SlavableAutomationControl::slaved () const
608 {
609         Glib::Threads::RWLock::ReaderLock lm (master_lock);
610         return !_masters.empty();
611 }
612
613 int
614 SlavableAutomationControl::MasterRecord::set_state (XMLNode const& n, int)
615 {
616         n.get_property (X_("yn"), _yn);
617         n.get_property (X_("val-ctrl"), _val_ctrl);
618         n.get_property (X_("val-master"), _val_master);
619         return 0;
620 }
621
622 void
623 SlavableAutomationControl::use_saved_master_ratios ()
624 {
625         if (!_masters_node) {
626                 return;
627         }
628
629         Glib::Threads::RWLock::ReaderLock lm (master_lock);
630
631         XMLNodeList nlist = _masters_node->children();
632         XMLNodeIterator niter;
633
634         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
635                 ID id_val;
636                 if (!(*niter)->get_property (X_("id"), id_val)) {
637                         continue;
638                 }
639                 Masters::iterator mi = _masters.find (id_val);
640                 if (mi == _masters.end()) {
641                         continue;
642                 }
643                 mi->second.set_state (**niter, Stateful::loading_state_version);
644         }
645
646         delete _masters_node;
647         _masters_node = 0;
648
649         return;
650 }
651
652
653 XMLNode&
654 SlavableAutomationControl::get_state ()
655 {
656         XMLNode& node (AutomationControl::get_state());
657
658         /* store VCA master ratios */
659
660         {
661                 Glib::Threads::RWLock::ReaderLock lm (master_lock);
662                 if (!_masters.empty()) {
663                         XMLNode* masters_node = new XMLNode (X_("masters"));
664                         for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
665                                 XMLNode* mnode = new XMLNode (X_("master"));
666                                 mnode->set_property (X_("id"), mr->second.master()->id());
667
668                                 if (_desc.toggled) {
669                                         mnode->set_property (X_("yn"), mr->second.yn());
670                                 } else {
671                                         mnode->set_property (X_("val-ctrl"), mr->second.val_ctrl());
672                                         mnode->set_property (X_("val-master"), mr->second.val_master());
673                                 }
674                                 masters_node->add_child_nocopy (*mnode);
675                         }
676                         node.add_child_nocopy (*masters_node);
677                 }
678         }
679
680         return node;
681 }
682
683 int
684 SlavableAutomationControl::set_state (XMLNode const& node, int version)
685 {
686         XMLNodeList nlist = node.children();
687         XMLNodeIterator niter;
688
689         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
690                 if ((*niter)->name() == X_("masters")) {
691                         _masters_node = new XMLNode (**niter);
692                 }
693         }
694
695         return AutomationControl::set_state (node, version);
696 }
697
698
699 #endif /* __libardour_slavable_automation_control_h__ */