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.

118 lines
2.4KB

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