Line data Source code
1 : #pragma once
2 :
3 : #include "MIDIInputElementMatchers.hpp"
4 :
5 : BEGIN_CS_NAMESPACE
6 :
7 : // -------------------------------------------------------------------------- //
8 :
9 : /// Generic base class for classes that listen for MIDI Note, Control Change and
10 : /// Key Pressure events on a range of addresses and save their values.
11 : ///
12 : /// @tparam Type
13 : /// The type of MIDI messages to listen for:
14 : /// - @ref MIDIMessageType::NoteOn
15 : /// - @ref MIDIMessageType::ControlChange
16 : /// - @ref MIDIMessageType::KeyPressure
17 : /// @tparam RangeLen
18 : /// The length of the range of addresses to listen to.
19 : template <MIDIMessageType Type, uint8_t RangeLen>
20 : class NoteCCKPRange
21 : : public MatchingMIDIInputElement<Type, TwoByteRangeMIDIMatcher> {
22 : public:
23 : using Matcher = TwoByteRangeMIDIMatcher;
24 :
25 : /// @param address
26 : /// The first address of the range to listen to.
27 1 : NoteCCKPRange(MIDIAddress address)
28 1 : : MatchingMIDIInputElement<Type, Matcher>({address, RangeLen}) {}
29 :
30 : private:
31 4 : bool handleUpdateImpl(typename Matcher::Result match) {
32 4 : bool newdirty = values[match.index] != match.value;
33 4 : values[match.index] = match.value;
34 4 : return newdirty;
35 : }
36 :
37 4 : void handleUpdate(typename Matcher::Result match) override {
38 4 : dirty |= handleUpdateImpl(match);
39 4 : }
40 :
41 : public:
42 : /// @name Data access
43 : /// @{
44 :
45 : /// Get the most recent MIDI value that was received for the given index
46 : /// in the range.
47 10 : uint8_t getValue(uint8_t index) const { return values[index]; }
48 :
49 : /// @}
50 :
51 : /// Reset all values to zero.
52 0 : void reset() override {
53 0 : values = {{}};
54 0 : dirty = true;
55 0 : }
56 :
57 : /// @name Detecting changes
58 : /// @{
59 :
60 : /// Check if the value was updated since the last time the dirty flag was
61 : /// cleared.
62 6 : bool getDirty() const { return dirty; }
63 : /// Clear the dirty flag.
64 4 : void clearDirty() { dirty = false; }
65 :
66 : /// @}
67 :
68 : private:
69 : AH::Array<uint8_t, RangeLen> values = {{}};
70 : bool dirty = true;
71 : };
72 :
73 : /// Class that listen for MIDI Note events on a range of addresses and
74 : /// saves their values.
75 : /// @ingroup MIDIInputElements
76 : template <uint8_t RangeLen>
77 : using NoteRange = NoteCCKPRange<MIDIMessageType::NoteOn, RangeLen>;
78 :
79 : /// Class that listen for MIDI Control Change events on a range of addresses and
80 : /// saves their values.
81 : /// @ingroup MIDIInputElements
82 : template <uint8_t RangeLen>
83 : using CCRange = NoteCCKPRange<MIDIMessageType::ControlChange, RangeLen>;
84 :
85 : /// Class that listen for MIDI Key Pressure events on a range of addresses and
86 : /// saves their values.
87 : /// @ingroup MIDIInputElements
88 : template <uint8_t RangeLen>
89 : using KPRange = NoteCCKPRange<MIDIMessageType::KeyPressure, RangeLen>;
90 :
91 : // -------------------------------------------------------------------------- //
92 :
93 : namespace Bankable {
94 :
95 : /// Generic base class for classes that listen for MIDI Note, Control Change and
96 : /// Key Pressure events on a range of addresses and save their values. This
97 : /// version listens for the range over different banks.
98 : ///
99 : /// @tparam Type
100 : /// The type of MIDI messages to listen for:
101 : /// - @ref MIDIMessageType::NoteOn
102 : /// - @ref MIDIMessageType::ControlChange
103 : /// - @ref MIDIMessageType::KeyPressure
104 : /// @tparam BankSize
105 : /// The number of banks.
106 : /// @tparam RangeLen
107 : /// The length of the range of addresses to listen to.
108 : template <MIDIMessageType Type, uint8_t BankSize, uint8_t RangeLen>
109 : class NoteCCKPRange : public BankableMatchingMIDIInputElement<
110 : Type, BankableTwoByteRangeMIDIMatcher<BankSize>> {
111 : public:
112 : using Matcher = BankableTwoByteRangeMIDIMatcher<BankSize>;
113 :
114 : /// @param config
115 : /// The bank configuration to use.
116 : /// @param address
117 : /// The base address to listen to.
118 6 : NoteCCKPRange(BankConfig<BankSize> config, MIDIAddress address)
119 : : BankableMatchingMIDIInputElement<Type, Matcher>(
120 6 : {config, address, RangeLen}) {}
121 :
122 : protected:
123 12 : bool handleUpdateImpl(typename Matcher::Result match) {
124 24 : bool newdirty = values[match.bankIndex][match.index] != match.value &&
125 12 : match.bankIndex == this->getActiveBank();
126 : // Only mark dirty if the value of the active bank changed
127 12 : values[match.bankIndex][match.index] = match.value;
128 12 : return newdirty;
129 : }
130 :
131 12 : void handleUpdate(typename Matcher::Result match) override {
132 12 : dirty |= handleUpdateImpl(match);
133 12 : }
134 :
135 : public:
136 : /// @name Data access
137 : /// @{
138 :
139 : /// Get the most recent MIDI value that was received for the active bank.
140 168 : uint8_t getValue(uint8_t index) const {
141 168 : return values[this->getActiveBank()][index];
142 : }
143 : /// Get the most recent MIDI value that was received for the given bank.
144 156 : uint8_t getValue(uint8_t bank, uint8_t index) const {
145 156 : return values[bank][index];
146 : }
147 :
148 : /// @}
149 :
150 : /// Reset all values to zero.
151 0 : void reset() override {
152 0 : values = {{{}}};
153 0 : dirty = true;
154 0 : }
155 :
156 : /// @name Detecting changes
157 : /// @{
158 :
159 : /// Check if the value was updated since the last time the dirty flag was
160 : /// cleared.
161 42 : bool getDirty() const { return dirty; }
162 : /// Clear the dirty flag.
163 22 : void clearDirty() { dirty = false; }
164 :
165 : /// @}
166 :
167 : protected:
168 44 : void onBankSettingChange() override { dirty = true; }
169 :
170 : private:
171 : AH::Array2D<uint8_t, BankSize, RangeLen> values = {{{}}};
172 :
173 : protected:
174 : bool dirty = true;
175 : };
176 :
177 : /// Class that listens for MIDI Note events on a range of addresses and
178 : /// saves their values. This version listens for the range over different banks.
179 : /// @ingroup BankableMIDIInputElements
180 : template <uint8_t BankSize, uint8_t RangeLen>
181 : using NoteRange = NoteCCKPRange<MIDIMessageType::NoteOn, BankSize, RangeLen>;
182 :
183 : /// Class that listens for MIDI Control Change events on a range of addresses
184 : /// and saves their values. This version listens for the range over different
185 : /// banks.
186 : /// @ingroup BankableMIDIInputElements
187 : template <uint8_t BankSize, uint8_t RangeLen>
188 : using CCRange =
189 : NoteCCKPRange<MIDIMessageType::ControlChange, BankSize, RangeLen>;
190 :
191 : /// Class that listens for MIDI Key Pressure events on a range of addresses and
192 : /// saves their values. This version listens for the range over different banks.
193 : /// @ingroup BankableMIDIInputElements
194 : template <uint8_t BankSize, uint8_t RangeLen>
195 : using KPRange = NoteCCKPRange<MIDIMessageType::KeyPressure, BankSize, RangeLen>;
196 :
197 : } // namespace Bankable
198 :
199 : END_CS_NAMESPACE
|