Add AutomationControl::set_value_unchecked() and AutomationControl::writable() and use them.

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.
This commit is contained in:
Paul Davis 2015-10-21 22:31:30 -04:00
parent 6ca3a1593e
commit 8d3a8ca913
14 changed files with 107 additions and 2 deletions

View 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 ();

View 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;

View 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; }

View File

@ -90,6 +90,8 @@ public:
{}
void set_value (double val);
void set_value_unchecked (double);
bool writable() const { return true; }
MidiTrack* _route;
};

View File

@ -48,6 +48,7 @@ public:
double lower () const;
void set_value (double);
void set_value_unchecked (double);
private:
Pannable* owner;

View 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();

View 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. */

View 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;

View 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

View 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);

View 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 */

View 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

View 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);

View 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) {