1 /* 2 * Copyright (C) 2016-2017 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2017 Robin Gareus <robin@gareus.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #ifndef __ardour_slavable_automation_control_h__ 21 #define __ardour_slavable_automation_control_h__ 22 23 #include "ardour/automation_control.h" 24 #include "ardour/libardour_visibility.h" 25 26 namespace ARDOUR { 27 28 class LIBARDOUR_API SlavableAutomationControl : public AutomationControl 29 { 30 public: 31 SlavableAutomationControl(ARDOUR::Session&, 32 const Evoral::Parameter& parameter, 33 const ParameterDescriptor& desc, 34 boost::shared_ptr<ARDOUR::AutomationList> l=boost::shared_ptr<ARDOUR::AutomationList>(), 35 const std::string& name="", 36 PBD::Controllable::Flag flags=PBD::Controllable::Flag (0) 37 ); 38 39 virtual ~SlavableAutomationControl (); 40 41 double get_value () const; 42 43 void add_master (boost::shared_ptr<AutomationControl>); 44 void remove_master (boost::shared_ptr<AutomationControl>); 45 void clear_masters (); 46 bool slaved_to (boost::shared_ptr<AutomationControl>) const; 47 bool slaved () const; 48 49 virtual void automation_run (samplepos_t start, pframes_t nframes); 50 get_masters_value()51 double get_masters_value () const { 52 Glib::Threads::RWLock::ReaderLock lm (master_lock); 53 return get_masters_value_locked (); 54 } 55 56 /* factor out get_masters_value() */ 57 double reduce_by_masters (double val, bool ignore_automation_state = false) const { 58 Glib::Threads::RWLock::ReaderLock lm (master_lock); 59 return reduce_by_masters_locked (val, ignore_automation_state); 60 } 61 get_masters_curve(samplepos_t s,samplepos_t e,float * v,samplecnt_t l)62 bool get_masters_curve (samplepos_t s, samplepos_t e, float* v, samplecnt_t l) const { 63 Glib::Threads::RWLock::ReaderLock lm (master_lock); 64 return get_masters_curve_locked (s, e, v, l); 65 } 66 67 /* for toggled/boolean controls, returns a count of the number of 68 masters currently enabled. For other controls, returns zero. 69 */ 70 int32_t get_boolean_masters () const; 71 72 PBD::Signal0<void> MasterStatusChange; 73 74 void use_saved_master_ratios (); 75 76 int set_state (XMLNode const&, int); 77 XMLNode& get_state(); 78 find_next_event(double n,double e,Evoral::ControlEvent & ev)79 bool find_next_event (double n, double e, Evoral::ControlEvent& ev) const 80 { 81 Glib::Threads::RWLock::ReaderLock lm (master_lock); 82 return find_next_event_locked (n, e, ev); 83 } 84 85 bool find_next_event_locked (double now, double end, Evoral::ControlEvent& next_event) const; 86 87 protected: 88 89 class MasterRecord { 90 public: MasterRecord(boost::weak_ptr<AutomationControl> gc,double vc,double vm)91 MasterRecord (boost::weak_ptr<AutomationControl> gc, double vc, double vm) 92 : _master (gc) 93 , _yn (false) 94 , _val_ctrl (vc) 95 , _val_master (vm) 96 {} 97 master()98 boost::shared_ptr<AutomationControl> master() const { assert(_master.lock()); return _master.lock(); } 99 val_ctrl()100 double val_ctrl () const { return _val_ctrl; } val_master()101 double val_master () const { return _val_master; } 102 val_master_inv()103 double val_master_inv () const { return _val_master == 0 ? 0 : 1.0 / _val_master; } master_ratio()104 double master_ratio () const { return _val_master == 0 ? 0 : master()->get_value() / _val_master; } 105 106 int set_state (XMLNode const&, int); 107 108 /* for boolean/toggled controls, we store a boolean value to 109 * indicate if this master returned true/false (1.0/0.0) from 110 * ::get_value() after its most recent change. 111 */ 112 yn()113 bool yn() const { return _yn; } set_yn(bool yn)114 void set_yn (bool yn) { _yn = yn; } 115 116 PBD::ScopedConnection changed_connection; 117 PBD::ScopedConnection dropped_connection; 118 119 private: 120 boost::weak_ptr<AutomationControl> _master; 121 /* holds most recently seen master value for boolean/toggle controls */ 122 bool _yn; 123 124 /* values at time of assignment */ 125 double _val_ctrl; 126 double _val_master; 127 }; 128 129 mutable Glib::Threads::RWLock master_lock; 130 typedef std::map<PBD::ID,MasterRecord> Masters; 131 Masters _masters; 132 133 void master_going_away (boost::weak_ptr<AutomationControl>); 134 double get_value_locked() const; 135 void actually_set_value (double value, PBD::Controllable::GroupControlDisposition); 136 void update_boolean_masters_records (boost::shared_ptr<AutomationControl>); 137 138 virtual bool get_masters_curve_locked (samplepos_t, samplepos_t, float*, samplecnt_t) const; 139 bool masters_curve_multiply (samplepos_t, samplepos_t, float*, samplecnt_t) const; 140 141 virtual double reduce_by_masters_locked (double val, bool) const; 142 virtual double scale_automation_callback (double val, double ratio) const; 143 144 virtual bool handle_master_change (boost::shared_ptr<AutomationControl>); 145 virtual bool boolean_automation_run_locked (samplepos_t start, pframes_t len); 146 bool boolean_automation_run (samplepos_t start, pframes_t len); 147 148 virtual void master_changed (bool from_self, GroupControlDisposition gcd, boost::weak_ptr<AutomationControl>); 149 virtual double get_masters_value_locked () const; pre_remove_master(boost::shared_ptr<AutomationControl>)150 virtual void pre_remove_master (boost::shared_ptr<AutomationControl>) {} post_add_master(boost::shared_ptr<AutomationControl>)151 virtual void post_add_master (boost::shared_ptr<AutomationControl>) {} 152 153 XMLNode* _masters_node; /* used to store master ratios in ::set_state() for later use */ 154 }; 155 156 } // namespace ARDOUR 157 158 #endif /* __ardour_slavable_automation_control_h__ */ 159