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