Line data Source code
1 : /* ✔ */ 2 : 3 : #pragma once 4 : 5 : #include "ChannelMessageMatcher.hpp" 6 : #include <Def/MIDIAddress.hpp> 7 : 8 : BEGIN_CS_NAMESPACE 9 : 10 : /** 11 : * @brief A class for objects that listen for incoming MIDI events. 12 : * 13 : * They can either update some kind of display, or they can just save the state. 14 : */ 15 : class MIDIInputElement { 16 : protected: 17 : MIDIInputElement() {} // not used, only for virtual inheritance 18 : /** 19 : * @brief Create a new MIDIInputElement that listens on the given address. 20 : * 21 : * @param address 22 : * The MIDI address to listen to. 23 : */ 24 44 : MIDIInputElement(const MIDIAddress &address) : address(address) {} 25 : 26 : public: 27 44 : virtual ~MIDIInputElement() = default; 28 : 29 : /// Initialize the input element. 30 0 : virtual void begin() {} 31 : 32 : /// Reset the input element to its initial state. 33 0 : virtual void reset() {} 34 : 35 : /// Update the value of the input element. Used for decaying VU meters etc. 36 0 : virtual void update() {} 37 : 38 : /// Receive a new MIDI message and update the internal state. 39 129 : bool updateWith(const ChannelMessageMatcher &midimsg) { 40 129 : MIDIAddress target = getTarget(midimsg); 41 129 : if (!this->match(target)) 42 12 : return false; 43 117 : DEBUGFN(F("MIDI message matches")); 44 117 : if (!updateImpl(midimsg, target)) 45 0 : return false; 46 117 : DEBUGFN(F("Updated")); 47 117 : return true; 48 129 : } 49 : 50 : private: 51 : /// Update the internal state with the new MIDI message. 52 : virtual bool updateImpl(const ChannelMessageMatcher &midimsg, 53 : const MIDIAddress &target) = 0; 54 : 55 : /** 56 : * @brief Extract the target address from a MIDI message. 57 : * @note This base version of the function is only valid for messages 58 : * that use data1 as an address (i.e. Note On, Note Off, Polyphonic 59 : * Key Pressure and Control Change), because it assumes that the 60 : * target address consists of the address (data 1), the MIDI 61 : * channel and the cable number. 62 : */ 63 110 : virtual MIDIAddress getTarget(const ChannelMessageMatcher &midimsg) const { 64 110 : return { 65 110 : int8_t(midimsg.data1), 66 110 : Channel(midimsg.channel), 67 110 : Cable(midimsg.CN), 68 : }; 69 : } 70 : 71 : /** 72 : * @brief Check if the address of the incoming MIDI message matches an 73 : * address of this element. 74 : * @note This base version of the function is only valid for non-Bankable 75 : * MIDI input elements, it only matches if the address is equal to 76 : * the address of this element. 77 : */ 78 12 : virtual bool match(const MIDIAddress &target) const { 79 12 : return MIDIAddress::matchSingle(this->address, target); 80 : } 81 : 82 : protected: 83 : const MIDIAddress address; 84 : }; 85 : 86 : END_CS_NAMESPACE