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.

112 lines
2.2KB

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