Control Surface master
MIDI Control Surface library for Arduino
USBMIDI_Parser.hpp
Go to the documentation of this file.
1#include "MIDI_Parser.hpp"
2#include "SysExBuffer.hpp"
4
5#ifdef MIDI_NUM_CABLES
6#define USB_MIDI_NUMBER_OF_CABLES MIDI_NUM_CABLES
7#elif defined(USB_MIDI4_SERIAL) || defined(USB_MIDI4)
8#define USB_MIDI_NUMBER_OF_CABLES 4
9#elif defined(USB_MIDI16_AUDIO_SERIAL) || defined(USB_MIDI16_SERIAL) || \
10 defined(USB_MIDI16)
11// TODO: || defined(USB_EVERYTHING)
12#define USB_MIDI_NUMBER_OF_CABLES 16
13#elif !defined(ARDUINO) || defined(DOXYGEN)
14#define USB_MIDI_NUMBER_OF_CABLES 16
15#else
16#define USB_MIDI_NUMBER_OF_CABLES 1
17#endif
18
20
27 public:
29
38 template <class BytePuller>
39 MIDIReadEvent pull(BytePuller &&puller);
40
41 protected:
46
47 public:
48#if !IGNORE_SYSEX
51 return {
55 };
56 }
57#endif
58
59 protected:
63 template <uint8_t NumBytes>
66
67 protected:
68#if !IGNORE_SYSEX
69 void startSysEx(Cable cable) { sysexbuffers[cable.getRaw()].start(); }
70 void endSysEx(Cable cable) {
71 sysexbuffers[cable.getRaw()].end();
72 activeCable = cable;
73 }
74 void endSysExChunk(Cable cable) { activeCable = cable; }
75 bool hasSysExSpace(Cable cable, uint8_t amount) const {
76 return sysexbuffers[cable.getRaw()].hasSpaceLeft(amount);
77 }
78 void addSysExByte(Cable cable, uint8_t data) {
79 sysexbuffers[cable.getRaw()].add(data);
80 }
81 void addSysExBytes(Cable cable, const uint8_t *data, uint8_t len) {
82 sysexbuffers[cable.getRaw()].add(data, len);
83 }
84 bool receivingSysEx(Cable cable) const {
85 return sysexbuffers[cable.getRaw()].isReceiving();
86 }
87
88 void storePacket(MIDIUSBPacket_t packet) { storedPacket = packet; }
89 bool hasStoredPacket() const { return storedPacket[0] != 0x00; }
92 storedPacket[0] = 0x00;
93 return t;
94 }
95
97
98 private:
101#endif
102};
103
104template <class BytePuller>
105inline MIDIReadEvent USBMIDI_Parser::pull(BytePuller &&puller) {
106 // First try resuming the parser, we might have a stored packet that has to
107 // be parsed first.
108 MIDIReadEvent evt = resume();
109 if (evt != MIDIReadEvent::NO_MESSAGE)
110 return evt;
111
112 // If resumption didn't produce a message, read new packets from the input
113 // and parse them until either we get a message, or until the input runs out
114 // of new packets.
115 MIDIUSBPacket_t midiPacket;
116 while (puller.pull(midiPacket)) {
117 evt = feed(midiPacket);
118 if (evt != MIDIReadEvent::NO_MESSAGE)
119 return evt;
120 }
122}
123
constexpr Cable CABLE_1
Definition: Cable.hpp:118
MIDIReadEvent
Values returned by the MIDI reading functions.
@ NO_MESSAGE
No new messages were received.
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
#define USB_MIDI_NUMBER_OF_CABLES
A type-safe class for MIDI USB Cable numbers.
Definition: Cable.hpp:13
constexpr uint8_t getRaw() const
Get the cable as an integer.
Definition: Cable.hpp:29
Base class for MIDI parsers.
Definition: MIDI_Parser.hpp:16
Helper for storing the System Exclusive messages being received by a MIDI parser.
Definition: SysExBuffer.hpp:13
const uint8_t * getBuffer() const
Get a pointer to the buffer.
Definition: SysExBuffer.cpp:34
bool hasSpaceLeft(uint8_t amount=1) const
Check if the buffer has at least amount bytes of free space available.
Definition: SysExBuffer.cpp:25
void start()
Start a new SysEx message.
Definition: SysExBuffer.cpp:6
void add(uint8_t data)
Add a byte to the current SysEx message.
Definition: SysExBuffer.cpp:15
void end()
Finish the current SysEx message.
Definition: SysExBuffer.cpp:11
uint16_t getLength() const
Get the length of the SysEx message in the buffer.
Definition: SysExBuffer.cpp:36
bool isReceiving() const
Check if the buffer is receiving a SysEx message.
Definition: SysExBuffer.cpp:32
Parser for MIDI over USB packets.
bool hasSysExSpace(Cable cable, uint8_t amount) const
MIDIReadEvent handleSingleByte(MIDIUSBPacket_t packet, Cable cable)
MIDIReadEvent resume()
Resume the parser with the previously stored and unhandled packet.
SysExBuffer sysexbuffers[16]
MIDIReadEvent handleSysExStartCont(MIDIUSBPacket_t packet, Cable cable)
void endSysExChunk(Cable cable)
void storePacket(MIDIUSBPacket_t packet)
MIDIReadEvent handleSysExEnd(MIDIUSBPacket_t packet, Cable cable)
MIDIReadEvent handleChannelMessage(MIDIUSBPacket_t packet, Cable cable)
void startSysEx(Cable cable)
bool receivingSysEx(Cable cable) const
bool hasStoredPacket() const
MIDIUSBPacket_t storedPacket
MIDIUSBPacket_t popStoredPacket()
MIDIReadEvent feed(MIDIUSBPacket_t packet)
Feed a new packet to the parser.
MIDIReadEvent pull(BytePuller &&puller)
Parse one incoming MIDI message.
void addSysExByte(Cable cable, uint8_t data)
void endSysEx(Cable cable)
void addSysExBytes(Cable cable, const uint8_t *data, uint8_t len)
MIDIReadEvent handleSysCommon(MIDIUSBPacket_t packet, Cable cable)
SysExMessage getSysExMessage() const
Get the latest SysEx message.
AH::Array< uint8_t, 4 > MIDIUSBPacket_t