forked from VCVRack/Rack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgamepad.cpp
115 lines (91 loc) · 2.33 KB
/
gamepad.cpp
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "gamepad.hpp"
#include <GLFW/glfw3.h>
namespace rack {
static const int GAMEPAD_DRIVER = -10;
static GamepadDriver *driver = NULL;
void GamepadInputDevice::step() {
if (!glfwJoystickPresent(deviceId))
return;
// Get gamepad state
int numAxes;
const float *axes = glfwGetJoystickAxes(deviceId, &numAxes);
int numButtons;
const unsigned char *buttons = glfwGetJoystickButtons(deviceId, &numButtons);
// Convert axes to MIDI CC
ccs.resize(numAxes);
for (int i = 0; i < numAxes; i++) {
// Allow CC value to go negative, but clamp at -127 instead of -128 for symmetry
int8_t cc = clamp((int) roundf(axes[i] * 127), -127, 127);
if (cc != ccs[i]) {
ccs[i] = cc;
// Send MIDI message
MidiMessage msg;
// MIDI channel 1
msg.cmd = (0xb << 4) | 0;
msg.data1 = i;
msg.data2 = ccs[i];
onMessage(msg);
}
}
// Convert buttons to MIDI notes
states.resize(numButtons);
for (int i = 0; i < numButtons; i++) {
bool state = !!buttons[i];
if (state != states[i]) {
states[i] = state;
MidiMessage msg;
msg.cmd = ((state ? 0x9 : 0x8) << 4);
msg.data1 = i;
msg.data2 = 127;
onMessage(msg);
}
}
}
GamepadDriver::GamepadDriver() {
for (int i = 0; i < 16; i++) {
devices[i].deviceId = i;
}
}
std::vector<int> GamepadDriver::getInputDeviceIds() {
std::vector<int> deviceIds;
for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(i)) {
deviceIds.push_back(i);
}
}
return deviceIds;
}
std::string GamepadDriver::getInputDeviceName(int deviceId) {
if (!(0 <= deviceId && deviceId < 16))
return "";
const char *name = glfwGetJoystickName(deviceId);
if (name) {
return name;
}
return stringf("Gamepad %d (unavailable)", deviceId + 1);
}
MidiInputDevice *GamepadDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (!(0 <= deviceId && deviceId < 16))
return NULL;
devices[deviceId].subscribe(midiInput);
return &devices[deviceId];
}
void GamepadDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
if (!(0 <= deviceId && deviceId < 16))
return;
devices[deviceId].unsubscribe(midiInput);
}
void gamepadInit() {
driver = new GamepadDriver();
midiDriverAdd(GAMEPAD_DRIVER, driver);
}
void gamepadStep() {
if (!driver)
return;
for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(i)) {
driver->devices[i].step();
}
}
}
} // namespace rack