LCOV - code coverage report
Current view: top level - src/Banks - BankableAddresses.hpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 21 24 87.5 %
Date: 2020-09-08 17:44:46 Functions: 10 10 100.0 %
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 OutputBankableMIDIAddress_Base {
      12             :   protected:
      13             :     /**
      14             :      * @brief   Constructor.
      15             :      * 
      16             :      * @param   bank
      17             :      *          The bank to add this element to.
      18             :      */
      19          37 :     OutputBankableMIDIAddress_Base(const OutputBank &bank) : bank(bank) {}
      20             : 
      21             :   public:
      22             :     /** 
      23             :      * @brief   Get the actual bank setting (no matter whether the element is 
      24             :      *          locked or not).
      25             :      */
      26          22 :     setting_t getRawBankSetting() const { return bank.getSelection(); }
      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             :      */
      34          44 :     setting_t getSelection() const {
      35          44 :         return lockedSetting == UNLOCKED ? getRawBankSetting() : lockedSetting;
      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          14 :     void lock() {
      45          14 :         if (lockedSetting == UNLOCKED)
      46          14 :             lockedSetting = getRawBankSetting();
      47          14 :     }
      48             : 
      49             :     /**
      50             :      * @brief   Unlock the bank setting.
      51             :      * 
      52             :      * After unlocking, @ref getSelection will return the actual bank setting 
      53             :      * again.
      54             :      */
      55          14 :     void unlock() { lockedSetting = UNLOCKED; }
      56             : 
      57             :   protected:
      58             :     const OutputBank &bank;
      59             : 
      60             :   private:
      61             :     constexpr static setting_t UNLOCKED = NO_SETTING;
      62          37 :     setting_t lockedSetting = UNLOCKED;
      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             : class OutputBankableMIDIAddress : public OutputBankableMIDIAddress_Base {
      82             :   public:
      83             :     /**
      84             :      * @brief   Create a new OutputBankableMIDIAddress object.
      85             :      * 
      86             :      * @param   bank
      87             :      *          The bank to add this element to.
      88             :      * @param   type
      89             :      *          What address type to change (address, channel or cable number).
      90             :      */
      91          28 :     OutputBankableMIDIAddress(const OutputBank &bank, BankType type)
      92          28 :         : OutputBankableMIDIAddress_Base{bank}, type(type) {}
      93             : 
      94             :     /**
      95             :      * @brief   Create a new OutputBankableMIDIAddress object.
      96             :      * 
      97             :      * @param   config
      98             :      *          The bank and address type to change.
      99             :      * 
     100             :      * @see     OutputBankableMIDIAddress::OutputBankableMIDIAddress(Bank<N> &, BankType)
     101             :      */
     102          28 :     OutputBankableMIDIAddress(BaseOutputBankConfig config)
     103          28 :         : OutputBankableMIDIAddress(config.bank, config.type) {}
     104             : 
     105             :     /** 
     106             :      * @brief   Get the offset relative to the base address.
     107             :      */
     108          36 :     RelativeMIDIAddress getAddressOffset() const {
     109          36 :         int8_t offset = getSelection() * bank.getTracksPerBank();
     110          36 :         switch (type) {
     111          36 :             case CHANGE_ADDRESS: return {offset, 0, 0};
     112           0 :             case CHANGE_CHANNEL: return {0, offset, 0};
     113           0 :             case CHANGE_CABLENB: return {0, 0, offset};
     114           0 :             default: return {};
     115             :         }
     116          36 :     }
     117             : 
     118             :   private:
     119             :     const BankType type;
     120             : };
     121             : 
     122             : /**
     123             :  * @brief   A base class for all MIDIOutputElement%s that can have one of many
     124             :  *          addresses.
     125             :  *          
     126             :  * The bank setting determines the address that's being used.
     127             :  *          
     128             :  * @note    To prevent 'sticky' notes (i.e. a button is pressed, a note on is
     129             :  *          sent, the bank is changed, the button is released, and the note off
     130             :  *          is sent to a different address, causing the first note to keep on 
     131             :  *          playing indefinitely), there must be a way to lock the bank setting
     132             :  *          while a note is playing. Then when it is no longer playing, the 
     133             :  *          bank setting is unlocked.
     134             :  * 
     135             :  * @invariant `getSelection` and `getRawBankSetting` always return a number in 
     136             :  *            the half-open interval 
     137             :  *            @f$ \left[0, \mathrm{bank.getNumberOfBanks()}\right) \cap 
     138             :  *            \mathbb{N} @f$.
     139             :  */
     140             : class ManyAddresses_Base : public OutputBankableMIDIAddress_Base {
     141             :   public:
     142             :     /**
     143             :      * @brief   Constructor.
     144             :      * 
     145             :      * @param   bank
     146             :      *          The bank to add this element to.
     147             :      * @tparam  NumBanks
     148             :      *          The number of bank settings @p bank has.
     149             :      */
     150             :     template <uint8_t NumBanks>
     151           9 :     ManyAddresses_Base(const Bank<NumBanks> &bank)
     152           9 :         : OutputBankableMIDIAddress_Base{bank} {}
     153             : };
     154             : 
     155             : END_CS_NAMESPACE

Generated by: LCOV version 1.14-6-g40580cd