Line data Source code
1 : #pragma once 2 : 3 : #include <AH/Containers/LinkedList.hpp> 4 : #include <MIDI_Inputs/MIDIInputElement.hpp> 5 : 6 : 7 : #if defined(ESP32) 8 : #include <mutex> 9 : #define GUARD_LIST_LOCK std::lock_guard<std::mutex> _guard(mutex) 10 : #else 11 : #define GUARD_LIST_LOCK 12 : #endif 13 : 14 : BEGIN_CS_NAMESPACE 15 : 16 : /** 17 : * @brief Class for objects that listen for incoming MIDI Controller Change 18 : * events. 19 : * 20 : * All instances are added to a linked list that can be traversed to update 21 : * all of them when a new MIDI CC event is received. 22 : */ 23 : class MIDIInputElementCC : public MIDIInputElement, 24 : public DoublyLinkable<MIDIInputElementCC> { 25 : public: 26 : /** 27 : * @brief Create a new MIDIInputElementCC that listens on the given 28 : * address. 29 : * 30 : * Add the element to the linked list. 31 : * 32 : * @param address 33 : * The MIDI address to listen to. (Controller number [0, 119], 34 : * Channel [1, 16], Cable Number [0, 15].) 35 : */ 36 18 : MIDIInputElementCC(const MIDICNChannelAddress &address) 37 36 : : MIDIInputElement{address} { 38 : GUARD_LIST_LOCK; 39 18 : elements.append(this); 40 18 : } 41 : 42 : /// Destructor: delete from the linked list. 43 18 : virtual ~MIDIInputElementCC() { 44 : GUARD_LIST_LOCK; 45 18 : elements.remove(this); 46 18 : } 47 : 48 : /// Initialize all MIDIInputElementCC elements. 49 : /// @see MIDIInputElementCC#begin 50 1 : static void beginAll() { 51 : GUARD_LIST_LOCK; 52 2 : for (MIDIInputElementCC &e : elements) 53 1 : e.begin(); 54 1 : } 55 : 56 : /// Update all MIDIInputElementCC elements. 57 : /// @see MIDIInputElementCC#update 58 0 : static void updateAll() { 59 : GUARD_LIST_LOCK; 60 0 : for (MIDIInputElementCC &e : elements) 61 0 : e.update(); 62 0 : } 63 : 64 : /// Reset all MIDIInputElementCC elements to their initial state. 65 : /// @see MIDIInputElementCC::reset 66 0 : static void resetAll() { 67 : GUARD_LIST_LOCK; 68 0 : for (MIDIInputElementCC &e : elements) 69 0 : e.reset(); 70 0 : } 71 : 72 : /// Update all MIDIInputElementCC elements with a new MIDI message. 73 : /// @see MIDIInputElementCC#updateWith 74 6 : static void updateAllWith(const ChannelMessageMatcher &midimsg) { 75 6 : for (MIDIInputElementCC &e : elements) 76 6 : if (e.updateWith(midimsg)) { 77 6 : e.moveDown(); 78 6 : return; 79 : } 80 : // No mutex required: 81 : // e.moveDown may alter the list, but if it does, it always returns, 82 : // and we stop iterating, so it doesn't matter. 83 6 : } 84 : 85 : private: 86 : /** 87 : * @brief Move down this element in the linked list of elements. 88 : * 89 : * This means that the element will be checked earlier on the next 90 : * iteration. 91 : */ 92 6 : void moveDown() { 93 : GUARD_LIST_LOCK; 94 6 : elements.moveDown(this); 95 6 : } 96 : 97 : static DoublyLinkedList<MIDIInputElementCC> elements; 98 : #ifdef ESP32 99 : static std::mutex mutex; 100 : #endif 101 : }; 102 : 103 : #undef GUARD_LIST_LOCK 104 : 105 : END_CS_NAMESPACE