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