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.

212 lines
4.3KB

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