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.

239 lines
4.4KB

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