You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
2.3KB

  1. #include "gamepad.hpp"
  2. #include <GLFW/glfw3.h>
  3. namespace rack {
  4. static const int GAMEPAD_DRIVER = -10;
  5. static GamepadDriver *driver = NULL;
  6. void GamepadInputDevice::step() {
  7. if (!glfwJoystickPresent(deviceId))
  8. return;
  9. // Get gamepad state
  10. int numAxes;
  11. const float *axes = glfwGetJoystickAxes(deviceId, &numAxes);
  12. int numButtons;
  13. const unsigned char *buttons = glfwGetJoystickButtons(deviceId, &numButtons);
  14. // Convert axes to MIDI CC
  15. ccs.resize(numAxes);
  16. for (int i = 0; i < numAxes; i++) {
  17. // Allow CC value to go negative, but clamp at -127 instead of -128 for symmetry
  18. int8_t cc = clamp((int) roundf(axes[i] * 127), -127, 127);
  19. if (cc != ccs[i]) {
  20. ccs[i] = cc;
  21. // Send MIDI message
  22. MidiMessage msg;
  23. // MIDI channel 1
  24. msg.cmd = (0xb << 4) | 0;
  25. msg.data1 = i;
  26. msg.data2 = ccs[i];
  27. onMessage(msg);
  28. }
  29. }
  30. // Convert buttons to MIDI notes
  31. states.resize(numButtons);
  32. for (int i = 0; i < numButtons; i++) {
  33. bool state = !!buttons[i];
  34. if (state != states[i]) {
  35. states[i] = state;
  36. MidiMessage msg;
  37. msg.cmd = ((state ? 0x9 : 0x8) << 4);
  38. msg.data1 = i;
  39. msg.data2 = 127;
  40. onMessage(msg);
  41. }
  42. }
  43. }
  44. GamepadDriver::GamepadDriver() {
  45. for (int i = 0; i < 16; i++) {
  46. devices[i].deviceId = i;
  47. }
  48. }
  49. std::vector<int> GamepadDriver::getInputDeviceIds() {
  50. std::vector<int> deviceIds;
  51. for (int i = 0; i < 16; i++) {
  52. if (glfwJoystickPresent(i)) {
  53. deviceIds.push_back(i);
  54. }
  55. }
  56. return deviceIds;
  57. }
  58. std::string GamepadDriver::getInputDeviceName(int deviceId) {
  59. if (!(0 <= deviceId && deviceId < 16))
  60. return "";
  61. const char *name = glfwGetJoystickName(deviceId);
  62. if (name) {
  63. return name;
  64. }
  65. return stringf("Gamepad %d (unavailable)", deviceId + 1);
  66. }
  67. MidiInputDevice *GamepadDriver::subscribeInputDevice(int deviceId, MidiInput *midiInput) {
  68. if (!(0 <= deviceId && deviceId < 16))
  69. return NULL;
  70. devices[deviceId].subscribe(midiInput);
  71. return &devices[deviceId];
  72. }
  73. void GamepadDriver::unsubscribeInputDevice(int deviceId, MidiInput *midiInput) {
  74. if (!(0 <= deviceId && deviceId < 16))
  75. return;
  76. devices[deviceId].unsubscribe(midiInput);
  77. }
  78. void gamepadInit() {
  79. driver = new GamepadDriver();
  80. midiDriverAdd(GAMEPAD_DRIVER, driver);
  81. }
  82. void gamepadStep() {
  83. if (!driver)
  84. return;
  85. for (int i = 0; i < 16; i++) {
  86. if (glfwJoystickPresent(i)) {
  87. driver->devices[i].step();
  88. }
  89. }
  90. }
  91. } // namespace rack