amend a1b4f9b8ab - handle disconnecting from all masters
[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         pre_remove_master (m);
332
333         {
334                 Glib::Threads::RWLock::WriterLock lm (master_lock);
335
336                 masters_connections.erase (boost::weak_ptr<AutomationControl>(m));
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                 masters_connections.clear ();
390                 new_value = get_value_locked ();
391         }
392
393         if (had_masters) {
394                 MasterStatusChange (); /* EMIT SIGNAL */
395         }
396
397         if (new_value != current_value) {
398                 actually_set_value (current_value, Controllable::UseGroup);
399         }
400
401         /* no need to update boolean masters records, since all MRs will have
402          * been removed already.
403          */
404 }
405
406 bool
407 SlavableAutomationControl::find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const
408 {
409         if (_masters.empty()) {
410                 return false;
411         }
412         bool rv = false;
413         /* iterate over all masters check their automation lists
414          * for any event between "now" and "end" which is earlier than
415          * next_event.when. If found, set next_event.when and return true.
416          * (see also Automatable::find_next_event)
417          */
418         for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
419                 boost::shared_ptr<AutomationControl> ac (mr->second.master());
420
421                 boost::shared_ptr<SlavableAutomationControl> sc
422                         = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
423
424                 if (sc && sc->find_next_event_locked (now, end, next_event)) {
425                         rv = true;
426                 }
427
428                 Evoral::ControlList::const_iterator i;
429                 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
430                 Evoral::ControlEvent cp (now, 0.0f);
431                 if (!alist) {
432                         continue;
433                 }
434
435                 for (i = lower_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator);
436                      i != alist->end() && (*i)->when < end; ++i) {
437                         if ((*i)->when > now) {
438                                 break;
439                         }
440                 }
441
442                 if (i != alist->end() && (*i)->when < end) {
443                         if ((*i)->when < next_event.when) {
444                                 next_event.when = (*i)->when;
445                                 rv = true;
446                         }
447                 }
448         }
449
450         return rv;
451 }
452
453 bool
454 SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
455 {
456         Glib::Threads::RWLock::ReaderLock lm (master_lock);
457         return _masters.find (m->id()) != _masters.end();
458 }
459
460 bool
461 SlavableAutomationControl::slaved () const
462 {
463         Glib::Threads::RWLock::ReaderLock lm (master_lock);
464         return !_masters.empty();
465 }
466
467 void
468 SlavableAutomationControl::use_saved_master_ratios ()
469 {
470         if (!_masters_node) {
471                 return;
472         }
473
474         Glib::Threads::RWLock::ReaderLock lm (master_lock);
475
476         /* use stored state, do not recompute */
477
478         if (_desc.toggled) {
479
480                 XMLNodeList nlist = _masters_node->children();
481                 XMLNodeIterator niter;
482
483                 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
484                         ID id_val;
485                         bool yn;
486                         if (!(*niter)->get_property (X_("id"), id_val) || !(*niter)->get_property (X_("yn"), yn)) {
487                                 continue;
488                   }
489
490                         Masters::iterator mi = _masters.find (id_val);
491                         if (mi != _masters.end()) {
492                                 mi->second.set_yn (yn);
493                         }
494                 }
495
496         } else {
497
498         }
499
500         delete _masters_node;
501         _masters_node = 0;
502
503         return;
504 }
505
506
507 XMLNode&
508 SlavableAutomationControl::get_state ()
509 {
510         XMLNode& node (AutomationControl::get_state());
511
512         /* store VCA master ratios */
513
514         {
515                 Glib::Threads::RWLock::ReaderLock lm (master_lock);
516
517                 if (!_masters.empty()) {
518
519                         XMLNode* masters_node = new XMLNode (X_("masters"));
520
521                         if (_desc.toggled) {
522                                 for (Masters::iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
523                                         XMLNode* mnode = new XMLNode (X_("master"));
524                                         mnode->set_property (X_("id"), mr->second.master()->id());
525                                         mnode->set_property (X_("yn"), mr->second.yn());
526                                         masters_node->add_child_nocopy (*mnode);
527                                 }
528                         } else {
529
530                         }
531
532                         node.add_child_nocopy (*masters_node);
533                 }
534         }
535
536         return node;
537 }
538
539 int
540 SlavableAutomationControl::set_state (XMLNode const& node, int version)
541 {
542         XMLNodeList nlist = node.children();
543         XMLNodeIterator niter;
544
545         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
546                 if ((*niter)->name() == X_("masters")) {
547                         _masters_node = new XMLNode (**niter);
548                 }
549         }
550
551         return AutomationControl::set_state (node, version);
552 }
553
554
555 #endif /* __libardour_slavable_automation_control_h__ */