1 #pragma once
2 
3 #include <QObject>
4 #include <QEvent>
5 #include <QMutex>
6 
7 #include "preferences/usersettings.h"
8 #include "controllers/midi/midimessage.h"
9 #include "control/control.h"
10 
11 class ControlObject : public QObject {
12     Q_OBJECT
13   public:
14     ControlObject();
15 
16     // bIgnoreNops: Don't emit a signal if the CO is set to its current value.
17     // bTrack: Record statistics about this control.
18     // bPersist: Store value on exit, load on startup.
19     // defaultValue: default value of CO. If CO is persistent and there is no valid
20     //               value found in the config, this is also the initial value.
21     ControlObject(const ConfigKey& key,
22             bool bIgnoreNops = true,
23             bool bTrack = false,
24             bool bPersist = false,
25             double defaultValue = 0.0);
26     virtual ~ControlObject();
27 
28     // Returns a pointer to the ControlObject matching the given ConfigKey
29     static ControlObject* getControl(const ConfigKey& key, ControlFlags flags = ControlFlag::None);
30     static ControlObject* getControl(const QString& group,
31             const QString& item,
32             ControlFlags flags = ControlFlag::None) {
33         ConfigKey key(group, item);
34         return getControl(key, flags);
35     }
36 
name()37     QString name() const {
38         return m_pControl ?  m_pControl->name() : QString();
39     }
40 
setName(const QString & name)41     void setName(const QString& name) {
42         if (m_pControl) {
43             m_pControl->setName(name);
44         }
45     }
46 
description()47     const QString description() const {
48         return m_pControl ?  m_pControl->description() : QString();
49     }
50 
setDescription(const QString & description)51     void setDescription(const QString& description) {
52         if (m_pControl) {
53             m_pControl->setDescription(description);
54         }
55     }
56 
57     // Return the key of the object
getKey()58     inline ConfigKey getKey() const {
59         return m_key;
60     }
61 
62     // Returns the value of the ControlObject
get()63     inline double get() const {
64         return m_pControl ? m_pControl->get() : 0.0;
65     }
66 
67     // Returns the bool interpretation of the ControlObject
toBool()68     inline bool toBool() const {
69         return get() > 0.0;
70     }
71 
72     // Instantly returns the value of the ControlObject
73     static double get(const ConfigKey& key);
74 
75     /// Returns the boolean interpretation of the ControlObject's value.
toBool(const ConfigKey & key)76     static bool toBool(const ConfigKey& key) {
77         return ControlObject::get(key) > 0;
78     }
79 
80     // Sets the ControlObject value. May require confirmation by owner.
set(double value)81     inline void set(double value) {
82         if (m_pControl) {
83             m_pControl->set(value, this);
84         }
85     }
86 
87     // Sets the ControlObject value and confirms it.
setAndConfirm(double value)88     inline void setAndConfirm(double value) {
89         if (m_pControl) {
90             m_pControl->setAndConfirm(value, this);
91         }
92     }
93 
94     // Forces the control to 'value', regardless of whether it has a change
95     // request handler attached (identical to setAndConfirm).
forceSet(double value)96     inline void forceSet(double value) {
97         setAndConfirm(value);
98     }
99 
100     // Instantly sets the value of the ControlObject
101     static void set(const ConfigKey& key, const double& value);
102 
103     // Sets the default value
reset()104     inline void reset() {
105         if (m_pControl) {
106             m_pControl->reset();
107         }
108     }
109 
setDefaultValue(double dValue)110     inline void setDefaultValue(double dValue) {
111         if (m_pControl) {
112             m_pControl->setDefaultValue(dValue);
113         }
114     }
defaultValue()115     inline double defaultValue() const {
116         return m_pControl ? m_pControl->defaultValue() : 0.0;
117     }
118 
119     // Returns the parameterized value of the object. Thread safe, non-blocking.
120     virtual double getParameter() const;
121 
122     // Returns the parameterized value of the object. Thread safe, non-blocking.
123     virtual double getParameterForValue(double value) const;
124 
125     // Returns the parameterized value of the object. Thread safe, non-blocking.
126     virtual double getParameterForMidi(double midiValue) const;
127 
128     // Sets the control parameterized value to v. Thread safe, non-blocking.
129     virtual void setParameter(double v);
130 
131     // Sets the control parameterized value to v. Thread safe, non-blocking.
132     virtual void setParameterFrom(double v, QObject* pSender = NULL);
133 
134     // Connects a Qt slot to a signal that is delivered when a new value change
135     // request arrives for this control.
136     // Qt::AutoConnection: Qt ensures that the signal slot is called from the
137     // thread where the receiving object was created
138     // You need to use Qt::DirectConnection for the engine objects, since the
139     // audio thread has no Qt event queue. But be a ware of race conditions in this case.
140     // ref: http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum
141     template <typename Receiver, typename Slot>
142     bool connectValueChangeRequest(Receiver receiver, Slot func,
143                                    Qt::ConnectionType type = Qt::AutoConnection) {
144         bool ret = false;
145         if (m_pControl) {
146           ret = m_pControl->connectValueChangeRequest(receiver, func, type);
147         }
148         return ret;
149     }
150 
151     // Installs a value-change request handler that ignores all sets.
152     void setReadOnly();
153 
154   signals:
155     void valueChanged(double);
156 
157   public:
158     // DEPRECATED: Called to set the control value from the controller
159     // subsystem.
160     virtual void setValueFromMidi(MidiOpCode o, double v);
161     virtual double getMidiParameter() const;
162 
163   protected:
164     // Key of the object
165     ConfigKey m_key;
166     QSharedPointer<ControlDoublePrivate> m_pControl;
167 
168   private slots:
169     void privateValueChanged(double value, QObject* pSetter);
170     void readOnlyHandler(double v);
171 
172   private:
173     ControlObject(ControlObject&&) = delete;
174     ControlObject(const ControlObject&) = delete;
175     ControlObject& operator=(ControlObject&&) = delete;
176     ControlObject& operator=(const ControlObject&) = delete;
177 
ignoreNops()178     inline bool ignoreNops() const {
179         return m_pControl ? m_pControl->ignoreNops() : true;
180     }
181 };
182