Line data Source code
1 : /* ✔ */ 2 : 3 : #pragma once 4 : 5 : #include <AH/Debug/Debug.hpp> 6 : #include <AH/Error/Error.hpp> 7 : #include <AH/Containers/LinkedList.hpp> 8 : #include <Selectors/Selectable.hpp> 9 : 10 : BEGIN_CS_NAMESPACE 11 : 12 : template <setting_t N> 13 : class BankableMIDIInput; 14 : 15 : class BankableMIDIOutput; 16 : 17 : /** 18 : * @brief A class for changing the address of BankableMIDIOutput%s. 19 : */ 20 : class OutputBank { 21 : public: 22 : /** 23 : * @brief Create a new OutputBank object. 24 : * 25 : * @param tracksPerBank 26 : * The number of addresses/tracks to skip for each bank setting. 27 : * Must be strictly positive. 28 : * @param initialSelection 29 : * The initial bank setting. 30 : */ 31 38 : OutputBank(uint8_t tracksPerBank = 1, setting_t initialSelection = 0) 32 38 : : tracksPerBank(tracksPerBank), bankSetting(initialSelection) { 33 38 : if (tracksPerBank == 0) 34 1 : FATAL_ERROR(F("A Bank must have a non-zero number of tracks."), 35 : 0x4573); 36 38 : } 37 : 38 : /** 39 : * @brief Select the given bank setting. 40 : * 41 : * @param setting 42 : * The new setting to select. 43 : */ 44 61 : void select(setting_t setting) { bankSetting = setting; } 45 : 46 : /** 47 : * @brief Get the current bank setting. 48 : */ 49 191 : virtual setting_t getSelection() const { return bankSetting; } 50 : 51 : /** 52 : * @brief Get the number of tracks per bank. 53 : * This is the number of addresses/tracks to skip for each bank setting. 54 : */ 55 112 : uint8_t getTracksPerBank() const { return tracksPerBank; } 56 : 57 : /** 58 : * @brief Get the offset (number of banks times the index of the selected 59 : * bank) 60 : */ 61 : uint8_t getOffset() const { return getSelection() * getTracksPerBank(); } 62 : 63 : private: 64 : uint8_t tracksPerBank; 65 : setting_t bankSetting; 66 : }; 67 : 68 : /** 69 : * @brief A class that groups Bankable BankableMIDIOutput%s and 70 : * BankableMIDIInput%s, and allows the user to change the addresses 71 : * of these elements. 72 : * 73 : * @tparam N 74 : * The number of banks. 75 : */ 76 : template <setting_t N> 77 : class Bank : public Selectable<N>, public OutputBank { 78 : friend class BankableMIDIInput<N>; 79 : 80 : public: 81 : /** 82 : * @brief Construct a new Bank object. 83 : * 84 : * @param tracksPerBank 85 : * The number of addresses/tracks to skip for each bank setting. 86 : * Must be strictly positive. 87 : * @param initialSelection 88 : * The initial bank setting. 89 : */ 90 21 : Bank(uint8_t tracksPerBank = 1, setting_t initialSelection = 0) 91 21 : : Selectable<N>(initialSelection), 92 63 : OutputBank(tracksPerBank, initialSelection) {} 93 : 94 : /** 95 : * @brief Select the given bank setting. 96 : * 97 : * All BankableMIDIInput%s will be updated. 98 : * 99 : * @param bankSetting 100 : * The new setting to select. 101 : */ 102 : void select(setting_t bankSetting) override; 103 : 104 : /** 105 : * @brief Get the number of Banks. 106 : */ 107 : constexpr static uint8_t getNumberOfBanks() { return N; } 108 : 109 : private: 110 : /** 111 : * @brief Add a BankableMIDIInput to the bank. 112 : * 113 : * This method is called in the BankableMIDIInput constructor. 114 : * 115 : * @param bankable 116 : * The BankableMIDIInput to be added. 117 : */ 118 : void add(BankableMIDIInput<N> *bankable); 119 : 120 : /** 121 : * @brief Remove a BankableMIDIInput from the bank. 122 : * 123 : * This method is called in the BankableMIDIInput destructor. 124 : * 125 : * @param bankable 126 : * The BankableMIDIInput to be removed. 127 : */ 128 : void remove(BankableMIDIInput<N> *bankable); 129 : 130 : /** 131 : * @brief A linked list of all BankableMIDIInput elements that have been 132 : * added to this bank, and that should be updated when the bank 133 : * setting changes. 134 : * 135 : * The list is updated automatically when BankableMIDIInput elements are 136 : * created or destroyed. 137 : */ 138 : DoublyLinkedList<BankableMIDIInput<N>> inputBankables; 139 : }; 140 : 141 : END_CS_NAMESPACE 142 : 143 : // ---------------------------- Implementations ----------------------------- // 144 : 145 : #include <Banks/BankableMIDIInput.hpp> 146 : 147 : BEGIN_CS_NAMESPACE 148 : 149 : template <setting_t N> 150 16 : void Bank<N>::add(BankableMIDIInput<N> *bankable) { 151 16 : inputBankables.append(bankable); 152 16 : } 153 : 154 : template <setting_t N> 155 16 : void Bank<N>::remove(BankableMIDIInput<N> *bankable) { 156 16 : inputBankables.remove(bankable); 157 16 : } 158 : 159 : template <setting_t N> 160 51 : void Bank<N>::select(setting_t bankSetting) { 161 51 : bankSetting = this->validateSetting(bankSetting); 162 51 : OutputBank::select(bankSetting); 163 100 : for (BankableMIDIInput<N> &e : inputBankables) 164 49 : e.onBankSettingChange(); 165 50 : } 166 : 167 : END_CS_NAMESPACE