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.

218 lines
4.1KB

  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. enum {
  11. CMD_OCTAVE_DOWN = -1,
  12. CMD_OCTAVE_UP = -2,
  13. };
  14. static const int deviceCount = 2;
  15. static const std::vector<std::map<int, int>> deviceKeyNote = {
  16. {
  17. {GLFW_KEY_GRAVE_ACCENT, CMD_OCTAVE_DOWN},
  18. {GLFW_KEY_1, CMD_OCTAVE_UP},
  19. {GLFW_KEY_Z, 0},
  20. {GLFW_KEY_S, 1},
  21. {GLFW_KEY_X, 2},
  22. {GLFW_KEY_D, 3},
  23. {GLFW_KEY_C, 4},
  24. {GLFW_KEY_V, 5},
  25. {GLFW_KEY_G, 6},
  26. {GLFW_KEY_B, 7},
  27. {GLFW_KEY_H, 8},
  28. {GLFW_KEY_N, 9},
  29. {GLFW_KEY_J, 10},
  30. {GLFW_KEY_M, 11},
  31. {GLFW_KEY_COMMA, 12},
  32. {GLFW_KEY_L, 13},
  33. {GLFW_KEY_PERIOD, 14},
  34. {GLFW_KEY_SEMICOLON, 15},
  35. {GLFW_KEY_SLASH, 16},
  36. {GLFW_KEY_Q, 12},
  37. {GLFW_KEY_2, 13},
  38. {GLFW_KEY_W, 14},
  39. {GLFW_KEY_3, 15},
  40. {GLFW_KEY_E, 16},
  41. {GLFW_KEY_R, 17},
  42. {GLFW_KEY_5, 18},
  43. {GLFW_KEY_T, 19},
  44. {GLFW_KEY_6, 20},
  45. {GLFW_KEY_Y, 21},
  46. {GLFW_KEY_7, 22},
  47. {GLFW_KEY_U, 23},
  48. {GLFW_KEY_I, 24},
  49. {GLFW_KEY_9, 25},
  50. {GLFW_KEY_O, 26},
  51. {GLFW_KEY_0, 27},
  52. {GLFW_KEY_P, 28},
  53. {GLFW_KEY_LEFT_BRACKET, 29},
  54. {GLFW_KEY_EQUAL, 30},
  55. {GLFW_KEY_RIGHT_BRACKET, 31},
  56. },
  57. {
  58. {GLFW_KEY_KP_DIVIDE, CMD_OCTAVE_DOWN},
  59. {GLFW_KEY_KP_MULTIPLY, CMD_OCTAVE_UP},
  60. {GLFW_KEY_KP_7, 0},
  61. {GLFW_KEY_KP_8, 1},
  62. {GLFW_KEY_KP_9, 2},
  63. {GLFW_KEY_KP_ADD, 3},
  64. {GLFW_KEY_KP_4, 4},
  65. {GLFW_KEY_KP_5, 5},
  66. {GLFW_KEY_KP_6, 6},
  67. {GLFW_KEY_KP_1, 8},
  68. {GLFW_KEY_KP_2, 9},
  69. {GLFW_KEY_KP_3, 10},
  70. {GLFW_KEY_KP_ENTER, 11},
  71. {GLFW_KEY_KP_0, 12},
  72. {GLFW_KEY_KP_DECIMAL, 14},
  73. },
  74. };
  75. struct InputDevice : midi::InputDevice {
  76. int deviceId;
  77. int octave = 5;
  78. std::map<int, int> pressedNotes;
  79. void onKeyPress(int key) {
  80. if (subscribed.empty())
  81. return;
  82. auto keyNote = deviceKeyNote[deviceId];
  83. auto it = keyNote.find(key);
  84. if (it == keyNote.end())
  85. return;
  86. int note = it->second;
  87. if (note < 0) {
  88. if (note == CMD_OCTAVE_DOWN)
  89. octave--;
  90. else if (note == CMD_OCTAVE_UP)
  91. octave++;
  92. octave = math::clamp(octave, 0, 9);
  93. return;
  94. }
  95. note += 12 * octave;
  96. if (note > 127)
  97. return;
  98. // MIDI note on
  99. midi::Message msg;
  100. msg.setStatus(0x9);
  101. msg.setNote(note);
  102. msg.setValue(127);
  103. onMessage(msg);
  104. pressedNotes[key] = note;
  105. }
  106. void onKeyRelease(int key) {
  107. if (subscribed.empty())
  108. return;
  109. auto it = pressedNotes.find(key);
  110. if (it == pressedNotes.end())
  111. return;
  112. int note = it->second;
  113. // MIDI note off
  114. midi::Message msg;
  115. msg.setStatus(0x8);
  116. msg.setNote(note);
  117. msg.setValue(127);
  118. onMessage(msg);
  119. pressedNotes.erase(it);
  120. }
  121. };
  122. struct Driver : midi::Driver {
  123. InputDevice devices[deviceCount];
  124. Driver() {
  125. for (int deviceId = 0; deviceId < deviceCount; deviceId++) {
  126. devices[deviceId].deviceId = deviceId;
  127. }
  128. devices[1].octave = 3;
  129. }
  130. std::string getName() override {return "Computer keyboard";}
  131. std::vector<int> getInputDeviceIds() override {
  132. std::vector<int> deviceIds;
  133. for (int deviceId = 0; deviceId < deviceCount; deviceId++) {
  134. deviceIds.push_back(deviceId);
  135. }
  136. return deviceIds;
  137. }
  138. std::string getInputDeviceName(int deviceId) override {
  139. if (deviceId == 0)
  140. return "QWERTY keyboard (US)";
  141. else if (deviceId == 1)
  142. return "Numpad keyboard (US)";
  143. return "";
  144. }
  145. midi::InputDevice *subscribeInput(int deviceId, midi::Input *input) override {
  146. if (!(0 <= deviceId && deviceId < deviceCount))
  147. return NULL;
  148. devices[deviceId].subscribe(input);
  149. return &devices[deviceId];
  150. }
  151. void unsubscribeInput(int deviceId, midi::Input *input) override {
  152. if (!(0 <= deviceId && deviceId < deviceCount))
  153. return;
  154. devices[deviceId].unsubscribe(input);
  155. }
  156. void onKeyPress(int key) {
  157. for (int deviceId = 0; deviceId < deviceCount; deviceId++) {
  158. devices[deviceId].onKeyPress(key);
  159. }
  160. }
  161. void onKeyRelease(int key) {
  162. for (int deviceId = 0; deviceId < deviceCount; deviceId++) {
  163. devices[deviceId].onKeyRelease(key);
  164. }
  165. }
  166. };
  167. void init() {
  168. driver = new Driver;
  169. midi::addDriver(DRIVER, driver);
  170. }
  171. void press(int key) {
  172. if (!driver)
  173. return;
  174. driver->onKeyPress(key);
  175. }
  176. void release(int key) {
  177. if (!driver)
  178. return;
  179. driver->onKeyRelease(key);
  180. }
  181. } // namespace keyboard
  182. } // namespace rack