#include #include #include #include namespace rack { namespace gamepad { struct Driver; static const int DRIVER = -10; static Driver* driver = NULL; struct InputDevice : midi::InputDevice { int deviceId; int8_t ccs[128] = {}; void 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 and buttons to MIDI CC int numCcs = std::min(numAxes + numButtons, 128); for (int i = 0; i < numCcs; i++) { // Allow CC value to go negative, but clamp at -127 instead of -128 for symmetry int8_t cc; if (i < numAxes) { // Axis cc = math::clamp((int) std::round(axes[i] * 127), -127, 127); } else { // Button cc = buttons[i - numAxes] ? 127 : 0; } if (cc == ccs[i]) continue; ccs[i] = cc; // Send MIDI message midi::Message msg; msg.setStatus(0xb); msg.setNote(i); // Allow 8th bit to be set msg.bytes[2] = cc; onMessage(msg); } } }; struct Driver : midi::Driver { InputDevice devices[16]; Driver() { for (int i = 0; i < 16; i++) { devices[i].deviceId = i; } } std::string getName() override { return "Gamepad"; } std::vector getInputDeviceIds() override { std::vector deviceIds; for (int i = 0; i < 16; i++) { if (glfwJoystickPresent(i)) { deviceIds.push_back(i); } } return deviceIds; } std::string getInputDeviceName(int deviceId) override { if (!(0 <= deviceId && deviceId < 16)) return ""; const char* name = glfwGetJoystickName(deviceId); if (name) { return name; } return string::f(" %d (unavailable)", deviceId + 1); } midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override { if (!(0 <= deviceId && deviceId < 16)) return NULL; devices[deviceId].subscribe(input); return &devices[deviceId]; } void unsubscribeInput(int deviceId, midi::Input* input) override { if (!(0 <= deviceId && deviceId < 16)) return; devices[deviceId].unsubscribe(input); } }; void init() { driver = new Driver; midi::addDriver(DRIVER, driver); } void step() { if (!driver) return; for (int i = 0; i < 16; i++) { if (glfwJoystickPresent(i)) { driver->devices[i].step(); } } } } // namespace gamepad } // namespace rack