LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - USBMIDI_Interface.hpp (source / functions) Hit Total Coverage
Test: ffed98f648fe78e7aa7bdd228474317d40dadbec Lines: 7 8 87.5 %
Date: 2022-05-28 15:22:59 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "MIDI_Interface.hpp"
       4             : #include "USBMIDI/USBMIDI.hpp"
       5             : #include "USBMIDI_Sender.hpp"
       6             : #include <AH/Error/Error.hpp>
       7             : #include <AH/Teensy/TeensyUSBTypes.hpp>
       8             : #include <MIDI_Parsers/USBMIDI_Parser.hpp>
       9             : 
      10             : AH_DIAGNOSTIC_WERROR()
      11             : 
      12             : BEGIN_CS_NAMESPACE
      13             : 
      14             : /**
      15             :  * @brief   A class for MIDI interfaces sending MIDI messages over a USB MIDI
      16             :  *          connection.
      17             :  */
      18             : template <class Backend>
      19             : class GenericUSBMIDI_Interface : public MIDI_Interface {
      20             :   public:
      21             :     /**
      22             :      * @brief   Construct a new GenericUSBMIDI_Interface.
      23             :      */
      24             :     template <class... Args>
      25          29 :     GenericUSBMIDI_Interface(Args &&...args)
      26             :         : backend(std::forward<Args>(args)...),
      27          29 :           alwaysSendImmediately_(backend.preferImmediateSend()) {}
      28             : 
      29             :   private:
      30             :     // MIDI send implementations
      31             :     void sendChannelMessageImpl(ChannelMessage) override;
      32             :     void sendSysCommonImpl(SysCommonMessage) override;
      33             :     void sendSysExImpl(SysExMessage) override;
      34             :     void sendRealTimeImpl(RealTimeMessage) override;
      35           0 :     void sendNowImpl() override { backend.sendNow(); }
      36             : 
      37             :   private:
      38             :     void handleStall() override;
      39             : 
      40             :   public:
      41             :     void begin() override;
      42             :     void update() override;
      43             : 
      44             :   public:
      45             :     /// @name   Reading incoming MIDI messages
      46             :     /// @{
      47             : 
      48             :     /// Try reading and parsing a single incoming MIDI message.
      49             :     /// @return Returns the type of the read message, or
      50             :     ///         `MIDIReadEvent::NO_MESSAGE` if no MIDI message was available.
      51             :     MIDIReadEvent read();
      52             : 
      53             :     /// Return the received channel voice message.
      54             :     ChannelMessage getChannelMessage() const;
      55             :     /// Return the received system common message.
      56             :     SysCommonMessage getSysCommonMessage() const;
      57             :     /// Return the received real-time message.
      58             :     RealTimeMessage getRealTimeMessage() const;
      59             :     /// Return the received system exclusive message.
      60             :     SysExMessage getSysExMessage() const;
      61             : 
      62             :     /// @}
      63             : 
      64             :   public:
      65             :     /// @name Underlying USB communication
      66             :     /// @{
      67             : 
      68             :     /// The (platform-specific) backend used for MIDI over USB communication.
      69             :     Backend backend;
      70             : 
      71             :   private:
      72             :     /// Functor to send USB MIDI packets.
      73             :     struct Sender {
      74             :         GenericUSBMIDI_Interface *iface;
      75          28 :         void operator()(Cable cn, MIDICodeIndexNumber cin, uint8_t d0,
      76             :                         uint8_t d1, uint8_t d2) {
      77          28 :             uint8_t cn_cin = (cn.getRaw() << 4) | uint8_t(cin);
      78          28 :             iface->backend.write({cn_cin, d0, d1, d2});
      79          28 :         }
      80             :     };
      81             :     /// @}
      82             : 
      83             :   private:
      84             :     /// Parses USB packets into MIDI messages.
      85             :     USBMIDI_Parser parser;
      86             :     /// Sends USB MIDI messages.
      87             :     USBMIDI_Sender sender;
      88             :     /// @see neverSendImmediately()
      89             :     bool alwaysSendImmediately_ = true;
      90             : 
      91             :   public:
      92             :     /// @name   Buffering USB packets
      93             :     /// @{
      94             : 
      95             :     /// Check if this USB interface always sends its USB packets immediately
      96             :     /// after sending a MIDI message. The default value depends on the MIDI USB
      97             :     /// backend being used: `true` for the `MIDIUSB` library, and `false` for
      98             :     /// the Teensy Core USB MIDI functions (because they have a short timeout).
      99             :     bool alwaysSendsImmediately() const { return alwaysSendImmediately_; }
     100             :     /// Don't send the USB packets immediately after sending a MIDI message.
     101             :     /// By disabling immediate transmission, packets are buffered until you
     102             :     /// call @ref sendNow() or until a timeout is reached, so multiple MIDI
     103             :     /// messages can be transmitted in a single USB packet. This is more
     104             :     /// efficient and results in a higher maximum bandwidth, but it could
     105             :     /// increase latency when used incorrectly.
     106             :     void neverSendImmediately() { alwaysSendImmediately_ = false; }
     107             :     /// Send the USB packets immediately after sending a MIDI message.
     108             :     /// @see @ref neverSendImmediately()
     109             :     void alwaysSendImmediately() { alwaysSendImmediately_ = true; }
     110             : 
     111             :     /// @}
     112             : };
     113             : 
     114             : END_CS_NAMESPACE
     115             : 
     116             : #include "USBMIDI_Interface.ipp"
     117             : 
     118             : #if defined(TEENSYDUINO) && !defined(TEENSY_MIDIUSB_ENABLED)
     119             : #warning                                                                       \
     120             :     "Teensy: USB MIDI not enabled. Enable it from the Tools > USB Type menu."
     121             : #define CS_USB_MIDI_DISABLED
     122             : #endif
     123             : 
     124             : // If MIDI over USB is supported
     125             : #if (!defined(CS_USB_MIDI_NOT_SUPPORTED) && !defined(CS_USB_MIDI_DISABLED)) || \
     126             :     !defined(ARDUINO)
     127             : 
     128             : BEGIN_CS_NAMESPACE
     129             : 
     130             : /**
     131             :  * @brief   A class for MIDI interfaces sending MIDI messages over a USB MIDI
     132             :  *          connection.
     133             :  * 
     134             :  * On boards that support it, this will create a native MIDI over USB interface
     135             :  * using the platform-specific libraries (e.g. MIDIUSB for Arduino Leonardo, or 
     136             :  * the Core usbMIDI library for Teensy).  
     137             :  * On boards without native USB support, it'll fall back to a serial MIDI 
     138             :  * interface at the default @ref MIDI_BAUD "MIDI baud rate" on the UART 
     139             :  * connected to the Serial to USB chip. This can be used with custom 
     140             :  * MIDI over USB firmware for the Serial to USB chip.
     141             :  * 
     142             :  * @note    See @ref md_pages_MIDI-over-USB for more information.
     143             :  * 
     144             :  * @ingroup MIDIInterfaces
     145             :  */
     146             : class USBMIDI_Interface
     147             :     : public GenericUSBMIDI_Interface<USBDeviceMIDIBackend> {
     148             :   public:
     149          29 :     USBMIDI_Interface() = default;
     150             :     using MIDIUSBPacket_t = USBDeviceMIDIBackend::MIDIUSBPacket_t;
     151             : };
     152             : 
     153             : END_CS_NAMESPACE
     154             : 
     155             : // If the main MCU doesn't have a USB connection:
     156             : // Fall back on Serial connection at the hardware MIDI baud rate.
     157             : // (Can be used with HIDUINO or USBMidiKliK.)
     158             : #elif !defined(CS_USB_MIDI_DISABLED)
     159             : 
     160             : #include "SerialMIDI_Interface.hpp"
     161             : 
     162             : BEGIN_CS_NAMESPACE
     163             : 
     164             : /**
     165             :  * @brief   A class for MIDI interfaces sending MIDI messages over a USB MIDI
     166             :  *          connection.
     167             :  * 
     168             :  * @note    See @ref md_pages_MIDI-over-USB for more information.
     169             :  * 
     170             :  * @ingroup MIDIInterfaces
     171             :  */
     172             : class USBMIDI_Interface : public USBSerialMIDI_Interface {
     173             :   public:
     174             :     /**
     175             :      * @brief   Construct a new USBMIDI_Interface.
     176             :      */
     177             :     USBMIDI_Interface() : USBSerialMIDI_Interface(MIDI_BAUD) {}
     178             : };
     179             : 
     180             : END_CS_NAMESPACE
     181             : 
     182             : #endif
     183             : 
     184             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.15