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.

226 lines
4.4KB

  1. #include "midi.hpp"
  2. #include "rtmidi.hpp"
  3. #include "bridge.hpp"
  4. #include "gamepad.hpp"
  5. #include "keyboard.hpp"
  6. namespace rack {
  7. ////////////////////
  8. // MidiIODevice
  9. ////////////////////
  10. void MidiInputDevice::subscribe(MidiInput *midiInput) {
  11. subscribed.insert(midiInput);
  12. }
  13. void MidiInputDevice::unsubscribe(MidiInput *midiInput) {
  14. auto it = subscribed.find(midiInput);
  15. if (it != subscribed.end())
  16. subscribed.erase(it);
  17. if (subscribed.size() == 0) {
  18. warn("TODO: Fix memory leak");
  19. }
  20. }
  21. void MidiInputDevice::onMessage(MidiMessage message) {
  22. for (MidiInput *midiInput : subscribed) {
  23. midiInput->onMessage(message);
  24. }
  25. }
  26. ////////////////////
  27. // MidiIODriver
  28. ////////////////////
  29. ////////////////////
  30. // MidiIO
  31. ////////////////////
  32. std::vector<int> MidiIO::getDriverIds() {
  33. std::vector<int> driverIds = rtmidiGetDrivers();
  34. // Add custom driverIds
  35. driverIds.push_back(BRIDGE_DRIVER);
  36. driverIds.push_back(GAMEPAD_DRIVER);
  37. driverIds.push_back(KEYBOARD_DRIVER);
  38. return driverIds;
  39. }
  40. std::string MidiIO::getDriverName(int driverId) {
  41. switch (driverId) {
  42. case -1: return "None";
  43. case RtMidi::UNSPECIFIED: return "Unspecified";
  44. case RtMidi::MACOSX_CORE: return "Core MIDI";
  45. case RtMidi::LINUX_ALSA: return "ALSA";
  46. case RtMidi::UNIX_JACK: return "JACK";
  47. case RtMidi::WINDOWS_MM: return "Windows MIDI";
  48. case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI";
  49. case BRIDGE_DRIVER: return "Bridge";
  50. case GAMEPAD_DRIVER: return "Gamepad";
  51. case KEYBOARD_DRIVER: return "Computer keyboard";
  52. default: return "Unknown";
  53. }
  54. }
  55. std::string MidiIO::getChannelName(int channel) {
  56. if (channel == -1)
  57. return "All channels";
  58. else
  59. return stringf("Channel %d", channel + 1);
  60. }
  61. json_t *MidiIO::toJson() {
  62. json_t *rootJ = json_object();
  63. json_object_set_new(rootJ, "driver", json_integer(driverId));
  64. std::string deviceName = getDeviceName(deviceId);
  65. if (!deviceName.empty())
  66. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  67. json_object_set_new(rootJ, "channel", json_integer(channel));
  68. return rootJ;
  69. }
  70. void MidiIO::fromJson(json_t *rootJ) {
  71. json_t *driverJ = json_object_get(rootJ, "driver");
  72. if (driverJ)
  73. setDriverId(json_integer_value(driverJ));
  74. json_t *deviceNameJ = json_object_get(rootJ, "deviceName");
  75. if (deviceNameJ) {
  76. std::string deviceName = json_string_value(deviceNameJ);
  77. // Search for device with equal name
  78. for (int deviceId : getDeviceIds()) {
  79. if (getDeviceName(deviceId) == deviceName) {
  80. setDeviceId(deviceId);
  81. break;
  82. }
  83. }
  84. }
  85. json_t *channelJ = json_object_get(rootJ, "channel");
  86. if (channelJ)
  87. channel = json_integer_value(channelJ);
  88. }
  89. ////////////////////
  90. // MidiInput
  91. ////////////////////
  92. MidiInput::MidiInput() {
  93. }
  94. MidiInput::~MidiInput() {
  95. setDriverId(-1);
  96. }
  97. void MidiInput::setDriverId(int driverId) {
  98. // Destroy driver
  99. setDeviceId(-1);
  100. if (driver) {
  101. driver = NULL;
  102. }
  103. this->driverId = -1;
  104. // Create driver
  105. if (driverId >= 0) {
  106. driver = rtmidiGetInputDriver(driverId);
  107. }
  108. else if (driverId == BRIDGE_DRIVER) {
  109. // TODO
  110. }
  111. else if (driverId == GAMEPAD_DRIVER) {
  112. driver = gamepadGetInputDriver();
  113. }
  114. else if (driverId == KEYBOARD_DRIVER) {
  115. driver = keyboardGetInputDriver();
  116. }
  117. // Set driverId
  118. if (driver) {
  119. this->driverId = driverId;
  120. }
  121. }
  122. std::vector<int> MidiInput::getDeviceIds() {
  123. if (driver) {
  124. return driver->getDeviceIds();
  125. }
  126. return {};
  127. }
  128. std::string MidiInput::getDeviceName(int deviceId) {
  129. if (driver) {
  130. return driver->getDeviceName(deviceId);
  131. }
  132. return "";
  133. }
  134. void MidiInput::setDeviceId(int deviceId) {
  135. // Destroy device
  136. if (device) {
  137. device->unsubscribe(this);
  138. device = NULL;
  139. }
  140. this->deviceId = -1;
  141. // Create device
  142. if (driver && deviceId >= 0) {
  143. device = driver->getDevice(deviceId);
  144. device->subscribe(this);
  145. }
  146. // Set deviceId
  147. if (device) {
  148. this->deviceId = deviceId;
  149. }
  150. }
  151. void MidiInputQueue::onMessage(MidiMessage message) {
  152. // Filter channel
  153. if (channel >= 0) {
  154. if (message.status() != 0xf && message.channel() != channel)
  155. return;
  156. }
  157. // Push to queue
  158. if ((int) queue.size() < queueSize)
  159. queue.push(message);
  160. }
  161. bool MidiInputQueue::shift(MidiMessage *message) {
  162. if (!message) return false;
  163. if (!queue.empty()) {
  164. *message = queue.front();
  165. queue.pop();
  166. return true;
  167. }
  168. return false;
  169. }
  170. ////////////////////
  171. // MidiOutput
  172. ////////////////////
  173. MidiOutput::MidiOutput() {
  174. }
  175. MidiOutput::~MidiOutput() {
  176. // TODO
  177. }
  178. void MidiOutput::setDriverId(int driverId) {
  179. // TODO
  180. }
  181. void MidiOutput::setDeviceId(int deviceId) {
  182. // TODO
  183. }
  184. } // namespace rack