Line data Source code
1 : #pragma once 2 : 3 : #include "MIDIInputElement.hpp" 4 : #include <AH/Containers/LinkedList.hpp> 5 : 6 : #if defined(ESP32) 7 : #include <mutex> 8 : #define GUARD_LIST_LOCK std::lock_guard<std::mutex> _guard(mutex) 9 : #else 10 : #define GUARD_LIST_LOCK 11 : #endif 12 : 13 : BEGIN_CS_NAMESPACE 14 : 15 : /** 16 : * @brief Class for objects that listen for incoming MIDI SysEx events. 17 : * 18 : * @ingroup MIDIInputElements 19 : */ 20 : class MIDIInputElementSysEx : public DoublyLinkable<MIDIInputElementSysEx> { 21 : protected: 22 : /** 23 : * @brief Constructor. 24 : * @todo Documentation. 25 : */ 26 12 : MIDIInputElementSysEx(uint8_t CN = 0) 27 24 : : CN{CN} { 28 : GUARD_LIST_LOCK; 29 12 : elements.append(this); 30 12 : } 31 : 32 : public: 33 : /** 34 : * @brief Destructor. 35 : * @todo Documentation. 36 : */ 37 12 : virtual ~MIDIInputElementSysEx() { 38 : GUARD_LIST_LOCK; 39 12 : elements.remove(this); 40 12 : } 41 : 42 : /// Initialize the input element. 43 0 : virtual void begin() {} 44 : 45 : /// Reset the input element to its initial state. 46 0 : virtual void reset() {} 47 : 48 : /// Update the value of the input element. Used for decaying VU meters etc. 49 0 : virtual void update() {} 50 : 51 : /** 52 : * @brief Initialize all MIDIInputElementSysEx elements. 53 : * 54 : * @see MIDIInputElementSysEx#begin 55 : */ 56 0 : static void beginAll() { 57 : GUARD_LIST_LOCK; 58 0 : for (MIDIInputElementSysEx &e : elements) 59 0 : e.begin(); 60 0 : } 61 : 62 : /** 63 : * @brief Update all MIDIInputElementSysEx elements. 64 : * 65 : * @see MIDIInputElementSysEx#update 66 : */ 67 0 : static void updateAll() { 68 : GUARD_LIST_LOCK; 69 0 : for (MIDIInputElementSysEx &e : elements) 70 0 : e.update(); 71 0 : } 72 : 73 : /** 74 : * @brief Reset all MIDIInputElementSysEx elements to their initial state. 75 : * 76 : * @see MIDIInputElementSysEx#reset 77 : */ 78 : static void resetAll() { 79 : GUARD_LIST_LOCK; 80 : for (MIDIInputElementSysEx &e : elements) 81 : e.reset(); 82 : } 83 : 84 : /** 85 : * @brief Update all MIDIInputElementSysEx elements with a new MIDI 86 : * message. 87 : * 88 : * @see MIDIInputElementSysEx#updateWith 89 : */ 90 12 : static void updateAllWith(SysExMessage midimsg) { 91 16 : for (MIDIInputElementSysEx &e : elements) 92 15 : if (e.updateWith(midimsg)) { 93 11 : e.moveDown(); 94 11 : return; 95 : } 96 : // No mutex required: 97 : // e.moveDown may alter the list, but if it does, it always returns, 98 : // and we stop iterating, so it doesn't matter. 99 12 : } 100 : 101 : private: 102 : /// @todo Documentation. 103 15 : bool updateWith(SysExMessage midimsg) { 104 15 : return midimsg.CN == this->CN && updateImpl(midimsg); 105 : } 106 : 107 : /// @todo Documentation. 108 : virtual bool updateImpl(SysExMessage midimsg) = 0; 109 : 110 : /** 111 : * @brief Move down this element in the linked list of elements. 112 : * 113 : * This means that the element will be checked earlier on the next 114 : * iteration. 115 : */ 116 11 : void moveDown() { 117 : GUARD_LIST_LOCK; 118 11 : elements.moveDown(this); 119 11 : } 120 : 121 : uint8_t CN; 122 : 123 : static DoublyLinkedList<MIDIInputElementSysEx> elements; 124 : #ifdef ESP32 125 : static std::mutex mutex; 126 : #endif 127 : }; 128 : 129 : #undef GUARD_LIST_LOCK 130 : 131 : END_CS_NAMESPACE