Line data Source code
1 : #include "MIDI_Interface.hpp"
2 :
3 : BEGIN_CS_NAMESPACE
4 :
5 76 : MIDI_Interface::MIDI_Interface() {
6 76 : setAsDefault(); // Make this the default MIDI Interface
7 76 : }
8 :
9 76 : MIDI_Interface::~MIDI_Interface() {
10 76 : if (getDefault() == this)
11 76 : DefaultMIDI_Interface = nullptr;
12 76 : }
13 :
14 : MIDI_Interface *MIDI_Interface::DefaultMIDI_Interface = nullptr;
15 :
16 76 : void MIDI_Interface::setAsDefault() { DefaultMIDI_Interface = this; }
17 :
18 170 : MIDI_Interface *MIDI_Interface::getDefault() { return DefaultMIDI_Interface; }
19 :
20 : // -------------------------------- SENDING --------------------------------- //
21 :
22 2 : void MIDI_Interface::send(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2) {
23 2 : sendOnCable(m, c, d1, d2, 0);
24 2 : }
25 :
26 2 : void MIDI_Interface::send(uint8_t m, uint8_t c, uint8_t d1) {
27 2 : sendOnCable(m, c, d1, 0);
28 2 : }
29 :
30 4 : void MIDI_Interface::sendOnCable(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2,
31 : uint8_t cn) {
32 4 : c--; // Channels are zero-based
33 4 : m &= 0xF0; // bitmask high nibble
34 4 : m |= 0b10000000; // set msb
35 4 : c &= 0x0F; // bitmask low nibble
36 4 : d1 &= 0x7F; // clear msb
37 4 : d2 &= 0x7F; // clear msb
38 4 : cn &= 0x0F; // bitmask low nibble
39 4 : sendImpl(m, c, d1, d2, cn);
40 4 : }
41 :
42 4 : void MIDI_Interface::sendOnCable(uint8_t m, uint8_t c, uint8_t d1, uint8_t cn) {
43 4 : c--; // Channels are zero-based
44 4 : m &= 0xF0; // bitmask high nibble
45 4 : m |= 0b10000000; // set msb
46 4 : c &= 0x0F; // bitmask low nibble
47 4 : d1 &= 0x7F; // clear msb
48 4 : cn &= 0x0F; // bitmask low nibble
49 4 : sendImpl(m, c, d1, cn);
50 4 : }
51 :
52 0 : void MIDI_Interface::sendOnCable(uint8_t r, uint8_t cn) {
53 0 : r |= 0b10000000; // set msb
54 0 : cn &= 0x0F; // bitmask low nibble
55 0 : sendImpl(r, cn);
56 0 : }
57 :
58 21 : void MIDI_Interface::sendNoteOn(MIDICNChannelAddress address,
59 : uint8_t velocity) {
60 21 : if (address)
61 42 : sendImpl(NOTE_ON, address.getRawChannel(), address.getAddress(),
62 21 : velocity, address.getCableNumber());
63 21 : }
64 20 : void MIDI_Interface::sendNoteOff(MIDICNChannelAddress address,
65 : uint8_t velocity) {
66 20 : if (address)
67 40 : sendImpl(NOTE_OFF, address.getRawChannel(), address.getAddress(),
68 20 : velocity, address.getCableNumber());
69 20 : }
70 2 : void MIDI_Interface::sendKP(MIDICNChannelAddress address, uint8_t pressure) {
71 2 : if (address)
72 4 : sendImpl(KEY_PRESSURE, address.getRawChannel(), address.getAddress(),
73 2 : pressure, address.getCableNumber());
74 2 : }
75 51 : void MIDI_Interface::sendCC(MIDICNChannelAddress address, uint8_t value) {
76 51 : if (address)
77 102 : sendImpl(CC, address.getRawChannel(), address.getAddress(), value,
78 51 : address.getCableNumber());
79 51 : }
80 3 : void MIDI_Interface::sendPC(MIDICNChannel address, uint8_t value) {
81 3 : if (address)
82 6 : sendImpl(PROGRAM_CHANGE, address.getRawChannel(), value,
83 3 : address.getCableNumber());
84 3 : }
85 2 : void MIDI_Interface::sendPC(MIDICNChannelAddress address) {
86 2 : if (address)
87 4 : sendImpl(PROGRAM_CHANGE, address.getRawChannel(), address.getAddress(),
88 2 : address.getCableNumber());
89 2 : }
90 2 : void MIDI_Interface::sendCP(MIDICNChannel address, uint8_t pressure) {
91 2 : if (address)
92 4 : sendImpl(CHANNEL_PRESSURE, address.getRawChannel(), pressure,
93 2 : address.getCableNumber());
94 2 : }
95 11 : void MIDI_Interface::sendPB(MIDICNChannel address, uint16_t value) {
96 11 : if (address)
97 22 : sendImpl(PITCH_BEND, address.getRawChannel(), value & 0x7F, value >> 7,
98 11 : address.getCableNumber());
99 11 : }
100 16 : void MIDI_Interface::send(SysExMessage message) {
101 16 : if (message.length) {
102 13 : if (message.length < 2) {
103 3 : ERROR(F("Error: invalid SysEx length"), 0x7F7F);
104 0 : return;
105 : }
106 10 : sendImpl(message.data, message.length, message.CN);
107 10 : }
108 16 : }
109 1 : void MIDI_Interface::send(uint8_t rt, uint8_t cn) {
110 1 : if (rt) {
111 1 : sendImpl(rt, cn);
112 1 : }
113 1 : }
114 :
115 : // -------------------------------- PARSING --------------------------------- //
116 :
117 76 : Parsing_MIDI_Interface::Parsing_MIDI_Interface(MIDI_Parser &parser)
118 228 : : parser(parser) {}
119 :
120 17 : ChannelMessage Parsing_MIDI_Interface::getChannelMessage() {
121 17 : return parser.getChannelMessage();
122 : }
123 :
124 8 : SysExMessage Parsing_MIDI_Interface::getSysExMessage() const {
125 8 : return parser.getSysEx();
126 : }
127 :
128 3 : uint8_t Parsing_MIDI_Interface::getCN() const { return parser.getCN(); }
129 :
130 : // -------------------------------- READING --------------------------------- //
131 :
132 1 : void Parsing_MIDI_Interface::update() {
133 1 : bool repeat = true;
134 3 : while (repeat) {
135 2 : MIDI_read_t event = read();
136 2 : repeat = dispatchMIDIEvent(event);
137 : }
138 1 : }
139 :
140 : #pragma GCC diagnostic push
141 : #pragma GCC diagnostic ignored "-Wswitch-enum"
142 :
143 63 : bool Parsing_MIDI_Interface::dispatchMIDIEvent(MIDI_read_t event) {
144 63 : switch (event) {
145 43 : case NO_MESSAGE: return false;
146 13 : case CHANNEL_MESSAGE: onChannelMessage(); return true;
147 5 : case SYSEX_MESSAGE: onSysExMessage(); return true;
148 2 : default: onRealtimeMessage(static_cast<uint8_t>(event)); return true;
149 : }
150 63 : }
151 :
152 : #pragma GCC diagnostic pop
153 :
154 2 : void Parsing_MIDI_Interface::onRealtimeMessage(uint8_t message) {
155 2 : if (callbacks)
156 2 : callbacks->onRealtimeMessage(*this, message);
157 2 : }
158 :
159 13 : void Parsing_MIDI_Interface::onChannelMessage() {
160 13 : if (callbacks)
161 13 : callbacks->onChannelMessage(*this);
162 13 : }
163 :
164 5 : void Parsing_MIDI_Interface::onSysExMessage() {
165 5 : if (callbacks)
166 5 : callbacks->onSysExMessage(*this);
167 5 : }
168 :
169 : END_CS_NAMESPACE
|