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 : class MIDIInputElementPC : public MIDIInputElement, 16 : public DoublyLinkable<MIDIInputElementPC> { 17 : public: 18 : /** 19 : * @brief Constructor. 20 : * @todo Documentation. 21 : */ 22 2 : MIDIInputElementPC(const MIDICNChannelAddress &address) 23 4 : : MIDIInputElement(address) { 24 : GUARD_LIST_LOCK; 25 2 : elements.append(this); 26 2 : } 27 : 28 : /** 29 : * @brief Destructor. 30 : * @todo Documentation. 31 : */ 32 2 : virtual ~MIDIInputElementPC() { 33 : GUARD_LIST_LOCK; 34 2 : elements.remove(this); 35 2 : } 36 : 37 0 : static void beginAll() { 38 : GUARD_LIST_LOCK; 39 0 : for (MIDIInputElementPC &el : elements) 40 0 : el.begin(); 41 0 : } 42 : 43 : /** 44 : * @brief Reset all MIDIInputElementPC elements to their 45 : * initial state. 46 : * 47 : * @see MIDIInputElementPC#reset 48 : */ 49 : static void resetAll() { 50 : GUARD_LIST_LOCK; 51 : for (MIDIInputElementPC &el : elements) 52 : el.reset(); 53 : } 54 : 55 : /** 56 : * @brief Update all MIDIInputElementPC elements. 57 : */ 58 0 : static void updateAll() { 59 : GUARD_LIST_LOCK; 60 0 : for (MIDIInputElementPC &el : elements) 61 0 : el.update(); 62 0 : } 63 : 64 : /** 65 : * @brief Update all MIDIInputElementPC elements with a new MIDI 66 : * message. 67 : * 68 : * @see MIDIInputElementPC#updateWith 69 : */ 70 0 : static void updateAllWith(const ChannelMessageMatcher &midimsg) { 71 0 : for (MIDIInputElementPC &e : elements) 72 0 : if (e.updateWith(midimsg)) { 73 0 : e.moveDown(); 74 0 : return; 75 : } 76 : // No mutex required: 77 : // e.moveDown may alter the list, but if it does, it always returns, 78 : // and we stop iterating, so it doesn't matter. 79 0 : } 80 : 81 : private: 82 : /// Program Change doesn't have an address, so the target consists of just 83 : /// the channel and the cable number. 84 : MIDICNChannelAddress 85 0 : getTarget(const ChannelMessageMatcher &midimsg) const override { 86 0 : return {0, Channel(midimsg.channel), midimsg.CN}; 87 : } 88 : 89 : /** 90 : * @brief Move down this element in the linked list of elements. 91 : * 92 : * This means that the element will be checked earlier on the next 93 : * iteration. 94 : */ 95 0 : void moveDown() { 96 : GUARD_LIST_LOCK; 97 0 : elements.moveDown(this); 98 0 : } 99 : 100 : static DoublyLinkedList<MIDIInputElementPC> elements; 101 : #ifdef ESP32 102 : static std::mutex mutex; 103 : #endif 104 : }; 105 : 106 : #undef GUARD_LIST_LOCK 107 : 108 : END_CS_NAMESPACE