2 Copyright (C) 2016 Paul Davis
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)
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
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.
19 #ifndef __libardour_slavable_automation_control_h__
20 #define __libardour_slavable_automation_control_h__
22 #include "pbd/enumwriter.h"
23 #include "pbd/error.h"
24 #include "pbd/types_convert.h"
27 #include "evoral/Curve.hpp"
29 #include "ardour/audioengine.h"
30 #include "ardour/slavable_automation_control.h"
31 #include "ardour/session.h"
34 using namespace ARDOUR;
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)
48 SlavableAutomationControl::~SlavableAutomationControl ()
57 SlavableAutomationControl::get_masters_value_locked () const
61 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
62 if (mr->second.master()->get_value()) {
69 double v = 1.0; /* the masters function as a scaling factor */
71 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
72 v *= mr->second.master()->get_value ();
80 SlavableAutomationControl::get_value_locked() const
82 /* read or write masters lock must be held */
84 if (_masters.empty()) {
85 return Control::get_double (false, _session.transport_frame());
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.
93 if (Control::get_double (false, _session.transport_frame())) {
98 return Control::get_double() * get_masters_value_locked ();
101 /** Get the current effective `user' value based on automation state */
103 SlavableAutomationControl::get_value() const
105 bool from_list = _list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback();
107 Glib::Threads::RWLock::ReaderLock lm (master_lock);
109 return get_value_locked ();
111 return Control::get_double (true, _session.transport_frame()) * get_masters_value_locked();
116 SlavableAutomationControl::get_masters_curve_locked (framepos_t, framepos_t, float*, framecnt_t) const
118 /* Every AutomationControl needs to implement this as-needed.
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()
128 SlavableAutomationControl::masters_curve_multiply (framepos_t start, framepos_t end, float* vec, framecnt_t veclen) const
130 bool rv = list()->curve().rt_safe_get_vector (start, end, vec, veclen);
131 if (_masters.empty()) {
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());
139 boost::shared_ptr<SlavableAutomationControl> sc
140 = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
142 got_curve = sc->get_masters_curve_locked (start, end, scratch, veclen);
144 got_curve = ac->list()->curve().rt_safe_get_vector (start, end, scratch, veclen);
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
150 // TODO optimize this, in case rv is false, direcly use "vec" above.
152 memcpy (vec, scratch, sizeof (float) * veclen);
154 for (framecnt_t i = 0; i < veclen; ++i) {
155 vec[i] *= scratch[i];
159 const float v = get_masters_value ();
160 for (framecnt_t i = 0; i < veclen; ++i) {
169 SlavableAutomationControl::actually_set_value (double value, PBD::Controllable::GroupControlDisposition gcd)
171 if (!_desc.toggled) {
173 Glib::Threads::RWLock::WriterLock lm (master_lock);
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) {
181 value /= masters_value;
182 value = std::max (lower(), std::min(upper(), value));
187 /* this will call Control::set_double() and emit Changed signals as appropriate */
188 AutomationControl::actually_set_value (value, gcd);
192 SlavableAutomationControl::add_master (boost::shared_ptr<AutomationControl> m, bool loading)
194 std::pair<Masters::iterator,bool> res;
197 Glib::Threads::RWLock::WriterLock lm (master_lock);
199 pair<PBD::ID,MasterRecord> newpair (m->id(), MasterRecord (m, 1.0));
200 res = _masters.insert (newpair);
206 if (!_desc.toggled) {
207 const double master_value = m->get_value();
209 if (master_value == 0.0) {
210 AutomationControl::set_double (0.0, Controllable::NoGroup);
212 /* scale control's own value by
213 amount that the master will
216 AutomationControl::set_double ((Control::get_double() / master_value), Controllable::NoGroup);
221 /* note that we bind @param m as a weak_ptr<AutomationControl>, thus
222 avoiding holding a reference to the control in the binding
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;
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
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).
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.
246 m->Changed.connect_same_thread (res.first->second.connection, boost::bind (&SlavableAutomationControl::master_changed, this, _1, _2, m));
251 /* this will notify everyone that we're now slaved to the master */
252 MasterStatusChange (); /* EMIT SIGNAL */
257 update_boolean_masters_records (m);
261 SlavableAutomationControl::get_boolean_masters () const
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()) {
278 SlavableAutomationControl::update_boolean_masters_records (boost::shared_ptr<AutomationControl> m)
281 /* We may modify a MasterRecord, but we not modify the master
282 * map, so we use a ReaderLock
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).
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
307 mi->second.set_yn (m->get_value());
313 SlavableAutomationControl::master_changed (bool /*from_self*/, GroupControlDisposition gcd, boost::shared_ptr<AutomationControl> m)
315 update_boolean_masters_records (m);
316 Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
320 SlavableAutomationControl::master_going_away (boost::weak_ptr<AutomationControl> wm)
322 boost::shared_ptr<AutomationControl> m = wm.lock();
329 SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
331 masters_connections.erase (boost::weak_ptr<AutomationControl>(m));
332 pre_remove_master (m);
335 Glib::Threads::RWLock::WriterLock lm (master_lock);
337 if (!_masters.erase (m->id())) {
341 if (!_session.deletion_in_progress()) {
343 const double master_value = m->get_value ();
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.
352 /* bump up the control's own value by the level
353 of the master that is being removed.
355 AutomationControl::set_double (AutomationControl::get_double() * master_value, Controllable::NoGroup);
360 if (_session.deletion_in_progress()) {
361 /* no reason to care about new values or sending signals */
365 MasterStatusChange (); /* EMIT SIGNAL */
367 /* no need to update boolean masters records, since the MR will have
368 * been removed already.
373 SlavableAutomationControl::clear_masters ()
375 double current_value;
377 bool had_masters = false;
379 /* null ptr means "all masters */
380 pre_remove_master (boost::shared_ptr<AutomationControl>());
383 Glib::Threads::RWLock::WriterLock lm (master_lock);
384 current_value = get_value_locked ();
385 if (!_masters.empty()) {
389 new_value = get_value_locked ();
393 MasterStatusChange (); /* EMIT SIGNAL */
396 if (new_value != current_value) {
397 actually_set_value (current_value, Controllable::UseGroup);
400 /* no need to update boolean masters records, since all MRs will have
401 * been removed already.
406 SlavableAutomationControl::find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const
408 if (_masters.empty()) {
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)
417 for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
418 boost::shared_ptr<AutomationControl> ac (mr->second.master());
420 boost::shared_ptr<SlavableAutomationControl> sc
421 = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
423 if (sc && sc->find_next_event_locked (now, end, next_event)) {
427 Evoral::ControlList::const_iterator i;
428 boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
429 Evoral::ControlEvent cp (now, 0.0f);
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) {
441 if (i != alist->end() && (*i)->when < end) {
442 if ((*i)->when < next_event.when) {
443 next_event.when = (*i)->when;
453 SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
455 Glib::Threads::RWLock::ReaderLock lm (master_lock);
456 return _masters.find (m->id()) != _masters.end();
460 SlavableAutomationControl::slaved () const
462 Glib::Threads::RWLock::ReaderLock lm (master_lock);
463 return !_masters.empty();
467 SlavableAutomationControl::use_saved_master_ratios ()
469 if (!_masters_node) {
473 Glib::Threads::RWLock::ReaderLock lm (master_lock);
475 /* use stored state, do not recompute */
479 XMLNodeList nlist = _masters_node->children();
480 XMLNodeIterator niter;
482 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
485 if (!(*niter)->get_property (X_("id"), id_val) || !(*niter)->get_property (X_("yn"), yn)) {
489 Masters::iterator mi = _masters.find (id_val);
490 if (mi != _masters.end()) {
491 mi->second.set_yn (yn);
499 delete _masters_node;
507 SlavableAutomationControl::get_state ()
509 XMLNode& node (AutomationControl::get_state());
511 /* store VCA master ratios */
514 Glib::Threads::RWLock::ReaderLock lm (master_lock);
516 if (!_masters.empty()) {
518 XMLNode* masters_node = new XMLNode (X_("masters"));
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);
531 node.add_child_nocopy (*masters_node);
539 SlavableAutomationControl::set_state (XMLNode const& node, int version)
541 XMLNodeList nlist = node.children();
542 XMLNodeIterator niter;
544 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
545 if ((*niter)->name() == X_("masters")) {
546 _masters_node = new XMLNode (**niter);
550 return AutomationControl::set_state (node, version);
554 #endif /* __libardour_slavable_automation_control_h__ */