X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Fautomation_control.h;h=a2eff17d9aea5aaa8dc048b851c917dbd71589d3;hb=b042072df4fcf8fd036965d2c9f5d17c34e0d2c1;hp=aeee9dab30cdcf9be4ef88bafdd843fdf873767a;hpb=2ba58dfe65bb0c5ba7d5eb18a1566fa79eeb6993;p=ardour.git diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h index aeee9dab30..a2eff17d9a 100644 --- a/libs/ardour/ardour/automation_control.h +++ b/libs/ardour/ardour/automation_control.h @@ -21,32 +21,46 @@ #ifndef __ardour_automation_control_h__ #define __ardour_automation_control_h__ +#include + +#include + #include #include #include "pbd/controllable.h" + +#include "evoral/types.hpp" #include "evoral/Control.hpp" -#include "ardour/libardour_visibility.h" #include "ardour/automation_list.h" +#include "ardour/control_group_member.h" +#include "ardour/parameter_descriptor.h" + +#include "ardour/libardour_visibility.h" namespace ARDOUR { class Session; class Automatable; - +class ControlGroup; /** A PBD::Controllable with associated automation data (AutomationList) */ -class LIBARDOUR_API AutomationControl : public PBD::Controllable, public Evoral::Control, public boost::enable_shared_from_this +class LIBARDOUR_API AutomationControl + : public PBD::Controllable + , public Evoral::Control + , public boost::enable_shared_from_this + , public ControlGroupMember { -public: + public: AutomationControl(ARDOUR::Session&, - const Evoral::Parameter& parameter, - boost::shared_ptr l=boost::shared_ptr(), - const std::string& name=""); + const Evoral::Parameter& parameter, + const ParameterDescriptor& desc, + boost::shared_ptr l=boost::shared_ptr(), + const std::string& name=""); - ~AutomationControl (); + ~AutomationControl (); boost::shared_ptr alist() const { return boost::dynamic_pointer_cast(_list); @@ -55,51 +69,133 @@ public: void set_list (boost::shared_ptr); inline bool automation_playback() const { - return alist()->automation_playback(); + return alist() ? alist()->automation_playback() : false; } inline bool automation_write() const { - return alist()->automation_write(); + return alist() ? alist()->automation_write() : false; } inline AutoState automation_state() const { - return alist()->automation_state(); + return alist() ? alist()->automation_state() : Off; } inline AutoStyle automation_style() const { - return alist()->automation_style(); + return alist() ? alist()->automation_style() : Absolute; } - void set_automation_state(AutoState as); - void set_automation_style(AutoStyle as); - void start_touch (double when); - void stop_touch (bool mark, double when); + void set_automation_state(AutoState as); + void set_automation_style(AutoStyle as); + void start_touch(double when); + void stop_touch(bool mark, double when); - void set_value (double); + /* inherited from PBD::Controllable. + */ double get_value () const; - - virtual double internal_to_interface (double v) const { - return v; - } - - virtual double interface_to_internal (double v) const { - return v; + /* 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 value, PBD::Controllable::GroupControlDisposition group_override); + /* 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. + */ + void set_value_unchecked (double val) { + actually_set_value (val, PBD::Controllable::NoGroup); } - virtual double internal_to_user (double v) const { - return v; - } + double lower() const { return _desc.lower; } + double upper() const { return _desc.upper; } + double normal() const { return _desc.normal; } + bool toggled() const { return _desc.toggled; } - double lower() const { return parameter().min(); } - double upper() const { return parameter().max(); } - double normal() const { return parameter().normal(); } - bool toggled() const { return parameter().toggled(); } + double internal_to_interface (double i) const; + double interface_to_internal (double i) const; - const ARDOUR::Session& session() const { return _session; } + const ParameterDescriptor& desc() const { return _desc; } -protected: + const ARDOUR::Session& session() const { return _session; } + void commit_transaction (bool did_write); + protected: ARDOUR::Session& _session; + boost::shared_ptr _group; + + const ParameterDescriptor _desc; + + bool check_rt (double val, Controllable::GroupControlDisposition gcd); + + /* derived classes may reimplement this, but should either + call this explicitly inside their version OR make sure that the + Controllable::Changed signal is emitted when necessary. + */ + + virtual void actually_set_value (double value, PBD::Controllable::GroupControlDisposition); + + private: + /* I am unclear on why we have to make ControlGroup a friend in order + to get access to the ::set_group() method when it is already + declared to be a friend in ControlGroupMember. Oh well. + */ + friend class ControlGroup; + void set_group (boost::shared_ptr); +}; + +class SlavableAutomationControl : public AutomationControl +{ + public: + SlavableAutomationControl(ARDOUR::Session&, + const Evoral::Parameter& parameter, + const ParameterDescriptor& desc, + boost::shared_ptr l=boost::shared_ptr(), + const std::string& name=""); + + ~SlavableAutomationControl (); + + double get_value () const; + + void add_master (boost::shared_ptr); + void remove_master (boost::shared_ptr); + void clear_masters (); + bool slaved_to (boost::shared_ptr) const; + bool slaved () const; + std::vector masters () const; + + PBD::Signal0 MasterStatusChange; + + protected: + + class MasterRecord { + public: + MasterRecord (boost::shared_ptr gc, double r) + : _master (gc) + , _ratio (r) + {} + + boost::shared_ptr master() const { return _master; } + double ratio () const { return _ratio; } + void reset_ratio (double r) { _ratio = r; } + + PBD::ScopedConnection connection; + + private: + boost::shared_ptr _master; + double _ratio; + + }; + + mutable Glib::Threads::RWLock master_lock; + typedef std::map Masters; + Masters _masters; + PBD::ScopedConnectionList masters_connections; + virtual void master_changed (bool from_self, GroupControlDisposition gcd); + void master_going_away (boost::weak_ptr); + virtual void recompute_masters_ratios (double val) { /* do nothing by default */} + virtual double get_masters_value_locked () const; + double get_value_locked() const; + };