LCOV - code coverage report
Current view: top level - src/MIDI_Inputs - MIDIInputElementMatchers.hpp (source / functions) Hit Total Coverage
Test: b8a30b4b7040ae1abf162fd0a258beaa2de43626 Lines: 41 43 95.3 %
Date: 2024-12-21 21:28:55 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "BankableMIDIMatcherHelpers.hpp"
       4             : #include "MIDIInputElement.hpp"
       5             : 
       6             : BEGIN_CS_NAMESPACE
       7             : 
       8             : /// @addtogroup MIDIInputMatchers
       9             : /// @{
      10             : 
      11             : // -------------------------------------------------------------------------- //
      12             : 
      13             : /// Matcher for MIDI messages with 1 data byte, such as Channel Pressure
      14             : /// and Program Change.
      15             : struct OneByteMIDIMatcher {
      16           3 :     OneByteMIDIMatcher(MIDIChannelCable address) : address(address) {}
      17             : 
      18             :     struct Result {
      19             :         bool match;
      20             :         uint8_t value;
      21             :     };
      22             : 
      23           4 :     Result operator()(ChannelMessage m) {
      24           4 :         if (!MIDIChannelCable::matchSingle(m.getChannelCable(), address))
      25           2 :             return {false, 0};
      26           2 :         uint8_t value = m.data1;
      27           2 :         return {true, value};
      28             :     }
      29             : 
      30             :     MIDIChannelCable address;
      31             : };
      32             : 
      33             : // -------------------------------------------------------------------------- //
      34             : 
      35             : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
      36             : /// Change, Key Pressure (but not Pitch Bend). Matches a single address.
      37             : struct TwoByteMIDIMatcher {
      38           7 :     TwoByteMIDIMatcher(MIDIAddress address) : address(address) {}
      39             : 
      40             :     struct Result {
      41             :         bool match;
      42             :         uint8_t value;
      43             :     };
      44             : 
      45          16 :     Result operator()(ChannelMessage m) {
      46          16 :         if (!MIDIAddress::matchSingle(m.getAddress(), address))
      47           0 :             return {false, 0};
      48             :         uint8_t value =
      49          16 :             m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
      50          16 :         return {true, value};
      51             :     }
      52             : 
      53             :     MIDIAddress address;
      54             : };
      55             : 
      56             : // -------------------------------------------------------------------------- //
      57             : 
      58             : /// Matcher for MIDI Pitch Bend messages. Matches a single address.
      59             : struct PitchBendMIDIMatcher {
      60             :     PitchBendMIDIMatcher(MIDIChannelCable address) : address(address) {}
      61             : 
      62             :     struct Result {
      63             :         bool match;
      64             :         uint16_t value;
      65             :     };
      66             : 
      67             :     Result operator()(ChannelMessage m) {
      68             :         if (!MIDIChannelCable::matchSingle(m.getChannelCable(), address))
      69             :             return {false, 0};
      70             :         uint16_t value = (m.data2 << 7) | m.data1;
      71             :         return {true, value};
      72             :     }
      73             : 
      74             :     MIDIChannelCable address;
      75             : };
      76             : 
      77             : // -------------------------------------------------------------------------- //
      78             : 
      79             : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
      80             : /// Change, Key Pressure (but not Pitch Bend). Matches ranges of addresses on a
      81             : /// single channel and cable.
      82             : struct TwoByteRangeMIDIMatcher {
      83          17 :     TwoByteRangeMIDIMatcher(MIDIAddress address, uint8_t length)
      84          17 :         : address(address), length(length) {}
      85             : 
      86             :     struct Result {
      87             :         bool match;
      88             :         uint8_t value;
      89             :         uint8_t index;
      90             :     };
      91             : 
      92          96 :     Result operator()(ChannelMessage m) {
      93          96 :         if (!MIDIAddress::matchAddressInRange(m.getAddress(), address, length))
      94           2 :             return {false, 0, 0};
      95             :         uint8_t value =
      96          94 :             m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
      97          94 :         uint8_t index = m.getData1() - address.getAddress();
      98          94 :         return {true, value, index};
      99             :     }
     100             : 
     101             :     MIDIAddress address;
     102             :     uint8_t length;
     103             : };
     104             : 
     105             : // -------------------------------------------------------------------------- //
     106             : 
     107             : /// Matcher for MIDI messages with 1 data byte, such as Channel Pressure
     108             : /// and Program Change. Matches a single address over multiple banks.
     109             : template <uint8_t BankSize>
     110             : struct BankableOneByteMIDIMatcher {
     111             :     BankableOneByteMIDIMatcher(
     112             :         BankConfig<BankSize, BankType::ChangeChannel> config,
     113             :         MIDIChannelCable address)
     114             :         : config(config), address(address) {}
     115             : 
     116             :     struct Result {
     117             :         bool match;
     118             :         uint8_t value;
     119             :         uint8_t bankIndex;
     120             :     };
     121             : 
     122             :     Result operator()(ChannelMessage m) {
     123             :         using BankableMIDIMatcherHelpers::getBankIndex;
     124             :         using BankableMIDIMatcherHelpers::matchBankable;
     125             :         if (!matchBankable(m.getChannelCable(), address, config))
     126             :             return {false, 0, 0};
     127             :         uint8_t value = m.data1;
     128             :         uint8_t bankIndex = getBankIndex(m.getChannelCable(), address, config);
     129             :         return {true, value, bankIndex};
     130             :     }
     131             : 
     132             :     Bank<BankSize> &getBank() { return config.bank; }
     133             :     const Bank<BankSize> &getBank() const { return config.bank; }
     134             :     BankType getBankType() const { return config.type; }
     135             :     static constexpr setting_t getBankSize() { return BankSize; }
     136             : 
     137             :     /// Get the current bank setting.
     138             :     /// @see    @ref Bank<N>::getSelection()
     139             :     setting_t getSelection() const { return getBank().getSelection(); }
     140             : 
     141             :     BaseBankConfig<BankSize> config;
     142             :     MIDIChannelCable address;
     143             : };
     144             : 
     145             : // -------------------------------------------------------------------------- //
     146             : 
     147             : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
     148             : /// Change, Key Pressure. Matches a single address over multiple banks.
     149             : template <uint8_t BankSize>
     150             : struct BankableTwoByteMIDIMatcher {
     151           6 :     BankableTwoByteMIDIMatcher(BankConfig<BankSize> config, MIDIAddress address)
     152           6 :         : config(config), address(address) {}
     153             : 
     154             :     struct Result {
     155             :         bool match;
     156             :         uint8_t value;
     157             :         uint8_t bankIndex;
     158             :     };
     159             : 
     160          11 :     Result operator()(ChannelMessage m) {
     161             :         using BankableMIDIMatcherHelpers::getBankIndex;
     162             :         using BankableMIDIMatcherHelpers::matchBankable;
     163          11 :         if (!matchBankable(m.getAddress(), address, config))
     164           0 :             return {false, 0, 0};
     165          11 :         uint8_t value =
     166          20 :             m.getMessageType() == MIDIMessageType::NoteOff ? 0 : m.getData2();
     167          11 :         uint8_t bankIndex = getBankIndex(m.getAddress(), address, config);
     168          11 :         return {true, value, bankIndex};
     169             :     }
     170             : 
     171          12 :     Bank<BankSize> &getBank() { return config.bank; }
     172          55 :     const Bank<BankSize> &getBank() const { return config.bank; }
     173             :     BankType getBankType() const { return config.type; }
     174             :     static constexpr setting_t getBankSize() { return BankSize; }
     175             : 
     176             :     /// Get the current bank setting.
     177             :     /// @see    @ref Bank<N>::getSelection()
     178          55 :     setting_t getSelection() const { return getBank().getSelection(); }
     179             : 
     180             :     BaseBankConfig<BankSize> config;
     181             :     MIDIAddress address;
     182             : };
     183             : 
     184             : // -------------------------------------------------------------------------- //
     185             : 
     186             : /// Matcher for MIDI Pitch Bend messages. Matches a single address over multiple
     187             : /// banks.
     188             : template <uint8_t BankSize>
     189             : struct BankablePitchBendMIDIMatcher {
     190             :     BankablePitchBendMIDIMatcher(
     191             :         BankConfig<BankSize, BankType::ChangeChannel> config,
     192             :         MIDIChannelCable address)
     193             :         : config(config), address(address) {}
     194             : 
     195             :     struct Result {
     196             :         bool match;
     197             :         uint16_t value;
     198             :         uint8_t bankIndex;
     199             :     };
     200             : 
     201             :     Result operator()(ChannelMessage m) {
     202             :         using BankableMIDIMatcherHelpers::getBankIndex;
     203             :         using BankableMIDIMatcherHelpers::matchBankable;
     204             :         if (!matchBankable(m.getChannelCable(), address, config))
     205             :             return {false, 0, 0};
     206             :         uint16_t value = (m.data2 << 7) | m.data1;
     207             :         uint8_t bankIndex = getBankIndex(m.getChannelCable(), address, config);
     208             :         return {true, value, bankIndex};
     209             :     }
     210             : 
     211             :     Bank<BankSize> &getBank() { return config.bank; }
     212             :     const Bank<BankSize> &getBank() const { return config.bank; }
     213             :     BankType getBankType() const { return config.type; }
     214             :     static constexpr setting_t getBankSize() { return BankSize; }
     215             : 
     216             :     /// Get the current bank setting.
     217             :     /// @see    @ref Bank<N>::getSelection()
     218             :     setting_t getSelection() const { return getBank().getSelection(); }
     219             : 
     220             :     BaseBankConfig<BankSize> config;
     221             :     MIDIChannelCable address;
     222             : };
     223             : 
     224             : // -------------------------------------------------------------------------- //
     225             : 
     226             : /// Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control
     227             : /// Change, Key Pressure. Matches a range of addresses over multiple banks.
     228             : template <uint8_t BankSize>
     229             : struct BankableTwoByteRangeMIDIMatcher {
     230             :     /// Constructor.
     231           6 :     BankableTwoByteRangeMIDIMatcher(BankConfig<BankSize> config,
     232             :                                     MIDIAddress address, uint8_t length)
     233           6 :         : config(config), address(address), length(length) {}
     234             : 
     235             :     struct Result {
     236             :         bool match;
     237             :         uint8_t value;
     238             :         uint8_t bankIndex;
     239             :         uint8_t index;
     240             :     };
     241             : 
     242          30 :     Result operator()(ChannelMessage m) {
     243             :         using BankableMIDIMatcherHelpers::getBankIndex;
     244             :         using BankableMIDIMatcherHelpers::getRangeIndex;
     245             :         using BankableMIDIMatcherHelpers::matchBankableInRange;
     246          30 :         if (!matchBankableInRange(m.getAddress(), address, config, length))
     247          18 :             return {false, 0, 0, 0};
     248          12 :         uint8_t value = m.getMessageType() == m.NoteOff ? 0 : m.getData2();
     249          12 :         uint8_t bankIndex = getBankIndex(m.getAddress(), address, config);
     250          12 :         uint8_t rangeIndex = getRangeIndex(m.getAddress(), address, config);
     251          12 :         return {true, value, bankIndex, rangeIndex};
     252             :     }
     253             : 
     254          12 :     Bank<BankSize> &getBank() { return config.bank; }
     255             :     const Bank<BankSize> &getBank() const { return config.bank; }
     256             :     static constexpr setting_t getBankSize() { return BankSize; }
     257             : 
     258             :     /// Get the current bank setting.
     259             :     /// @see    @ref Bank<N>::getSelection()
     260         180 :     setting_t getSelection() const { return config.bank.getSelection(); }
     261             : 
     262             :     BaseBankConfig<BankSize> config;
     263             :     MIDIAddress address;
     264             :     uint8_t length;
     265             : };
     266             : 
     267             : // -------------------------------------------------------------------------- //
     268             : 
     269             : /// @}
     270             : 
     271             : END_CS_NAMESPACE

Generated by: LCOV version 1.15