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.

220 lines
4.3KB

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