Line data Source code
1 : #pragma once
2 :
3 : #include "BankableMIDIMatcherHelpers.hpp"
4 : #include "MIDIInputElement.hpp"
5 :
6 : BEGIN_CS_NAMESPACE
7 :
8 : /// @addtogroup MIDIInputMatchers
9 : /// @{
10 :
11 : // -------------------------------------------------------------------------- //
12 :
13 : /// Matcher for MIDI messages with 1 data byte, such as Channel Pressure
14 : /// and Program Change.
15 : struct OneByteMIDIMatcher {
16 3 : OneByteMIDIMatcher(MIDIChannelCable address) : address(address) {}
17 :
18 : struct Result {
19 : bool match;
20 : uint8_t value;
21 : };
22 :
23 4 : Result operator()(ChannelMessage m) {
24 4 : if (!MIDIChannelCable::matchSingle(m.getChannelCable(), address))
25 2 : return {false, 0};
26 2 : uint8_t value = m.data1;
27 2 : return {true, value};
28 : }
29 :
30 : MIDIChannelCable address;
31 : };
32 :
33 : // -------------------------------------------------------------------------- //
34 :
35 : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
36 : /// Change, Key Pressure (but not Pitch Bend). Matches a single address.
37 : struct TwoByteMIDIMatcher {
38 7 : TwoByteMIDIMatcher(MIDIAddress address) : address(address) {}
39 :
40 : struct Result {
41 : bool match;
42 : uint8_t value;
43 : };
44 :
45 16 : Result operator()(ChannelMessage m) {
46 16 : if (!MIDIAddress::matchSingle(m.getAddress(), address))
47 0 : return {false, 0};
48 : uint8_t value =
49 16 : m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
50 16 : return {true, value};
51 : }
52 :
53 : MIDIAddress address;
54 : };
55 :
56 : // -------------------------------------------------------------------------- //
57 :
58 : /// Matcher for MIDI Pitch Bend messages. Matches a single address.
59 : struct PitchBendMIDIMatcher {
60 : PitchBendMIDIMatcher(MIDIChannelCable address) : address(address) {}
61 :
62 : struct Result {
63 : bool match;
64 : uint16_t value;
65 : };
66 :
67 : Result operator()(ChannelMessage m) {
68 : if (!MIDIChannelCable::matchSingle(m.getChannelCable(), address))
69 : return {false, 0};
70 : uint16_t value = (m.data2 << 7) | m.data1;
71 : return {true, value};
72 : }
73 :
74 : MIDIChannelCable address;
75 : };
76 :
77 : // -------------------------------------------------------------------------- //
78 :
79 : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
80 : /// Change, Key Pressure (but not Pitch Bend). Matches ranges of addresses on a
81 : /// single channel and cable.
82 : struct TwoByteRangeMIDIMatcher {
83 17 : TwoByteRangeMIDIMatcher(MIDIAddress address, uint8_t length)
84 17 : : address(address), length(length) {}
85 :
86 : struct Result {
87 : bool match;
88 : uint8_t value;
89 : uint8_t index;
90 : };
91 :
92 96 : Result operator()(ChannelMessage m) {
93 96 : if (!MIDIAddress::matchAddressInRange(m.getAddress(), address, length))
94 2 : return {false, 0, 0};
95 : uint8_t value =
96 94 : m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
97 94 : uint8_t index = m.getData1() - address.getAddress();
98 94 : return {true, value, index};
99 : }
100 :
101 : MIDIAddress address;
102 : uint8_t length;
103 : };
104 :
105 : // -------------------------------------------------------------------------- //
106 :
107 : /// Matcher for MIDI messages with 1 data byte, such as Channel Pressure
108 : /// and Program Change. Matches a single address over multiple banks.
109 : template <uint8_t BankSize>
110 : struct BankableOneByteMIDIMatcher {
111 : BankableOneByteMIDIMatcher(
112 : BankConfig<BankSize, BankType::ChangeChannel> config,
113 : MIDIChannelCable address)
114 : : config(config), address(address) {}
115 :
116 : struct Result {
117 : bool match;
118 : uint8_t value;
119 : uint8_t bankIndex;
120 : };
121 :
122 : Result operator()(ChannelMessage m) {
123 : using BankableMIDIMatcherHelpers::getBankIndex;
124 : using BankableMIDIMatcherHelpers::matchBankable;
125 : if (!matchBankable(m.getChannelCable(), address, config))
126 : return {false, 0, 0};
127 : uint8_t value = m.data1;
128 : uint8_t bankIndex = getBankIndex(m.getChannelCable(), address, config);
129 : return {true, value, bankIndex};
130 : }
131 :
132 : Bank<BankSize> &getBank() { return config.bank; }
133 : const Bank<BankSize> &getBank() const { return config.bank; }
134 : BankType getBankType() const { return config.type; }
135 : static constexpr setting_t getBankSize() { return BankSize; }
136 :
137 : /// Get the current bank setting.
138 : /// @see @ref Bank<N>::getSelection()
139 : setting_t getSelection() const { return getBank().getSelection(); }
140 :
141 : BaseBankConfig<BankSize> config;
142 : MIDIChannelCable address;
143 : };
144 :
145 : // -------------------------------------------------------------------------- //
146 :
147 : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
148 : /// Change, Key Pressure. Matches a single address over multiple banks.
149 : template <uint8_t BankSize>
150 : struct BankableTwoByteMIDIMatcher {
151 6 : BankableTwoByteMIDIMatcher(BankConfig<BankSize> config, MIDIAddress address)
152 6 : : config(config), address(address) {}
153 :
154 : struct Result {
155 : bool match;
156 : uint8_t value;
157 : uint8_t bankIndex;
158 : };
159 :
160 11 : Result operator()(ChannelMessage m) {
161 : using BankableMIDIMatcherHelpers::getBankIndex;
162 : using BankableMIDIMatcherHelpers::matchBankable;
163 11 : if (!matchBankable(m.getAddress(), address, config))
164 0 : return {false, 0, 0};
165 11 : uint8_t value =
166 20 : m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
167 11 : uint8_t bankIndex = getBankIndex(m.getAddress(), address, config);
168 11 : return {true, value, bankIndex};
169 : }
170 :
171 12 : Bank<BankSize> &getBank() { return config.bank; }
172 55 : const Bank<BankSize> &getBank() const { return config.bank; }
173 : BankType getBankType() const { return config.type; }
174 : static constexpr setting_t getBankSize() { return BankSize; }
175 :
176 : /// Get the current bank setting.
177 : /// @see @ref Bank<N>::getSelection()
178 55 : setting_t getSelection() const { return getBank().getSelection(); }
179 :
180 : BaseBankConfig<BankSize> config;
181 : MIDIAddress address;
182 : };
183 :
184 : // -------------------------------------------------------------------------- //
185 :
186 : /// Matcher for MIDI Pitch Bend messages. Matches a single address over multiple
187 : /// banks.
188 : template <uint8_t BankSize>
189 : struct BankablePitchBendMIDIMatcher {
190 : BankablePitchBendMIDIMatcher(
191 : BankConfig<BankSize, BankType::ChangeChannel> config,
192 : MIDIChannelCable address)
193 : : config(config), address(address) {}
194 :
195 : struct Result {
196 : bool match;
197 : uint16_t value;
198 : uint8_t bankIndex;
199 : };
200 :
201 : Result operator()(ChannelMessage m) {
202 : using BankableMIDIMatcherHelpers::getBankIndex;
203 : using BankableMIDIMatcherHelpers::matchBankable;
204 : if (!matchBankable(m.getChannelCable(), address, config))
205 : return {false, 0, 0};
206 : uint16_t value = (m.data2 << 7) | m.data1;
207 : uint8_t bankIndex = getBankIndex(m.getChannelCable(), address, config);
208 : return {true, value, bankIndex};
209 : }
210 :
211 : Bank<BankSize> &getBank() { return config.bank; }
212 : const Bank<BankSize> &getBank() const { return config.bank; }
213 : BankType getBankType() const { return config.type; }
214 : static constexpr setting_t getBankSize() { return BankSize; }
215 :
216 : /// Get the current bank setting.
217 : /// @see @ref Bank<N>::getSelection()
218 : setting_t getSelection() const { return getBank().getSelection(); }
219 :
220 : BaseBankConfig<BankSize> config;
221 : MIDIChannelCable address;
222 : };
223 :
224 : // -------------------------------------------------------------------------- //
225 :
226 : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
227 : /// Change, Key Pressure. Matches a range of addresses over multiple banks.
228 : template <uint8_t BankSize>
229 : struct BankableTwoByteRangeMIDIMatcher {
230 : /// Constructor.
231 6 : BankableTwoByteRangeMIDIMatcher(BankConfig<BankSize> config,
232 : MIDIAddress address, uint8_t length)
233 6 : : config(config), address(address), length(length) {}
234 :
235 : struct Result {
236 : bool match;
237 : uint8_t value;
238 : uint8_t bankIndex;
239 : uint8_t index;
240 : };
241 :
242 30 : Result operator()(ChannelMessage m) {
243 : using BankableMIDIMatcherHelpers::getBankIndex;
244 : using BankableMIDIMatcherHelpers::getRangeIndex;
245 : using BankableMIDIMatcherHelpers::matchBankableInRange;
246 30 : if (!matchBankableInRange(m.getAddress(), address, config, length))
247 18 : return {false, 0, 0, 0};
248 12 : uint8_t value = m.getMessageType() == m.NoteOff ? 0 : m.getData2();
249 12 : uint8_t bankIndex = getBankIndex(m.getAddress(), address, config);
250 12 : uint8_t rangeIndex = getRangeIndex(m.getAddress(), address, config);
251 12 : return {true, value, bankIndex, rangeIndex};
252 : }
253 :
254 12 : Bank<BankSize> &getBank() { return config.bank; }
255 : const Bank<BankSize> &getBank() const { return config.bank; }
256 : static constexpr setting_t getBankSize() { return BankSize; }
257 :
258 : /// Get the current bank setting.
259 : /// @see @ref Bank<N>::getSelection()
260 180 : setting_t getSelection() const { return config.bank.getSelection(); }
261 :
262 : BaseBankConfig<BankSize> config;
263 : MIDIAddress address;
264 : uint8_t length;
265 : };
266 :
267 : // -------------------------------------------------------------------------- //
268 :
269 : /// @}
270 :
271 : END_CS_NAMESPACE
|