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.

223 lines
4.6KB

  1. #include "midi.hpp"
  2. #include "bridge.hpp"
  3. namespace rack {
  4. ////////////////////
  5. // MidiIO
  6. ////////////////////
  7. std::vector<int> MidiIO::getDrivers() {
  8. std::vector<RtMidi::Api> rtApis;
  9. RtMidi::getCompiledApi(rtApis);
  10. std::vector<int> drivers;
  11. for (RtMidi::Api api : rtApis) {
  12. drivers.push_back((int) api);
  13. }
  14. // Add fake Bridge driver
  15. drivers.push_back(BRIDGE_DRIVER);
  16. return drivers;
  17. }
  18. std::string MidiIO::getDriverName(int driver) {
  19. switch (driver) {
  20. case RtMidi::UNSPECIFIED: return "Unspecified";
  21. case RtMidi::MACOSX_CORE: return "Core MIDI";
  22. case RtMidi::LINUX_ALSA: return "ALSA";
  23. case RtMidi::UNIX_JACK: return "JACK";
  24. case RtMidi::WINDOWS_MM: return "Windows MIDI";
  25. case RtMidi::RTMIDI_DUMMY: return "Dummy MIDI";
  26. case BRIDGE_DRIVER: return "Bridge";
  27. default: return "Unknown";
  28. }
  29. }
  30. int MidiIO::getDeviceCount() {
  31. if (rtMidi) {
  32. return rtMidi->getPortCount();
  33. }
  34. else if (driver == BRIDGE_DRIVER) {
  35. return BRIDGE_NUM_PORTS;
  36. }
  37. return 0;
  38. }
  39. std::string MidiIO::getDeviceName(int device) {
  40. if (device < 0)
  41. return "";
  42. if (rtMidi) {
  43. if (device == this->device)
  44. return deviceName;
  45. else
  46. return rtMidi->getPortName(device);
  47. }
  48. else if (driver == BRIDGE_DRIVER) {
  49. return stringf("Port %d", device + 1);
  50. }
  51. return "";
  52. }
  53. void MidiIO::setDevice(int device) {
  54. if (rtMidi) {
  55. rtMidi->closePort();
  56. if (device >= 0) {
  57. rtMidi->openPort(device);
  58. deviceName = rtMidi->getPortName(device);
  59. }
  60. this->device = device;
  61. }
  62. else if (driver == BRIDGE_DRIVER) {
  63. if (device >= 0) {
  64. bridgeMidiSubscribe(device, this);
  65. }
  66. else {
  67. bridgeMidiUnsubscribe(device, this);
  68. }
  69. this->device = device;
  70. }
  71. }
  72. std::string MidiIO::getChannelName(int channel) {
  73. if (channel == -1)
  74. return "All channels";
  75. else
  76. return stringf("Channel %d", channel + 1);
  77. }
  78. json_t *MidiIO::toJson() {
  79. json_t *rootJ = json_object();
  80. json_object_set_new(rootJ, "driver", json_integer(driver));
  81. std::string deviceName = getDeviceName(device);
  82. if (!deviceName.empty())
  83. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  84. json_object_set_new(rootJ, "channel", json_integer(channel));
  85. return rootJ;
  86. }
  87. void MidiIO::fromJson(json_t *rootJ) {
  88. json_t *driverJ = json_object_get(rootJ, "driver");
  89. if (driverJ)
  90. setDriver(json_integer_value(driverJ));
  91. json_t *deviceNameJ = json_object_get(rootJ, "deviceName");
  92. if (deviceNameJ) {
  93. std::string deviceName = json_string_value(deviceNameJ);
  94. // Search for device with equal name
  95. int deviceCount = getDeviceCount();
  96. for (int device = 0; device < deviceCount; device++) {
  97. if (getDeviceName(device) == deviceName) {
  98. setDevice(device);
  99. break;
  100. }
  101. }
  102. }
  103. json_t *channelJ = json_object_get(rootJ, "channel");
  104. if (channelJ)
  105. channel = json_integer_value(channelJ);
  106. }
  107. ////////////////////
  108. // MidiInput
  109. ////////////////////
  110. static void midiInputCallback(double timeStamp, std::vector<unsigned char> *message, void *userData) {
  111. if (!message) return;
  112. if (!userData) return;
  113. MidiInput *midiInput = (MidiInput*) userData;
  114. if (!midiInput) return;
  115. MidiMessage msg;
  116. if (message->size() >= 1)
  117. msg.cmd = (*message)[0];
  118. if (message->size() >= 2)
  119. msg.data1 = (*message)[1];
  120. if (message->size() >= 3)
  121. msg.data2 = (*message)[2];
  122. midiInput->onMessage(msg);
  123. }
  124. MidiInput::MidiInput() {
  125. setDriver(RtMidi::UNSPECIFIED);
  126. }
  127. MidiInput::~MidiInput() {
  128. setDriver(-1);
  129. }
  130. void MidiInput::setDriver(int driver) {
  131. setDevice(-1);
  132. if (rtMidiIn) {
  133. delete rtMidiIn;
  134. rtMidi = rtMidiIn = NULL;
  135. }
  136. if (driver >= 0) {
  137. rtMidiIn = new RtMidiIn((RtMidi::Api) driver);
  138. rtMidiIn->setCallback(midiInputCallback, this);
  139. rtMidiIn->ignoreTypes(false, false, false);
  140. rtMidi = rtMidiIn;
  141. this->driver = rtMidiIn->getCurrentApi();
  142. }
  143. else if (driver == BRIDGE_DRIVER) {
  144. this->driver = BRIDGE_DRIVER;
  145. }
  146. }
  147. void MidiInputQueue::onMessage(MidiMessage message) {
  148. // Filter channel
  149. if (channel >= 0) {
  150. if (message.status() != 0xf && message.channel() != channel)
  151. return;
  152. }
  153. if ((int) queue.size() < queueSize)
  154. queue.push(message);
  155. }
  156. bool MidiInputQueue::shift(MidiMessage *message) {
  157. if (!message) return false;
  158. if (!queue.empty()) {
  159. *message = queue.front();
  160. queue.pop();
  161. return true;
  162. }
  163. return false;
  164. }
  165. ////////////////////
  166. // MidiOutput
  167. ////////////////////
  168. MidiOutput::MidiOutput() {
  169. setDriver(RtMidi::UNSPECIFIED);
  170. }
  171. MidiOutput::~MidiOutput() {
  172. setDriver(-1);
  173. }
  174. void MidiOutput::setDriver(int driver) {
  175. setDevice(-1);
  176. if (rtMidiOut) {
  177. delete rtMidiOut;
  178. rtMidi = rtMidiOut = NULL;
  179. }
  180. if (driver >= 0) {
  181. rtMidiOut = new RtMidiOut((RtMidi::Api) driver);
  182. rtMidi = rtMidiOut;
  183. this->driver = rtMidiOut->getCurrentApi();
  184. }
  185. }
  186. } // namespace rack