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.

119 lines
2.3KB

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