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.

157 lines
3.3KB

  1. #include "keyboard.hpp"
  2. #include "midi.hpp"
  3. #include "window.hpp"
  4. #include <map>
  5. namespace rack {
  6. namespace keyboard {
  7. struct Driver;
  8. static const int DRIVER = -11;
  9. static Driver *driver = NULL;
  10. struct InputDevice : midi::InputDevice {
  11. int octave = 5;
  12. std::map<int, int> pressedNotes;
  13. void onKeyPress(int key) {
  14. int note = -1;
  15. switch (key) {
  16. case GLFW_KEY_Z: note = 0; break;
  17. case GLFW_KEY_S: note = 1; break;
  18. case GLFW_KEY_X: note = 2; break;
  19. case GLFW_KEY_D: note = 3; break;
  20. case GLFW_KEY_C: note = 4; break;
  21. case GLFW_KEY_V: note = 5; break;
  22. case GLFW_KEY_G: note = 6; break;
  23. case GLFW_KEY_B: note = 7; break;
  24. case GLFW_KEY_H: note = 8; break;
  25. case GLFW_KEY_N: note = 9; break;
  26. case GLFW_KEY_J: note = 10; break;
  27. case GLFW_KEY_M: note = 11; break;
  28. case GLFW_KEY_COMMA: note = 12; break;
  29. case GLFW_KEY_L: note = 13; break;
  30. case GLFW_KEY_PERIOD: note = 14; break;
  31. case GLFW_KEY_SEMICOLON: note = 15; break;
  32. case GLFW_KEY_SLASH: note = 16; break;
  33. case GLFW_KEY_Q: note = 12; break;
  34. case GLFW_KEY_2: note = 13; break;
  35. case GLFW_KEY_W: note = 14; break;
  36. case GLFW_KEY_3: note = 15; break;
  37. case GLFW_KEY_E: note = 16; break;
  38. case GLFW_KEY_R: note = 17; break;
  39. case GLFW_KEY_5: note = 18; break;
  40. case GLFW_KEY_T: note = 19; break;
  41. case GLFW_KEY_6: note = 20; break;
  42. case GLFW_KEY_Y: note = 21; break;
  43. case GLFW_KEY_7: note = 22; break;
  44. case GLFW_KEY_U: note = 23; break;
  45. case GLFW_KEY_I: note = 24; break;
  46. case GLFW_KEY_9: note = 25; break;
  47. case GLFW_KEY_O: note = 26; break;
  48. case GLFW_KEY_0: note = 27; break;
  49. case GLFW_KEY_P: note = 28; break;
  50. case GLFW_KEY_LEFT_BRACKET: note = 29; break;
  51. case GLFW_KEY_EQUAL: note = 30; break;
  52. case GLFW_KEY_RIGHT_BRACKET: note = 31; break;
  53. case GLFW_KEY_GRAVE_ACCENT: {
  54. octave--;
  55. } break;
  56. case GLFW_KEY_1: {
  57. octave++;
  58. } break;
  59. default: break;
  60. }
  61. octave = math::clamp(octave, 0, 9);
  62. if (note < 0)
  63. return;
  64. note += 12 * octave;
  65. if (note > 127)
  66. return;
  67. midi::Message msg;
  68. msg.cmd = 0x9 << 4;
  69. msg.data1 = note;
  70. msg.data2 = 127;
  71. onMessage(msg);
  72. pressedNotes[key] = note;
  73. }
  74. void onKeyRelease(int key) {
  75. auto it = pressedNotes.find(key);
  76. if (it != pressedNotes.end()) {
  77. int note = it->second;
  78. midi::Message msg;
  79. msg.cmd = 0x8 << 4;
  80. msg.data1 = note;
  81. msg.data2 = 127;
  82. onMessage(msg);
  83. pressedNotes.erase(it);
  84. }
  85. }
  86. };
  87. struct Driver : midi::Driver {
  88. InputDevice device;
  89. std::string getName() override {return "Computer keyboard";}
  90. std::vector<int> getInputDeviceIds() override {
  91. return {0};
  92. }
  93. std::string getInputDeviceName(int deviceId) override {
  94. if (deviceId == 0)
  95. return "QWERTY keyboard (US)";
  96. return "";
  97. }
  98. midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
  99. if (deviceId != 0)
  100. return NULL;
  101. device.subscribe(input);
  102. return &device;
  103. }
  104. void unsubscribeInput(int deviceId, midi::Input *input) override {
  105. if (deviceId != 0)
  106. return;
  107. device.unsubscribe(input);
  108. }
  109. };
  110. void init() {
  111. driver = new Driver;
  112. midi::addDriver(DRIVER, driver);
  113. }
  114. void press(int key) {
  115. if (!driver)
  116. return;
  117. driver->device.onKeyPress(key);
  118. }
  119. void release(int key) {
  120. if (!driver)
  121. return;
  122. driver->device.onKeyRelease(key);
  123. }
  124. } // namespace keyboard
  125. } // namespace rack