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.

154 lines
3.0KB

  1. #include <gamepad.hpp>
  2. #include <midi.hpp>
  3. #include <string.hpp>
  4. #include <Window.hpp>
  5. namespace rack {
  6. namespace gamepad {
  7. struct Driver;
  8. static const int DRIVER = -10;
  9. static Driver* driver = NULL;
  10. struct InputDevice : midi::InputDevice {
  11. int deviceId;
  12. int16_t ccValues[128] = {};
  13. std::string getName() override {
  14. const char* name = glfwGetJoystickName(deviceId);
  15. if (!name)
  16. return "";
  17. return name;
  18. }
  19. void step() {
  20. if (!glfwJoystickPresent(deviceId))
  21. return;
  22. // Get gamepad state
  23. int numAxes;
  24. const float* axes = glfwGetJoystickAxes(deviceId, &numAxes);
  25. int numButtons;
  26. const unsigned char* buttons = glfwGetJoystickButtons(deviceId, &numButtons);
  27. // Convert axes and buttons to MIDI CC
  28. // Unfortunately to support 14-bit MIDI CC, only the first 32 CCs can be used.
  29. // This could be fixed by continuing with CC 64 if more than 32 CCs are needed.
  30. int numCcs = std::min(numAxes + numButtons, 32);
  31. for (int i = 0; i < numCcs; i++) {
  32. // Allow CC value to go negative
  33. int16_t value;
  34. if (i < numAxes) {
  35. // Axis
  36. value = math::clamp((int) std::round(axes[i] * 0x3f80), -0x3f80, 0x3f80);
  37. }
  38. else {
  39. // Button
  40. value = buttons[i - numAxes] ? 0x3f80 : 0;
  41. }
  42. if (value == ccValues[i])
  43. continue;
  44. ccValues[i] = value;
  45. // Send MSB MIDI message
  46. midi::Message msg;
  47. msg.setStatus(0xb);
  48. msg.setNote(i);
  49. // Allow 8th bit to be set to allow bipolar value hack.
  50. msg.bytes[2] = (value >> 7);
  51. onMessage(msg);
  52. // Send LSB MIDI message for axis CCs
  53. if (i < numAxes) {
  54. midi::Message msg;
  55. msg.setStatus(0xb);
  56. msg.setNote(i + 32);
  57. msg.bytes[2] = (value & 0x7f);
  58. onMessage(msg);
  59. }
  60. }
  61. }
  62. };
  63. struct Driver : midi::Driver {
  64. InputDevice devices[16];
  65. Driver() {
  66. for (int i = 0; i < 16; i++) {
  67. devices[i].deviceId = i;
  68. }
  69. }
  70. std::string getName() override {
  71. return "Gamepad";
  72. }
  73. std::vector<int> getInputDeviceIds() override {
  74. std::vector<int> deviceIds;
  75. for (int i = 0; i < 16; i++) {
  76. if (glfwJoystickPresent(i)) {
  77. deviceIds.push_back(i);
  78. }
  79. }
  80. return deviceIds;
  81. }
  82. int getDefaultInputDeviceId() override {
  83. return 0;
  84. }
  85. std::string getInputDeviceName(int deviceId) override {
  86. if (!(0 <= deviceId && deviceId < 16))
  87. return "";
  88. const char* name = glfwGetJoystickName(deviceId);
  89. if (!name)
  90. return string::f("#%d (unavailable)", deviceId + 1);
  91. return name;
  92. }
  93. midi::InputDevice* subscribeInput(int deviceId, midi::Input* input) override {
  94. if (!(0 <= deviceId && deviceId < 16))
  95. return NULL;
  96. if (!glfwJoystickPresent(deviceId))
  97. return NULL;
  98. devices[deviceId].subscribe(input);
  99. return &devices[deviceId];
  100. }
  101. void unsubscribeInput(int deviceId, midi::Input* input) override {
  102. if (!(0 <= deviceId && deviceId < 16))
  103. return;
  104. devices[deviceId].unsubscribe(input);
  105. }
  106. };
  107. void init() {
  108. driver = new Driver;
  109. midi::addDriver(DRIVER, driver);
  110. }
  111. void step() {
  112. for (int i = 0; i < 16; i++) {
  113. if (glfwJoystickPresent(i)) {
  114. driver->devices[i].step();
  115. }
  116. }
  117. }
  118. } // namespace gamepad
  119. } // namespace rack