Merge event control lists when disconnecting a master-ctrl
[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                 if (!_masters.empty() && automation_write ()) {
110                         /* writing automation takes the fader value as-is, factor out the master */
111                         return Control::user_double ();
112                 }
113                 return get_value_locked ();
114         } else {
115                 return Control::get_double (true, _session.transport_frame()) * get_masters_value_locked();
116         }
117 }
118
119 bool
120 SlavableAutomationControl::get_masters_curve_locked (framepos_t, framepos_t, float*, framecnt_t) const
121 {
122         /* Every AutomationControl needs to implement this as-needed.
123          *
124          * This class also provides some convenient methods which
125          * could be used as defaults here (depending on  AutomationType)
126          * e.g. masters_curve_multiply()
127          */
128         return false;
129 }
130
131 bool
132 SlavableAutomationControl::masters_curve_multiply (framepos_t start, framepos_t end, float* vec, framecnt_t veclen) const
133 {
134         gain_t* scratch = _session.scratch_automation_buffer ();
135         bool from_list = _list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback();
136         bool rv = from_list && list()->curve().rt_safe_get_vector (start, end, scratch, veclen);
137         if (rv) {
138                 for (framecnt_t i = 0; i < veclen; ++i) {
139                         vec[i] *= scratch[i];
140                 }
141         } else {
142                 apply_gain_to_buffer (vec, veclen, Control::get_double ());
143         }
144         if (_masters.empty()) {
145                 return rv;
146         }
147
148         for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
149                 boost::shared_ptr<SlavableAutomationControl> sc
150                         = boost::dynamic_pointer_cast<SlavableAutomationControl>(mr->second.master());
151                 assert (sc);
152                 rv |= sc->masters_curve_multiply (start, end, vec, veclen);
153                 if (mr->second.val_master () != 0) {
154                         apply_gain_to_buffer (vec, veclen, 1.f / mr->second.val_master ());
155                 }
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; // XXX 1.0, see master_ratio(), val_master_inv()
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, bool loading)
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, Glib::Threads::TRY_LOCK);
295         if (!lm.locked ()) {
296                 /* boolean_automation_run_locked () special case */
297                 return;
298         }
299         bool send_signal = handle_master_change (m);
300         lm.release (); // update_boolean_masters_records() takes lock
301
302         update_boolean_masters_records (m);
303         if (send_signal) {
304                 Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
305         }
306 }
307
308 void
309 SlavableAutomationControl::master_going_away (boost::weak_ptr<AutomationControl> wm)
310 {
311         boost::shared_ptr<AutomationControl> m = wm.lock();
312         if (m) {
313                 remove_master (m);
314         }
315 }
316
317 double
318 SlavableAutomationControl::scale_automation_callback (double value, double ratio) const
319 {
320         /* derived classes can override this and e.g. add/subtract. */
321         value *= ratio;
322         value = std::max (lower(), std::min(upper(), value));
323         return value;
324 }
325
326 void
327 SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
328 {
329         if (_session.deletion_in_progress()) {
330                 /* no reason to care about new values or sending signals */
331                 return;
332         }
333
334         pre_remove_master (m);
335
336         const double old_val = AutomationControl::get_double();
337
338         bool update_value = false;
339         double master_ratio = 0;
340         double list_ratio = 1;
341
342         boost::shared_ptr<AutomationControl> master;
343
344         {
345                 Glib::Threads::RWLock::WriterLock lm (master_lock);
346
347                 Masters::const_iterator mi = _masters.find (m->id ());
348
349                 if (mi != _masters.end()) {
350                         master_ratio = mi->second.master_ratio ();
351                         update_value = true;
352                         master = mi->second.master();
353                         list_ratio *= mi->second.val_master_inv ();
354                 }
355
356                 if (!_masters.erase (m->id())) {
357                         return;
358                 }
359         }
360
361         if (update_value) {
362                 /* when un-assigning we apply the master-value permanently */
363                 double new_val = old_val * master_ratio;
364
365                 if (old_val != new_val) {
366                         AutomationControl::set_double (new_val, Controllable::NoGroup);
367                 }
368
369                 /* ..and update automation */
370                 if (_list) {
371                         if (master->automation_playback () && master->list()) {
372                                 _list->list_merge (*master->list().get(), boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, _2));
373                                 _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, list_ratio));
374                         } else {
375                                 // do we need to freeze/thaw the list? probably no: iterators & positions don't change
376                                 _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
377                         }
378                 }
379         }
380
381         MasterStatusChange (); /* EMIT SIGNAL */
382
383         /* no need to update boolean masters records, since the MR will have
384          * been removed already.
385          */
386 }
387
388 void
389 SlavableAutomationControl::clear_masters ()
390 {
391         if (_session.deletion_in_progress()) {
392                 /* no reason to care about new values or sending signals */
393                 return;
394         }
395
396         const double old_val = AutomationControl::get_double();
397
398         ControlList masters;
399         bool update_value = false;
400         double master_ratio = 0;
401         double list_ratio = 1;
402
403         /* null ptr means "all masters */
404         pre_remove_master (boost::shared_ptr<AutomationControl>());
405
406         {
407                 Glib::Threads::RWLock::WriterLock lm (master_lock);
408                 if (_masters.empty()) {
409                         return;
410                 }
411
412                 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
413                         boost::shared_ptr<AutomationControl> master = mr->second.master();
414                         if (master->automation_playback () && master->list()) {
415                                 masters.push_back (mr->second.master());
416                                 list_ratio *= mr->second.val_master_inv ();
417                         } else {
418                                 list_ratio *= mr->second.master_ratio ();
419                         }
420                 }
421
422                 master_ratio = get_masters_value_locked ();
423                 update_value = true;
424                 _masters.clear ();
425         }
426
427         if (update_value) {
428                 /* permanently apply masters value */
429                         double new_val = old_val * master_ratio;
430
431                         if (old_val != new_val) {
432                                 AutomationControl::set_double (new_val, Controllable::NoGroup);
433                         }
434
435                         /* ..and update automation */
436                         if (_list) {
437                                 if (!masters.empty()) {
438                                         for (ControlList::const_iterator m = masters.begin(); m != masters.end(); ++m) {
439                                                 _list->list_merge (*(*m)->list().get(), boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, _2));
440                                         }
441                                         _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, list_ratio));
442                                 } else {
443                                         _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
444                                 }
445                         }
446         }
447
448         MasterStatusChange (); /* EMIT SIGNAL */
449
450         /* no need to update boolean masters records, since all MRs will have
451          * been removed already.
452          */
453 }
454
455 bool
456 SlavableAutomationControl::find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const
457 {
458         if (_masters.empty()) {
459                 return false;
460         }
461         bool rv = false;
462         /* iterate over all masters check their automation lists
463          * for any event between "now" and "end" which is earlier than
464          * next_event.when. If found, set next_event.when and return true.
465          * (see also Automatable::find_next_event)
466          */
467         for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
468                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
469
470                 boost::shared_ptr<SlavableAutomationControl> sc
471                         = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
472
473                 if (sc && sc->find_next_event_locked (now, end, next_event)) {
474                         rv = true;
475                 }
476
477                 Evoral::ControlList::const_iterator i;
478                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
479                 Evoral::ControlEvent cp (now, 0.0f);
480                 if (!alist) {
481                         continue;
482                 }
483
484                 for (i = lower_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator);
485                      i != alist->end() && (*i)->when < end; ++i) {
486                         if ((*i)->when > now) {
487                                 break;
488                         }
489                 }
490
491                 if (i != alist->end() && (*i)->when < end) {
492                         if ((*i)->when < next_event.when) {
493                                 next_event.when = (*i)->when;
494                                 rv = true;
495                         }
496                 }
497         }
498
499         return rv;
500 }
501
502 bool
503 SlavableAutomationControl::handle_master_change (boost::shared_ptr<AutomationControl>)
504 {
505         /* Derived classes can implement this for special cases (e.g. mute).
506          * This method is called with a ReaderLock (master_lock) held.
507          *
508          * return true if the changed master value resulted
509          * in a change of the control itself. */
510         return true; // emit Changed
511 }
512
513 bool
514 SlavableAutomationControl::boolean_automation_run_locked (framepos_t start, pframes_t len)
515 {
516         bool rv = false;
517         if (!_desc.toggled) {
518                 return false;
519         }
520         for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
521                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
522                 if (!ac->automation_playback ()) {
523                         continue;
524                 }
525                 if (!ac->toggled ()) {
526                         continue;
527                 }
528                 boost::shared_ptr<SlavableAutomationControl> sc = boost::dynamic_pointer_cast<MuteControl>(ac);
529                 if (sc) {
530                         rv |= sc->boolean_automation_run (start, len);
531                 }
532                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
533                 bool valid = false;
534                 const bool yn = alist->rt_safe_eval (start, valid) >= 0.5;
535                 if (!valid) {
536                         continue;
537                 }
538                 /* ideally we'd call just master_changed() which calls update_boolean_masters_records()
539                  * but that takes the master_lock, which is already locked */
540                 if (mr->second.yn() != yn) {
541                         rv |= handle_master_change (ac);
542                         mr->second.set_yn (yn);
543                         /* notify the GUI, without recursion:
544                          * master_changed() above will ignore the change if the lock is held.
545                          */
546                         ac->set_value_unchecked (yn ? 1. : 0.);
547                         ac->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
548                 }
549         }
550         return rv;
551 }
552
553 bool
554 SlavableAutomationControl::boolean_automation_run (framepos_t start, pframes_t len)
555 {
556         bool change = false;
557         {
558                  Glib::Threads::RWLock::ReaderLock lm (master_lock);
559                  change = boolean_automation_run_locked (start, len);
560         }
561         if (change) {
562                 Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
563         }
564         return change;
565 }
566
567 bool
568 SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
569 {
570         Glib::Threads::RWLock::ReaderLock lm (master_lock);
571         return _masters.find (m->id()) != _masters.end();
572 }
573
574 bool
575 SlavableAutomationControl::slaved () const
576 {
577         Glib::Threads::RWLock::ReaderLock lm (master_lock);
578         return !_masters.empty();
579 }
580
581 int
582 SlavableAutomationControl::MasterRecord::set_state (XMLNode const& n, int)
583 {
584         n.get_property (X_("yn"), _yn);
585         n.get_property (X_("val-ctrl"), _val_ctrl);
586         n.get_property (X_("val-master"), _val_master);
587         return 0;
588 }
589
590 void
591 SlavableAutomationControl::use_saved_master_ratios ()
592 {
593         if (!_masters_node) {
594                 return;
595         }
596
597         Glib::Threads::RWLock::ReaderLock lm (master_lock);
598
599         XMLNodeList nlist = _masters_node->children();
600         XMLNodeIterator niter;
601
602         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
603                 ID id_val;
604                 if (!(*niter)->get_property (X_("id"), id_val)) {
605                         continue;
606                 }
607                 Masters::iterator mi = _masters.find (id_val);
608                 if (mi == _masters.end()) {
609                         continue;
610                 }
611                 mi->second.set_state (**niter, Stateful::loading_state_version);
612         }
613
614         delete _masters_node;
615         _masters_node = 0;
616
617         return;
618 }
619
620
621 XMLNode&
622 SlavableAutomationControl::get_state ()
623 {
624         XMLNode& node (AutomationControl::get_state());
625
626         /* store VCA master ratios */
627
628         {
629                 Glib::Threads::RWLock::ReaderLock lm (master_lock);
630                 if (!_masters.empty()) {
631                         XMLNode* masters_node = new XMLNode (X_("masters"));
632                         for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
633                                 XMLNode* mnode = new XMLNode (X_("master"));
634                                 mnode->set_property (X_("id"), mr->second.master()->id());
635
636                                 if (_desc.toggled) {
637                                         mnode->set_property (X_("yn"), mr->second.yn());
638                                 } else {
639                                         mnode->set_property (X_("val-ctrl"), mr->second.val_ctrl());
640                                         mnode->set_property (X_("val-master"), mr->second.val_master());
641                                 }
642                                 masters_node->add_child_nocopy (*mnode);
643                         }
644                         node.add_child_nocopy (*masters_node);
645                 }
646         }
647
648         return node;
649 }
650
651 int
652 SlavableAutomationControl::set_state (XMLNode const& node, int version)
653 {
654         XMLNodeList nlist = node.children();
655         XMLNodeIterator niter;
656
657         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
658                 if ((*niter)->name() == X_("masters")) {
659                         _masters_node = new XMLNode (**niter);
660                 }
661         }
662
663         return AutomationControl::set_state (node, version);
664 }
665
666
667 #endif /* __libardour_slavable_automation_control_h__ */