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
|