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

Generated by: LCOV version 1.15