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

Generated by: LCOV version 2.4-beta