summaryrefslogtreecommitdiffstats
path: root/src/control/controlobject.h
blob: d36b2add69bec9c12c95c03abf9834da0c2ebb00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#pragma once

#include <QObject>
#include <QEvent>

#include "preferences/usersettings.h"
#include "controllers/midi/midimessage.h"
#include "control/control.h"

class ControlObject : public QObject {
    Q_OBJECT
  public:
    ControlObject();

    // bIgnoreNops: Don't emit a signal if the CO is set to its current value.
    // bTrack: Record statistics about this control.
    // bPersist: Store value on exit, load on startup.
    // defaultValue: default value of CO. If CO is persistent and there is no valid
    //               value found in the config, this is also the initial value.
    ControlObject(const ConfigKey& key,
            bool bIgnoreNops = true,
            bool bTrack = false,
            bool bPersist = false,
            double defaultValue = 0.0);
    virtual ~ControlObject();

    // Returns a pointer to the ControlObject matching the given ConfigKey
    static ControlObject* getControl(const ConfigKey& key, ControlFlags flags = ControlFlag::None);
    static ControlObject* getControl(const QString& group,
            const QString& item,
            ControlFlags flags = ControlFlag::None) {
        ConfigKey key(group, item);
        return getControl(key, flags);
    }

    QString name() const {
        return m_pControl ?  m_pControl->name() : QString();
    }

    void setName(const QString& name) {
        if (m_pControl) {
            m_pControl->setName(name);
        }
    }

    const QString description() const {
        return m_pControl ?  m_pControl->description() : QString();
    }

    void setDescription(const QString& description) {
        if (m_pControl) {
            m_pControl->setDescription(description);
        }
    }

    void setKbdRepeatable(bool enable) {
        if (m_pControl) {
            m_pControl->setKbdRepeatable(enable);
        }
    }

    bool getKbdRepeatable() const {
        return m_pControl ? m_pControl->getKbdRepeatable() : false;
    }

    // Return the key of the object
    inline ConfigKey getKey() const {
        return m_key;
    }

    // Returns the value of the ControlObject
    inline double get() const {
        return m_pControl ? m_pControl->get() : 0.0;
    }

    // Returns the bool interpretation of the ControlObject
    inline bool toBool() const {
        return get() > 0.0;
    }

    // Instantly returns the value of the ControlObject
    static double get(const ConfigKey& key);

    /// Returns the boolean interpretation of the ControlObject's value.
    static bool toBool(const ConfigKey& key) {
        return ControlObject::get(key) > 0;
    }

    // Sets the ControlObject value. May require confirmation by owner.
    inline void set(double value) {
        if (m_pControl) {
            m_pControl->set(value, this);
        }
    }

    // Sets the ControlObject value and confirms it.
    inline void setAndConfirm(double value) {
        if (m_pControl) {
            m_pControl->setAndConfirm(value, this);
        }
    }

    // Forces the control to 'value', regardless of whether it has a change
    // request handler attached (identical to setAndConfirm).
    inline void forceSet(double value) {
        setAndConfirm(value);
    }

    // Instantly sets the value of the ControlObject
    static void set(const ConfigKey& key, const double& value);

    // Sets the default value
    inline void reset() {
        if (m_pControl) {
            m_pControl->reset();
        }
    }

    inline void setDefaultValue(double dValue) {
        if (m_pControl) {
            m_pControl->setDefaultValue(dValue);
        }
    }
    inline double defaultValue() const {
        return m_pControl ? m_pControl->defaultValue() : 0.0;
    }

    // Returns the parameterized value of the object. Thread safe, non-blocking.
    virtual double getParameter() const;

    // Returns the parameterized value of the object. Thread safe, non-blocking.
    virtual double getParameterForValue(double value) const;

    // Returns the parameterized value of the object. Thread safe, non-blocking.
    virtual double getParameterForMidi(double midiValue) const;

    // Sets the control parameterized value to v. Thread safe, non-blocking.
    virtual void setParameter(double v);

    // Sets the control parameterized value to v. Thread safe, non-blocking.
    virtual void setParameterFrom(double v, QObject* pSender = NULL);

    // Connects a Qt slot to a signal that is delivered when a new value change
    // request arrives for this control.
    // Qt::AutoConnection: Qt ensures that the signal slot is called from the
    // thread where the receiving object was created
    // You need to use Qt::DirectConnection for the engine objects, since the
    // audio thread has no Qt event queue. But be a ware of race conditions in this case.
    // ref: http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum
    template <typename Receiver, typename Slot>
    bool connectValueChangeRequest(Receiver receiver, Slot func,
                                   Qt::ConnectionType type = Qt::AutoConnection) {
        bool ret = false;
        if (m_pControl) {
          ret = m_pControl->connectValueChangeRequest(receiver, func, type);
        }
        return ret;
    }

    // Installs a value-change request handler that ignores all sets.
    void setReadOnly();

  signals:
    void valueChanged(double);

  public:
    // DEPRECATED: Called to set the control value from the controller
    // subsystem.
    virtual void setValueFromMidi(MidiOpCode o, double v);
    virtual double getMidiParameter() const;

  protected:
    // Key of the object
    ConfigKey m_key;
    QSharedPointer<ControlDoublePrivate> m_pControl;

  private slots:
    void privateValueChanged(double value, QObject* pSetter);
    void readOnlyHandler(double v);

  private:
    ControlObject(ControlObject&&) = delete;
    ControlObject(const ControlObject&) = delete;
    ControlObject& operator=(ControlObject&&) = delete;
    ControlObject& operator=(const ControlObject&) = delete;

    inline bool ignoreNops() const {
        return m_pControl ? m_pControl->ignoreNops() : true;
    }
};