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.

159 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 note on
  68. midi::Message msg;
  69. msg.setStatus(0x9);
  70. msg.setNote(note);
  71. msg.setValue(127);
  72. onMessage(msg);
  73. pressedNotes[key] = note;
  74. }
  75. void onKeyRelease(int key) {
  76. auto it = pressedNotes.find(key);
  77. if (it != pressedNotes.end()) {
  78. int note = it->second;
  79. // MIDI note off
  80. midi::Message msg;
  81. msg.setStatus(0x8);
  82. msg.setNote(note);
  83. msg.setValue(127);
  84. onMessage(msg);
  85. pressedNotes.erase(it);
  86. }
  87. }
  88. };
  89. struct Driver : midi::Driver {
  90. InputDevice device;
  91. std::string getName() override {return "Computer keyboard";}
  92. std::vector<int> getInputDeviceIds() override {
  93. return {0};
  94. }
  95. std::string getInputDeviceName(int deviceId) override {
  96. if (deviceId == 0)
  97. return "QWERTY keyboard (US)";
  98. return "";
  99. }
  100. midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
  101. if (deviceId != 0)
  102. return NULL;
  103. device.subscribe(input);
  104. return &device;
  105. }
  106. void unsubscribeInput(int deviceId, midi::Input *input) override {
  107. if (deviceId != 0)
  108. return;
  109. device.unsubscribe(input);
  110. }
  111. };
  112. void init() {
  113. driver = new Driver;
  114. midi::addDriver(DRIVER, driver);
  115. }
  116. void press(int key) {
  117. if (!driver)
  118. return;
  119. driver->device.onKeyPress(key);
  120. }
  121. void release(int key) {
  122. if (!driver)
  123. return;
  124. driver->device.onKeyRelease(key);
  125. }
  126. } // namespace keyboard
  127. } // namespace rack