LCOV - code coverage report
Current view: top level - src/Banks - BankableAddresses.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 87.5 % 24 21
Test Date: 2026-06-06 17:44:35 Functions: 100.0 % 11 11
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta