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.

205 lines
4.3KB

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