Add AutomationControl::set_value_unchecked() and AutomationControl::writable() and...
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 22 Oct 2015 02:31:30 +0000 (22:31 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 22 Oct 2015 02:31:35 +0000 (22:31 -0400)
Classes derived from AutomationControl now check ::writable() in their ::set_value() methods to ensure that they
do not attempt to overwrite data sent to them while automation playback is underway.

14 files changed:
libs/ardour/amp.cc
libs/ardour/ardour/amp.h
libs/ardour/ardour/automation_control.h
libs/ardour/ardour/midi_track.h
libs/ardour/ardour/pan_controllable.h
libs/ardour/ardour/plugin_insert.h
libs/ardour/ardour/route.h
libs/ardour/ardour/track.h
libs/ardour/automation_control.cc
libs/ardour/midi_track.cc
libs/ardour/pan_controllable.cc
libs/ardour/plugin_insert.cc
libs/ardour/route.cc
libs/ardour/track.cc

index c62bb7ff69574c86271825777d2a1bad85175b2c..8b55b8ca8def8a34dc70501468e0cb18b6af0383 100644 (file)
@@ -402,6 +402,14 @@ Amp::set_state (const XMLNode& node, int version)
 
 void
 Amp::GainControl::set_value (double val)
+{
+       if (writable()) {
+               set_value_unchecked (val);
+       }
+}
+
+void
+Amp::GainControl::set_value_unchecked (double val)
 {
        AutomationControl::set_value (std::max (std::min (val, (double)_desc.upper), (double)_desc.lower));
        _amp->session().set_dirty ();
index 62f273e477e1177dbda4b98f800a862f39331ad6..7cde8531550a3352bfe62efa59a657acf81d239c 100644 (file)
@@ -91,6 +91,7 @@ public:
                }
 
                void set_value (double val);
+               void set_value_unchecked (double);
 
                double internal_to_interface (double) const;
                double interface_to_internal (double) const;
index c634e3474a7b437740e53341789f4de98c054eaf..9190b716774d5ffbe17760a891c5b70b628e4c08 100644 (file)
@@ -81,9 +81,21 @@ public:
        void start_touch(double when);
        void stop_touch(bool mark, double when);
 
+       /* inherited from PBD::Controllable.
+        * Derived classes MUST call ::writable() to verify
+        * that writing to the parameter is legal at that time.
+        */
        void set_value (double);
        double get_value () const;
 
+       /* automation related value setting */
+       virtual bool writable () const;
+       /* Call to ::set_value() with no test for writable() because
+        * this is only used by automation playback. We would like
+        * to make it pure virtual 
+        */
+       virtual void set_value_unchecked (double val) {}
+
        double lower()   const { return _desc.lower; }
        double upper()   const { return _desc.upper; }
        double normal()  const { return _desc.normal; }
index c48f384ce922f93e22aace9f94399fd1f74b809a..80bb743b10976cb65a76fabca40f715280413df2 100644 (file)
@@ -90,6 +90,8 @@ public:
                {}
 
                void set_value (double val);
+               void set_value_unchecked (double);
+               bool writable() const { return true; }
 
                MidiTrack* _route;
        };
index 63ee9d3b8cbf64016f9b1d16f244a344864f14c5..ff00d8119fc7feb84d45385415d59ba5e8f71c42 100644 (file)
@@ -48,6 +48,7 @@ public:
 
        double lower () const;
        void set_value (double);
+       void set_value_unchecked (double);
 
 private:
        Pannable* owner;
index d4d9adb54dc6a8fc2b521b5b82d2de6268400888..a37c9cae68287e213dc39862dbba0cce05d3a643 100644 (file)
@@ -95,6 +95,7 @@ class LIBARDOUR_API PluginInsert : public Processor
                               boost::shared_ptr<AutomationList> list=boost::shared_ptr<AutomationList>());
 
                void set_value (double val);
+               void set_value_unchecked (double);
                double get_value (void) const;
                void catch_up_with_external_value (double val);
                XMLNode& get_state();
@@ -113,6 +114,7 @@ class LIBARDOUR_API PluginInsert : public Processor
 
                void set_value (const Variant& val);
                void set_value (double val);
+               void set_value_unchecked (double);
                double get_value (void) const;
                XMLNode& get_state();
 
index 001accb2e3473b13bfe236f79b20107fdf6f94a0..da4f0f809e1c5f794a8bff048ef312346a9d47cc 100644 (file)
@@ -389,6 +389,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        public:
                SoloControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double);
+               void set_value_unchecked (double);
                double get_value () const;
 
        private:
@@ -399,6 +400,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
        public:
                MuteControllable (std::string name, boost::shared_ptr<Route>);
                void set_value (double);
+               void set_value_unchecked (double);
                double get_value () const;
 
                /* Pretend to change value, but do not affect actual route mute. */
index 31ae261ea777f3fd808358b3c349fa346d731436..fa7b1f30bbd673f450f87c814c370be19bb89f56 100644 (file)
@@ -207,6 +207,7 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream
                RecEnableControl (boost::shared_ptr<Track> t);
 
                void set_value (double);
+               void set_value_unchecked (double);
                double get_value (void) const;
 
                boost::weak_ptr<Track> track;
index 0e2355e708947ffdabd0ba6aa87520fe39cf6c47..671cd6e977b899f24e17b05e4871dcceac2ecd2b 100644 (file)
@@ -25,6 +25,7 @@
 #include "ardour/session.h"
 
 #include "pbd/memento_command.h"
+#include "pbd/stacktrace.h"
 
 #include "i18n.h"
 
@@ -48,6 +49,16 @@ AutomationControl::~AutomationControl ()
 {
 }
 
+bool
+AutomationControl::writable() const
+{
+       boost::shared_ptr<AutomationList> al = alist();
+       if (al) {
+               return al->automation_state() != Play;
+       }
+       return true;
+}
+
 /** Get the current effective `user' value based on automation state */
 double
 AutomationControl::get_value() const
index f3bc2c4f79880f064d5ad5aa724c1c15eddaa018..c49a2ef7f1afbb227327104cb796f0238cfd62d8 100644 (file)
@@ -716,6 +716,14 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st
 
 void
 MidiTrack::MidiControl::set_value(double val)
+{
+       if (writable()) {
+               set_value_unchecked (val);
+       }
+}
+
+void
+MidiTrack::MidiControl::set_value_unchecked(double val)
 {
        const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
        const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
index ecffa174401c8bb05b32f787e86c5bbd25dba0f4..71c8a9f62fc220e76e3ff9f757938b0fe9d6f3da 100644 (file)
@@ -37,7 +37,15 @@ PanControllable::lower () const
 void
 PanControllable::set_value (double v)
 {
-        boost::shared_ptr<Panner> p = owner->panner();
+       if (writable()) {
+               set_value_unchecked (v);
+       }
+}
+
+void
+PanControllable::set_value_unchecked (double v)
+{
+       boost::shared_ptr<Panner> p = owner->panner();
 
         if (!p) {
                 /* no panner: just do it */
index ec6d86d71a76c66094fdba48db8e72065af82033..34745b7cabd933aea2f7b685dd6e2d5fffedf30f 100644 (file)
@@ -405,7 +405,16 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
                                const float val = c->list()->rt_safe_eval (now, valid);
 
                                if (valid) {
-                                       c->set_value(val);
+                                       /* This is the ONLY place where we are
+                                        *  allowed to call
+                                        *  AutomationControl::set_value_unchecked(). We
+                                        *  know that the control is in
+                                        *  automation playback mode, so no
+                                        *  check on writable() is required
+                                        *  (which must be done in AutomationControl::set_value()
+                                        *
+                                        */
+                                       c->set_value_unchecked(val);
                                }
 
                        }
@@ -1294,6 +1303,14 @@ PluginInsert::PluginControl::PluginControl (PluginInsert*                     p,
 /** @param val `user' value */
 void
 PluginInsert::PluginControl::set_value (double user_val)
+{
+       if (writable()) {
+               set_value_unchecked (user_val);
+       }
+}
+
+void
+PluginInsert::PluginControl::set_value_unchecked (double user_val)
 {
        /* FIXME: probably should be taking out some lock here.. */
 
@@ -1359,6 +1376,14 @@ PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert*
 
 void
 PluginInsert::PluginPropertyControl::set_value (double user_val)
+{
+       if (writable()) {
+               set_value_unchecked (user_val);
+       }
+}
+
+void
+PluginInsert::PluginPropertyControl::set_value_unchecked (double user_val)
 {
        /* Old numeric set_value(), coerce to appropriate datatype if possible.
           This is lossy, but better than nothing until Ardour's automation system
index 60f4908768c055952e0b642a902516a969acd1b5..56d1f69ebec4d5308c1bce872e2d03a7609a5b6b 100644 (file)
@@ -3847,6 +3847,14 @@ Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<R
 
 void
 Route::SoloControllable::set_value (double val)
+{
+       if (writable()) {
+               set_value_unchecked (val);
+       }
+}
+
+void
+Route::SoloControllable::set_value_unchecked (double val)
 {
        const bool bval = ((val >= 0.5) ? true : false);
 
@@ -3920,6 +3928,14 @@ Route::MuteControllable::set_superficial_value(bool muted)
 
 void
 Route::MuteControllable::set_value (double val)
+{
+       if (writable()) {
+               set_value_unchecked (val);
+       }
+}
+
+void
+Route::MuteControllable::set_value_unchecked (double val)
 {
        const bool bval = ((val >= 0.5) ? true : false);
 
index e99d07f0475f139f46828899bf09b3108f78869f..c4c82808bd5cb0d5d9f45a8de1f407f1d2c8e63f 100644 (file)
@@ -191,6 +191,14 @@ Track::RecEnableControl::RecEnableControl (boost::shared_ptr<Track> t)
 
 void
 Track::RecEnableControl::set_value (double val)
+{
+       if (writable()) {
+               set_value_unchecked (val);
+       }
+}
+
+void
+Track::RecEnableControl::set_value_unchecked (double val)
 {
        boost::shared_ptr<Track> t = track.lock ();
        if (!t) {