-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathusbMidi.cpp
More file actions
87 lines (78 loc) · 2.77 KB
/
usbMidi.cpp
File metadata and controls
87 lines (78 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#define log_name "usbmidi"
#include "usbMidi.h"
#include "apcKey25.h"
#include <circle/logger.h>
#include <circle/devicenameservice.h>
#include <circle/usb/usbmidi.h>
#include <circle/string.h>
static void packetHandler(unsigned nCable, u8 *pPacket, unsigned nLength)
{
if (nLength < 3) return;
if (pTheAPC)
pTheAPC->handleMidi(pPacket[0], pPacket[1], pPacket[2]);
}
static bool s_registered[9] = {};
static CUSBMIDIDevice *s_pDevices[9] = {};
static int s_updateCount = 0;
void usbMidiProcess(bool bPlugAndPlayUpdated)
{
if (!bPlugAndPlayUpdated) return;
// Re-query every slot each PnP update and track the live device pointer, not
// a sticky "registered once" flag. A device that disappears then re-appears
// (re-enumeration into the same slot) gets a NEW CUSBMIDIDevice*; the old
// sticky flag skipped it, leaving s_pDevices[] dangling AND the LED cache
// never re-invalidated (post-reconnect LEDs frozen on stale colors). Now any
// pointer CHANGE (gone, new, or swapped) re-registers and invalidates the LED
// cache so the next tick re-sends every LED to match true state.
CString name;
bool changed = false;
for (int i = 1; i <= 8; i++)
{
name.Format("umidi%d", i);
CUSBMIDIDevice *pDev = (CUSBMIDIDevice *)
CDeviceNameService::Get()->GetDevice((const char *)name, FALSE);
if (pDev == s_pDevices[i]) continue; // unchanged slot
s_pDevices[i] = pDev;
s_registered[i] = (pDev != nullptr);
changed = true;
if (pDev)
{
CLogger::Get()->Write(log_name, LogNotice, "USB MIDI device connected: %s", (const char *)name);
pDev->RegisterPacketHandler(packetHandler);
}
else
{
CLogger::Get()->Write(log_name, LogNotice, "USB MIDI device gone: %s", (const char *)name);
}
}
// Any roster change re-syncs the LED cache so every pad re-sends next tick.
if (changed && pTheAPC) pTheAPC->invalidateLedCache();
}
bool usbMidiSendNoteOn(u8 note, u8 velocity)
{
u8 msg[3] = { 0x90, note, velocity };
bool any = false;
for (int i = 1; i <= 8; i++) {
if (s_pDevices[i]) {
if (s_pDevices[i]->SendPlainMIDI(0, msg, 3)) any = true;
}
}
return any;
}
void usbMidiInjectMidi(u8 status, u8 data1, u8 data2)
{
if (pTheAPC)
pTheAPC->handleMidi(status, data1, data2);
}
void usbMidiSendCC(int cc_num, int value)
{
u8 msg[3] = { 0xB0, (u8)cc_num, (u8)value };
for (int i = 1; i <= 8; i++)
if (s_pDevices[i]) s_pDevices[i]->SendPlainMIDI(0, msg, 3);
}
void usbMidiSend(u8 status, u8 data1, u8 data2)
{
u8 msg[3] = { status, data1, data2 };
for (int i = 1; i <= 8; i++)
if (s_pDevices[i]) s_pDevices[i]->SendPlainMIDI(0, msg, 3);
}