summaryrefslogtreecommitdiffstats
path: root/src/control/controlbehavior.h
blob: 1075cf0bea307d45017e2b104211ef57810e5d5f (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
#pragma once

#include <QTimer>
#include <QScopedPointer>

#include "controllers/midi/midimessage.h"

class ControlDoublePrivate;

// A linear 0 .. 1 control without Midi representation
class ControlNumericBehavior {
  public:
    virtual ~ControlNumericBehavior() { };

    // this may change the dValue in place before it is adopted
    // Returns false to reject the new value entirely
    virtual bool setFilter(double* dValue);

    // returns the normalized parameter range 0..1
    virtual double valueToParameter(double dValue);
    // returns the normalized parameter range 0..1
    virtual double midiToParameter(double midiValue);
    // returns the scaled user visible value
    virtual double parameterToValue(double dParam);
    // returns the midi range parameter 0..127
    virtual double valueToMidiParameter(double dValue);

    virtual void setValueFromMidi(
            MidiOpCode o, double dParam, ControlDoublePrivate* pControl);
};

// ControlEncoderBehavior passes the midi value directly to the internal parameter value.  It's
// useful for selector knobs that pass +1 in one direction and -1 in the other.
class ControlEncoderBehavior : public ControlNumericBehavior {
  public:
    ControlEncoderBehavior() {}
    double midiToParameter(double midiValue) override;
    double valueToMidiParameter(double dValue) override;
};

class ControlPotmeterBehavior : public ControlNumericBehavior {
  public:
    ControlPotmeterBehavior(double dMinValue, double dMaxValue,
                            bool allowOutOfBounds);

    bool setFilter(double* dValue) override;
    double valueToParameter(double dValue) override;
    double midiToParameter(double midiValue) override;
    double parameterToValue(double dParam) override;
    double valueToMidiParameter(double dValue) override;

  protected:
    double m_dMinValue;
    double m_dMaxValue;
    double m_dValueRange;
    bool m_bAllowOutOfBounds;
};

class ControlLogPotmeterBehavior : public ControlPotmeterBehavior {
  public:
    ControlLogPotmeterBehavior(double dMinValue, double dMaxValue, double minDB);

    double valueToParameter(double dValue) override;
    double parameterToValue(double dParam) override;

  protected:
    double m_minDB;
    double m_minOffset;
};

class ControlLogInvPotmeterBehavior : public ControlLogPotmeterBehavior {
  public:
    ControlLogInvPotmeterBehavior(double dMinValue, double dMaxValue, double minDB);

    double valueToParameter(double dValue) override;
    double parameterToValue(double dParam) override;
};

class ControlLinPotmeterBehavior : public ControlPotmeterBehavior {
  public:
    ControlLinPotmeterBehavior(
            double dMinValue, double dMaxValue, bool allowOutOfBounds);
};

class ControlLinInvPotmeterBehavior : public ControlPotmeterBehavior {
  public:
    ControlLinInvPotmeterBehavior(
            double dMinValue, double dMaxValue, bool allowOutOfBounds);
    double valueToParameter(double dValue) override;
    double parameterToValue(double dParam) override;
};

class ControlAudioTaperPotBehavior : public ControlPotmeterBehavior {
  public:
    ControlAudioTaperPotBehavior(double minDB, double maxDB,
                                 double neutralParameter);

    double valueToParameter(double dValue) override;
    double parameterToValue(double dParam) override;
    double midiToParameter(double midiValue) override;
    double valueToMidiParameter(double dValue) override;
    void setValueFromMidi(
            MidiOpCode o, double dParam, ControlDoublePrivate* pControl)
                    override;

  protected:
    // a knob position between 0 and 1 where the gain is 1 (0dB)
    double m_neutralParameter;
    // the Start value of the pure db scale it cranked to -Infinity by the
    // linear part of the AudioTaperPot
    double m_minDB;
    // maxDB is the upper gain Value
    double m_maxDB;
    // offset at knob position 0 (Parameter = 0) to reach -Infinity
    double m_offset;
    // ensures that the neutral position on a integer midi value
    // This value is subtracted from the Midi value at neutral position
    // and is always < 1
    double m_midiCorrection;
};

class ControlTTRotaryBehavior : public ControlNumericBehavior {
  public:
    double valueToParameter(double dValue) override;
    double parameterToValue(double dParam) override;
};

class ControlPushButtonBehavior : public ControlNumericBehavior {
  public:
    static const int kPowerWindowTimeMillis;
    static const int kLongPressLatchingTimeMillis;

    // TODO(XXX) Duplicated from ControlPushButton. It's complicated and
    // annoying to share them so I just copied them.
    enum ButtonMode {
         PUSH = 0,
         TOGGLE,
         POWERWINDOW,
         LONGPRESSLATCHING,
         TRIGGER
    };

    ControlPushButtonBehavior(ButtonMode buttonMode, int iNumStates);
    void setValueFromMidi(
            MidiOpCode o, double dParam, ControlDoublePrivate* pControl)
                override;

  private:
    // We create many hundreds of push buttons at Mixxx startup and most of them
    // never use their timer. Delay creation of the timer until it's needed.
    QTimer* getTimer() {
        if (m_pushTimer.isNull()) {
            m_pushTimer.reset(new QTimer());
        }
        return m_pushTimer.data();
    }
    ButtonMode m_buttonMode;
    int m_iNumStates;
    QScopedPointer<QTimer> m_pushTimer;
};