LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - USBMIDI_Interface.hpp (source / functions) Hit Total Coverage
Test: b8a30b4b7040ae1abf162fd0a258beaa2de43626 Lines: 7 9 77.8 %
Date: 2024-12-21 21:28:55 Functions: 2 4 50.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             :     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 1.15