Line data Source code
1 : /* ✔ */ 2 : 3 : #pragma once 4 : 5 : #include <AH/Hardware/Button.hpp> 6 : #include <Def/Def.hpp> 7 : #include <MIDI_Outputs/Abstract/MIDIOutputElement.hpp> 8 : 9 : BEGIN_CS_NAMESPACE 10 : 11 : /** 12 : * @brief A class for momentary buttons and switches that send MIDI events. 13 : * 14 : * The button is debounced, and the button is latched (press once to enable, 15 : * press again to disable) (toggle). 16 : * 17 : * @see Button 18 : */ 19 : template <class Sender> 20 : class MIDIButtonLatched : public MIDIOutputElement { 21 : protected: 22 : /** 23 : * @brief Create a new MIDIButtonLatched object on the given pin and 24 : * address. 25 : * 26 : * @param pin 27 : * The digital input pin to read from. 28 : * The internal pull-up resistor will be enabled. 29 : * @param address 30 : * The MIDI address to send to. 31 : * @param sender 32 : * The MIDI sender to use. 33 : */ 34 2 : MIDIButtonLatched(pin_t pin, MIDIAddress address, const Sender &sender) 35 2 : : button(pin), address(address), sender(sender) {} 36 : 37 : public: 38 0 : void begin() final override { button.begin(); } 39 0 : void update() final override { 40 0 : AH::Button::State state = button.update(); 41 0 : if (state == AH::Button::Falling) 42 0 : toggleState(); 43 0 : } 44 : 45 : /// Flip the state (on → off or off → on). 46 : /// Sends the appropriate MIDI event. 47 0 : bool toggleState() { 48 0 : setState(!getState()); 49 0 : return getState(); 50 : } 51 : 52 : /// Get the current state. 53 0 : bool getState() const { return state; } 54 : 55 : /// Set the state to the given value. 56 : /// Sends the appropriate MIDI event. 57 0 : void setState(bool state) { 58 0 : this->state = state; 59 0 : state ? sender.sendOn(address) : sender.sendOff(address); 60 0 : } 61 : 62 : /// @see @ref AH::Button::invert() 63 : void invert() { button.invert(); } 64 : 65 : /// Get the state of the underlying button. 66 : AH::Button::State getButtonState() const { return button.getState(); } 67 : 68 : /// Get the MIDI address. 69 : MIDIAddress getAddress() const { return this->address; } 70 : /// Set the MIDI address. Has unexpected consequences if used while the 71 : /// button is active. Use banks if you need to support that. 72 : void setAddressUnsafe(MIDIAddress address) { this->address = address; } 73 : 74 : private: 75 : AH::Button button; 76 : MIDIAddress address; 77 : bool state = false; 78 : 79 : public: 80 : Sender sender; 81 : }; 82 : 83 : END_CS_NAMESPACE