Control Surface  1.1.0
MIDI Control Surface library for Arduino
BankableMIDIOutput.hpp
Go to the documentation of this file.
1 /* ✔ */
2 
3 #pragma once
4 
5 #include "Bank.hpp"
6 #include "BankConfig.hpp"
8 
10 
12  protected:
13  /**
14  * @brief Constructor.
15  *
16  * @param bank
17  * The bank to add this element to.
18  */
20 
21  public:
22  /**
23  * @brief Get the actual bank setting (no matter whether the element is
24  * locked or not).
25  */
27 
28  /**
29  * @brief Get the bank setting.
30  *
31  * If the element is locked, the bank setting from the moment it was locked
32  * is returned.
33  */
36  }
37 
38  /**
39  * @brief Lock the bank setting.
40  *
41  * As long as it's locked, `getSelection` will return the current setting,
42  * independent from the actual bank setting.
43  */
44  void lock() {
45  if (lockedSetting == UNLOCKED)
47  }
48 
49  /**
50  * @brief Unlock the bank setting.
51  *
52  * After unlocking, `getSelection` will return the actual bank setting
53  * again.
54  */
56 
57  protected:
58  const OutputBank &bank;
59 
60  private:
61  constexpr static setting_t UNLOCKED = NO_SETTING;
63 };
64 
65 /**
66  * @brief A base class for all MIDIOutputElement%s that can be banked.
67  *
68  * @note These elements don't have to be updated when the bank setting is
69  * changed, because they poll the bank setting each time they send a
70  * MIDI event.
71  * They are not added to the bank, they just keep a reference to the
72  * bank they're a part of.
73  *
74  * @note To prevent 'sticky' notes (i.e. a button is pressed, a note on is
75  * sent, the bank is changed, the button is released, and the note off
76  * is sent to a different address, causing the first note to keep on
77  * playing indefinitely), there must be a way to lock the bank setting
78  * while a note is playing. Then when it is no longer playing, the
79  * bank setting is unlocked.
80  *
81  * @todo Create BankableMIDIElement class, make this inherit from it, as
82  * well as ManyAddressesMIDIOutput.
83  */
85  public:
86  /**
87  * @brief Create a new BankableMIDIOutput object.
88  *
89  * @param bank
90  * The bank to add this element to.
91  * @param type
92  * What address type to change (address, channel or cable number).
93  */
96 
97  /**
98  * @brief Create a new BankableMIDIOutput object.
99  *
100  * @param config
101  * The bank and address type to change.
102  *
103  * @see BankableMIDIOutput::BankableMIDIOutput(Bank<N> &, BankType)
104  */
106  : BankableMIDIOutput(config.bank, config.type) {}
107 
108  /**
109  * @brief Get the offset relative to the base address.
110  */
112  int8_t offset = getSelection() * bank.getTracksPerBank();
113  switch (type) {
114  case CHANGE_ADDRESS: return {offset, 0, 0};
115  case CHANGE_CHANNEL: return {0, offset, 0};
116  case CHANGE_CABLENB: return {0, 0, offset};
117  default: return {};
118  }
119  }
120 
121  private:
122  const BankType type;
123 };
124 
125 /**
126  * @brief A base class for all MIDIOutputElement%s that can have one of many
127  * addresses.
128  *
129  * The bank setting determines the address that's being used.
130  *
131  * @tparam N
132  * The number of addresses the element has.
133  *
134  * @note To prevent 'sticky' notes (i.e. a button is pressed, a note on is
135  * sent, the bank is changed, the button is released, and the note off
136  * is sent to a different address, causing the first note to keep on
137  * playing indefinitely), there must be a way to lock the bank setting
138  * while a note is playing. Then when it is no longer playing, the
139  * bank setting is unlocked.
140  *
141  * @invariant `getSelection` and `getRawBankSetting` always return a number in
142  * the half-open interval
143  * @f$ \left[0, \mathrm{bank.getNumberOfBanks()}\right) \cap
144  * \mathbb{N} @f$.
145  */
147  public:
148  /**
149  * @brief Constructor.
150  *
151  * @param bank
152  * The bank to add this element to.
153  * @tparam NumBanks
154  * The number of bank settings @p bank has.
155  */
156  template <uint8_t NumBanks>
159 };
160 
BankableMIDIOutput_Base::UNLOCKED
constexpr static setting_t UNLOCKED
Definition: BankableMIDIOutput.hpp:61
OutputBank
A class for changing the address of BankableMIDIOutputs.
Definition: Bank.hpp:20
Bank
A class that groups Bankable BankableMIDIOutputs and BankableMIDIInputs, and allows the user to chang...
Definition: Bank.hpp:77
BankConfig.hpp
OutputBank::getTracksPerBank
uint8_t getTracksPerBank() const
Get the number of tracks per bank.
Definition: Bank.hpp:55
BankableMIDIOutput_Base::getRawBankSetting
setting_t getRawBankSetting() const
Get the actual bank setting (no matter whether the element is locked or not).
Definition: BankableMIDIOutput.hpp:26
BankableMIDIOutput_Base::BankableMIDIOutput_Base
BankableMIDIOutput_Base(const OutputBank &bank)
Constructor.
Definition: BankableMIDIOutput.hpp:19
BankableMIDIOutput_Base::lock
void lock()
Lock the bank setting.
Definition: BankableMIDIOutput.hpp:44
MIDICNChannelAddress.hpp
BankableMIDIOutput_Base::bank
const OutputBank & bank
Definition: BankableMIDIOutput.hpp:58
BEGIN_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
Definition: Settings/NamespaceSettings.hpp:9
ManyAddressesMIDIOutput
A base class for all MIDIOutputElements that can have one of many addresses.
Definition: BankableMIDIOutput.hpp:146
BankableMIDIOutput_Base
Definition: BankableMIDIOutput.hpp:11
RelativeMIDICNChannelAddress
A class for saving an offset to a MIDI address.
Definition: MIDICNChannelAddress.hpp:58
ManyAddressesMIDIOutput::ManyAddressesMIDIOutput
ManyAddressesMIDIOutput(const Bank< NumBanks > &bank)
Constructor.
Definition: BankableMIDIOutput.hpp:157
BankableMIDIOutput::getAddressOffset
RelativeMIDICNChannelAddress getAddressOffset() const
Get the offset relative to the base address.
Definition: BankableMIDIOutput.hpp:111
END_CS_NAMESPACE
#define END_CS_NAMESPACE
Definition: Settings/NamespaceSettings.hpp:10
BankableMIDIOutput_Base::lockedSetting
setting_t lockedSetting
Definition: BankableMIDIOutput.hpp:62
BankableMIDIOutput_Base::getSelection
setting_t getSelection() const
Get the bank setting.
Definition: BankableMIDIOutput.hpp:34
OutputBank::getSelection
virtual setting_t getSelection() const
Get the current bank setting.
Definition: Bank.hpp:49
NO_SETTING
constexpr setting_t NO_SETTING
A special setting that indicates an unused or invalid setting.
Definition: Def.hpp:52
BankableMIDIOutput::BankableMIDIOutput
BankableMIDIOutput(const OutputBank &bank, BankType type)
Create a new BankableMIDIOutput object.
Definition: BankableMIDIOutput.hpp:94
CHANGE_CHANNEL
Change the offset of the channel number of the element.
Definition: BankConfig.hpp:21
BankableMIDIOutput_Base::unlock
void unlock()
Unlock the bank setting.
Definition: BankableMIDIOutput.hpp:55
CHANGE_CABLENB
Change the offset of the cable number of the element (experimental).
Definition: BankConfig.hpp:27
BankType
BankType
An enumeration of the different bank types.
Definition: BankConfig.hpp:12
setting_t
uint8_t setting_t
The type used for Selectors.
Definition: Def.hpp:50
BankableMIDIOutput::type
const BankType type
Definition: BankableMIDIOutput.hpp:122
Bank.hpp
BankableMIDIOutput::BankableMIDIOutput
BankableMIDIOutput(const OutputBankConfig &config)
Create a new BankableMIDIOutput object.
Definition: BankableMIDIOutput.hpp:105
CHANGE_ADDRESS
Change the offset of the address (i.e.
Definition: BankConfig.hpp:17
OutputBankConfig
A struct for selecting the bank of BankableMIDIOutputs and the bank type.
Definition: BankConfig.hpp:50
BankableMIDIOutput
A base class for all MIDIOutputElements that can be banked.
Definition: BankableMIDIOutput.hpp:84