LCOV - code coverage report
Current view: top level - src/MIDI_Inputs - NoteCCRange.hpp (source / functions) Hit Total Coverage
Test: 90a1b9beff85a60dc6ebcea034a947a845e56960 Lines: 71 72 98.6 %
Date: 2019-11-30 15:53:32 Functions: 77 98 78.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <Banks/BankableMIDIInput.hpp>
       4             : #include <MIDI_Inputs/MIDIInputElementCC.hpp>
       5             : #include <MIDI_Inputs/MIDIInputElementNote.hpp>
       6             : 
       7             : BEGIN_CS_NAMESPACE
       8             : 
       9             : class INoteCCValue {
      10             :   protected:
      11          11 :     INoteCCValue(uint8_t rangeLength) : rangeLength{rangeLength} {}
      12             : 
      13             :   public:
      14           4 :     uint8_t length() const { return rangeLength; }
      15             :     virtual uint8_t getValue(uint8_t index) const = 0;
      16          15 :     uint8_t getValue() const { return getValue(0); }
      17             : 
      18             :   private:
      19             :     uint8_t rangeLength;
      20             : };
      21             : 
      22             : class NoteCCRangeEmptyCallback {
      23             :   public:
      24           9 :     void begin(const INoteCCValue &) {}
      25          13 :     void update(const INoteCCValue &, uint8_t) {}
      26          30 :     void updateAll(const INoteCCValue &) {}
      27             : };
      28             : 
      29           2 : struct SimpleNoteCCValueCallback {
      30             :   protected:
      31           2 :     SimpleNoteCCValueCallback() = default;
      32             : 
      33             :   public:
      34           0 :     virtual void begin(const INoteCCValue &) {}
      35             :     virtual void update(const INoteCCValue &, uint8_t) = 0;
      36           2 :     virtual void updateAll(const INoteCCValue &noteccval) {
      37           4 :         for (uint8_t i = 0; i < noteccval.length(); ++i)
      38           2 :             update(noteccval, i);
      39           2 :     }
      40             : };
      41             : 
      42             : // -------------------------------------------------------------------------- //
      43             : 
      44             : template <class MIDIInput_t, uint8_t RangeLen, uint8_t NumBanks, class Callback>
      45          11 : class NoteCCRange : public MIDIInput_t, public INoteCCValue {
      46             :   public:
      47          11 :     NoteCCRange(MIDICNChannelAddress address, const Callback &callback)
      48          22 :         : MIDIInput_t{address}, INoteCCValue{RangeLen}, callback(callback) {}
      49             : 
      50             :     /// @todo   check index bounds
      51         134 :     uint8_t getValue(uint8_t index) const override {
      52         134 :         return values[getSelection()][index];
      53             :     }
      54             :     using INoteCCValue::getValue;
      55             : 
      56             :     /// Initialize
      57          11 :     void begin() override { callback.begin(*this); }
      58             :     /// Reset all values to zero
      59           2 :     void reset() override {
      60           2 :         values = {{}};
      61           2 :         callback.updateAll(*this);
      62           2 :     }
      63             : 
      64             :   private:
      65          21 :     bool updateImpl(const ChannelMessageMatcher &midimsg,
      66             :                     const MIDICNChannelAddress &target) override {
      67          21 :         uint8_t bankIndex = this->getBankIndex(target);
      68          21 :         uint8_t rangeIndex = this->getRangeIndex(target);
      69          21 :         uint8_t value = getValueFromMIDIMessage(midimsg);
      70          21 :         values[bankIndex][rangeIndex] = value;
      71          21 :         if (bankIndex == this->getSelection())
      72          17 :             callback.update(*this, rangeIndex);
      73          21 :         return true;
      74             :     }
      75             : 
      76             :     static uint8_t
      77          21 :     getValueFromMIDIMessage(const ChannelMessageMatcher &midimsg) {
      78          21 :         return midimsg.type == NOTE_OFF ? 0 : midimsg.data2;
      79             :     }
      80             : 
      81             :     /// Get the active bank selection
      82          39 :     virtual uint8_t getSelection() const { return 0; }
      83             : 
      84             :     /// Get the bank index from a MIDI address
      85          13 :     virtual setting_t getBankIndex(MIDICNChannelAddress target) const {
      86             :         (void)target;
      87          13 :         return 0;
      88             :     }
      89             : 
      90          13 :     virtual uint8_t getRangeIndex(MIDICNChannelAddress target) const {
      91          13 :         return target.getAddress() - this->address.getAddress();
      92             :     }
      93             : 
      94          15 :     Array<Array<uint8_t, RangeLen>, NumBanks> values = {{}};
      95             : 
      96             :   public:
      97             :     Callback callback;
      98             :     constexpr static uint8_t length() { return RangeLen; }
      99             : };
     100             : 
     101             : // -------------------------------------------------------------------------- //
     102             : 
     103             : template <class MIDIInput_t, uint8_t RangeLen,
     104             :           class Callback = NoteCCRangeEmptyCallback>
     105           7 : class GenericNoteCCRange
     106             :     : public NoteCCRange<MIDIInput_t, RangeLen, 1, Callback> {
     107             :   public:
     108           7 :     GenericNoteCCRange(MIDICNChannelAddress address, const Callback &callback)
     109           7 :         : NoteCCRange<MIDIInput_t, RangeLen, 1, Callback>{address, callback} {}
     110             : 
     111             :   private:
     112             :     /// Check if the address of the incoming MIDI message is within the range
     113             :     /// of addresses of this element.
     114          13 :     bool match(const MIDICNChannelAddress &target) const override {
     115          13 :         return MIDICNChannelAddress::matchAddressInRange( //
     116          13 :             target, this->address, RangeLen);
     117             :     }
     118             : };
     119             : 
     120             : /**
     121             :  * @brief   MIDI Input Element that listens to a range of notes.
     122             :  * 
     123             :  * @ingroup MIDIInputElements
     124             :  * @tparam  RangeLen 
     125             :  *          The length of the range of notes to listen to.
     126             :  */
     127             : template <uint8_t RangeLen>
     128           1 : class NoteRange : public GenericNoteCCRange<MIDIInputElementNote, RangeLen> {
     129             :   public:
     130           1 :     NoteRange(MIDICNChannelAddress address)
     131           1 :         : GenericNoteCCRange<MIDIInputElementNote, RangeLen>{address, {}} {}
     132             : };
     133             : 
     134           4 : class NoteValue : public GenericNoteCCRange<MIDIInputElementNote, 1> {
     135             :   public:
     136           4 :     NoteValue(MIDICNChannelAddress address)
     137           4 :         : GenericNoteCCRange<MIDIInputElementNote, 1>{address, {}} {}
     138             : };
     139             : using MIDINote[[deprecated("Use NoteValue instead")]] = NoteValue;
     140             : 
     141             : template <uint8_t RangeLen>
     142             : class CCRange : public GenericNoteCCRange<MIDIInputElementCC, RangeLen> {
     143             :   public:
     144             :     CCRange(MIDICNChannelAddress address)
     145             :         : GenericNoteCCRange<MIDIInputElementCC, RangeLen>{address, {}} {}
     146             : };
     147             : 
     148             : class CCValue : public GenericNoteCCRange<MIDIInputElementCC, 1> {
     149             :   public:
     150             :     CCValue(MIDICNChannelAddress address)
     151             :         : GenericNoteCCRange<MIDIInputElementCC, 1>{address, {}} {}
     152             : };
     153             : 
     154             : // -------------------------------------------------------------------------- //
     155             : 
     156             : namespace Bankable {
     157             : 
     158             : /// @tparam RangeLen
     159             : ///         The length of the range.
     160             : /// @tparam NumBanks
     161             : ///         The size of the bank.
     162             : template <class MIDIInput_t, uint8_t RangeLen, uint8_t NumBanks,
     163             :           class Callback = NoteCCRangeEmptyCallback>
     164           4 : class GenericNoteCCRange
     165             :     : public NoteCCRange<MIDIInput_t, RangeLen, NumBanks, Callback>,
     166             :       public BankableMIDIInput<NumBanks> {
     167             :   public:
     168           4 :     GenericNoteCCRange(BankConfig<NumBanks> config,
     169             :                        MIDICNChannelAddress address,
     170             :                        const Callback &callback)
     171           4 :         : NoteCCRange<MIDIInput_t, RangeLen, NumBanks, Callback>{
     172           4 :             address,
     173           4 :             callback,
     174           8 :         }, BankableMIDIInput<NumBanks>{config} {}
     175             : 
     176             :   private:
     177             :     /// Check if the address of the incoming MIDI message is within the range
     178             :     /// of addresses and in one of the banks of this element.
     179          20 :     bool match(const MIDICNChannelAddress &target) const override {
     180          40 :         return BankableMIDIInput<NumBanks>::matchBankableAddressInRange(
     181          20 :             target, this->address, RangeLen);
     182             :     }
     183             : 
     184         116 :     setting_t getSelection() const override {
     185         116 :         return BankableMIDIInput<NumBanks>::getSelection();
     186             :     };
     187             : 
     188           8 :     uint8_t getBankIndex(MIDICNChannelAddress target) const override {
     189           8 :         return BankableMIDIInput<NumBanks>::getBankIndex(target, this->address);
     190             :     }
     191             : 
     192           8 :     uint8_t getRangeIndex(MIDICNChannelAddress target) const override {
     193          16 :         return BankableMIDIInput<NumBanks>::getRangeIndex(target,
     194           8 :                                                           this->address);
     195             :     }
     196             : 
     197          28 :     void onBankSettingChange() override { this->callback.updateAll(*this); }
     198             : };
     199             : 
     200             : template <uint8_t RangeLen, uint8_t NumBanks>
     201           4 : class NoteRange
     202             :     : public GenericNoteCCRange<MIDIInputElementNote, RangeLen, NumBanks> {
     203             :   public:
     204           4 :     NoteRange(BankConfig<NumBanks> config, MIDICNChannelAddress address)
     205           4 :         : GenericNoteCCRange<MIDIInputElementNote, RangeLen, NumBanks>{
     206           8 :               config, address, {}} {}
     207             : };
     208             : 
     209             : template <uint8_t NumBanks>
     210             : class NoteValue : public GenericNoteCCRange<MIDIInputElementNote, 1, NumBanks> {
     211             :   public:
     212             :     NoteValue(BankConfig<NumBanks> config, MIDICNChannelAddress address)
     213             :         : GenericNoteCCRange<MIDIInputElementNote, 1, NumBanks>{
     214             :               config, address, {}} {}
     215             : };
     216             : template <uint8_t NumBanks>
     217             : using MIDINote[[deprecated("Use NoteValue instead")]] = NoteValue<NumBanks>;
     218             : 
     219             : template <uint8_t RangeLen, uint8_t NumBanks>
     220             : class CCRange
     221             :     : public GenericNoteCCRange<MIDIInputElementCC, RangeLen, NumBanks> {
     222             :   public:
     223             :     CCRange(BankConfig<NumBanks> config, MIDICNChannelAddress address)
     224             :         : GenericNoteCCRange<MIDIInputElementCC, RangeLen, NumBanks>{
     225             :               config, address, {}} {}
     226             : };
     227             : 
     228             : template <uint8_t NumBanks>
     229             : class CCValue : public GenericNoteCCRange<MIDIInputElementCC, 1, NumBanks> {
     230             :   public:
     231             :     CCValue(BankConfig<NumBanks> config, MIDICNChannelAddress address)
     232             :         : GenericNoteCCRange<MIDIInputElementCC, 1, NumBanks>{
     233             :               config, address, {}} {}
     234             : };
     235             : 
     236             : } // namespace Bankable
     237             : 
     238             : END_CS_NAMESPACE

Generated by: LCOV version 1.14-5-g4ff2ed6