summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2016-10-16 15:50:41 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2016-10-16 15:51:50 -0400
commitd2835bc8024a12a751d8019db3cba4591ed2a33a (patch)
treeefa0de69d4ac9630e8d27f23cfe529adedc4344c
parent7e5e95d7dbaba4d1280d68b3880a736351a5280d (diff)
improved and hopefully correct fix for "setting AutomationControl marks session dirty even when it should not, if in playback mode"
Hopefully comment is more explanatory as well.
-rw-r--r--libs/ardour/automation_control.cc43
1 files changed, 32 insertions, 11 deletions
diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc
index 56fd0e6409..a377aed839 100644
--- a/libs/ardour/automation_control.cc
+++ b/libs/ardour/automation_control.cc
@@ -119,20 +119,41 @@ AutomationControl::set_value (double val, PBD::Controllable::GroupControlDisposi
void
AutomationControl::actually_set_value (double value, PBD::Controllable::GroupControlDisposition gcd)
{
- bool to_list = _list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_write();
- /* We cannot use ::get_value() here since that is virtual,
- and its return value will/may depend on the ordering
- of a derived class' own implementation of ::actually_set_value().
-
- The derived classes generally need to set their own internal state
- before calling this version, which means that ::get_value()
- would generally return the *NEW* state, and thus lead to
- Changed() not being emitted below.
+ boost::shared_ptr<AutomationList> al = boost::dynamic_pointer_cast<AutomationList> (_list);
+ const framepos_t pos = _session.transport_frame();
+ bool to_list;
+ double old_value;
+
+ /* We cannot use ::get_value() here since that is virtual, and intended
+ to return a scalar value that in some way reflects the state of the
+ control (with semantics defined by the control itself, since it's
+ internal state may be more complex than can be fully represented by
+ a single scalar).
+
+ This method's only job is to set the "user_double()" value of the
+ underlying Evoral::Control object, and so we should compare the new
+ value we're being given to the current user_double().
+
+ Unless ... we're doing automation playback, in which case the
+ current effective value of the control (used to determine if
+ anything has changed) is the one derived from the automation event
+ list.
*/
- const double old_value = Control::user_double ();
+ if (!al) {
+ to_list = false;
+ old_value = Control::user_double();
+ } else {
+ if (al->automation_write ()) {
+ to_list = true;
+ old_value = Control::user_double ();
+ } else if (al->automation_playback()) {
+ to_list = false;
+ old_value = al->eval (pos);
+ }
+ }
- Control::set_double (value, _session.transport_frame(), to_list);
+ Control::set_double (value, pos, to_list);
if (old_value != value) {
// AutomationType at = (AutomationType) _parameter.type();