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