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.

264 lines
5.6KB

  1. #if 0
  2. #include <list>
  3. #include <algorithm>
  4. #include "core.hpp"
  5. #include "MidiIO.hpp"
  6. using namespace rack;
  7. /**
  8. * MidiIO implements the shared functionality of all midi modules, namely:
  9. * + Channel Selection (including helper for storing json)
  10. * + Interface Selection (including helper for storing json)
  11. * + rtMidi initialisation (input or output)
  12. */
  13. MidiIO::MidiIO(bool isOut) {
  14. channel = -1;
  15. this->isOut = isOut;
  16. // TODO
  17. // Support MIDI out
  18. assert(!isOut);
  19. };
  20. void MidiIO::setChannel(int channel) {
  21. this->channel = channel;
  22. }
  23. std::unordered_map<std::string, MidiInWrapper *> MidiIO::midiInMap = {};
  24. json_t *MidiIO::addBaseJson(json_t *rootJ) {
  25. if (deviceName != "") {
  26. json_object_set_new(rootJ, "interfaceName", json_string(deviceName.c_str()));
  27. json_object_set_new(rootJ, "channel", json_integer(channel));
  28. }
  29. return rootJ;
  30. }
  31. void MidiIO::baseFromJson(json_t *rootJ) {
  32. json_t *portNameJ = json_object_get(rootJ, "interfaceName");
  33. if (portNameJ) {
  34. openDevice(json_string_value(portNameJ));
  35. }
  36. json_t *channelJ = json_object_get(rootJ, "channel");
  37. if (channelJ) {
  38. setChannel(json_integer_value(channelJ));
  39. }
  40. }
  41. std::vector<std::string> MidiIO::getDevices() {
  42. std::vector<std::string> names = {};
  43. if (isOut) {
  44. // TODO
  45. return names;
  46. }
  47. RtMidiIn *m;
  48. try {
  49. m = new RtMidiIn();
  50. }
  51. catch (RtMidiError &error) {
  52. warn("Failed to create RtMidiIn: %s", error.getMessage().c_str());
  53. return names;
  54. }
  55. for (unsigned int i = 0; i < m->getPortCount(); i++) {
  56. names.push_back(m->getPortName(i));
  57. }
  58. if (!isPortOpen())
  59. delete (m);
  60. return names;
  61. }
  62. void MidiIO::openDevice(std::string deviceName) {
  63. if (this->id > 0 || this->deviceName != "") {
  64. close();
  65. }
  66. MidiInWrapper *mw = midiInMap[deviceName];
  67. if (!mw) {
  68. try {
  69. mw = new MidiInWrapper();
  70. midiInMap[deviceName] = mw;
  71. for (unsigned int i = 0; i < mw->getPortCount(); i++) {
  72. if (deviceName == mw->getPortName(i)) {
  73. mw->openPort(i);
  74. break;
  75. }
  76. }
  77. if (!mw->isPortOpen()) {
  78. warn("Failed to create RtMidiIn: No such device %s", deviceName.c_str());
  79. this->deviceName = "";
  80. this->id = -1;
  81. return;
  82. }
  83. }
  84. catch (RtMidiError &error) {
  85. warn("Failed to create RtMidiIn: %s", error.getMessage().c_str());
  86. this->deviceName = "";
  87. this->id = -1;
  88. return;
  89. }
  90. }
  91. this->deviceName = deviceName;
  92. id = midiInMap[deviceName]->add();
  93. onDeviceChange();
  94. }
  95. void MidiIO::setIgnores(bool ignoreSysex, bool ignoreTime, bool ignoreSense) {
  96. bool sy = true, ti = true, se = true;
  97. midiInMap[deviceName]->ignoresMap[id].midiSysex = ignoreSysex;
  98. midiInMap[deviceName]->ignoresMap[id].midiTime = ignoreTime;
  99. midiInMap[deviceName]->ignoresMap[id].midiSense = ignoreSense;
  100. for (auto kv : midiInMap[deviceName]->ignoresMap) {
  101. sy = sy && kv.second.midiSysex;
  102. ti = ti && kv.second.midiTime;
  103. se = se && kv.second.midiSense;
  104. }
  105. midiInMap[deviceName]->ignoreTypes(se, ti, se);
  106. }
  107. std::string MidiIO::getDeviceName() {
  108. return deviceName;
  109. }
  110. double MidiIO::getMessage(std::vector<unsigned char> *msg) {
  111. MidiMessage next_msg = MidiMessage();
  112. MidiInWrapper *mw = midiInMap[deviceName];
  113. if (!mw) {
  114. warn("Device not opened!: %s", deviceName.c_str());
  115. return 0;
  116. }
  117. next_msg.timeStamp = mw->getMessage(&next_msg.bytes);
  118. if (next_msg.bytes.size() > 0) {
  119. for (auto &kv : mw->idMessagesMap) {
  120. kv.second.push_back(next_msg);
  121. }
  122. }
  123. if (mw->idMessagesMap[id].size() > 0) {
  124. next_msg = mw->idMessagesMap[id].front();
  125. mw->idMessagesMap[id].pop_front();
  126. }
  127. *msg = next_msg.bytes;
  128. return next_msg.timeStamp;
  129. }
  130. bool MidiIO::isPortOpen() {
  131. return id > 0;
  132. }
  133. void MidiIO::close() {
  134. MidiInWrapper *mw = midiInMap[deviceName];
  135. if (!mw || id < 0) {
  136. //warn("Trying to close already closed device!");
  137. return;
  138. }
  139. setIgnores(); // reset ignore types for this instance
  140. mw->erase(id);
  141. if (mw->idMessagesMap.size() == 0) {
  142. mw->closePort();
  143. midiInMap.erase(deviceName);
  144. delete (mw);
  145. }
  146. id = -1;
  147. deviceName = "";
  148. }
  149. void MidiItem::onAction(EventAction &e) {
  150. midiModule->resetMidi(); // reset Midi values
  151. midiModule->openDevice(text);
  152. }
  153. void MidiChoice::onAction(EventAction &e) {
  154. Menu *menu = gScene->createMenu();
  155. menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
  156. menu->box.size.x = box.size.x;
  157. {
  158. MidiItem *midiItem = new MidiItem();
  159. midiItem->midiModule = midiModule;
  160. midiItem->text = "";
  161. menu->addChild(midiItem);
  162. }
  163. std::vector<std::string> deviceNames = midiModule->getDevices();
  164. for (unsigned int i = 0; i < deviceNames.size(); i++) {
  165. MidiItem *midiItem = new MidiItem();
  166. midiItem->midiModule = midiModule;
  167. midiItem->text = deviceNames[i];
  168. menu->addChild(midiItem);
  169. }
  170. }
  171. void MidiChoice::step() {
  172. if (midiModule->getDeviceName() == "") {
  173. text = "No Device";
  174. return;
  175. }
  176. std::string name = midiModule->getDeviceName();
  177. text = ellipsize(name, 15);
  178. }
  179. void ChannelItem::onAction(EventAction &e) {
  180. midiModule->resetMidi(); // reset Midi values
  181. midiModule->setChannel(channel);
  182. }
  183. void ChannelChoice::onAction(EventAction &e) {
  184. Menu *menu = gScene->createMenu();
  185. menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
  186. menu->box.size.x = box.size.x;
  187. {
  188. ChannelItem *channelItem = new ChannelItem();
  189. channelItem->midiModule = midiModule;
  190. channelItem->channel = -1;
  191. channelItem->text = "All";
  192. menu->addChild(channelItem);
  193. }
  194. for (int channel = 0; channel < 16; channel++) {
  195. ChannelItem *channelItem = new ChannelItem();
  196. channelItem->midiModule = midiModule;
  197. channelItem->channel = channel;
  198. channelItem->text = stringf("%d", channel + 1);
  199. menu->addChild(channelItem);
  200. }
  201. }
  202. void ChannelChoice::step() {
  203. text = (midiModule->channel >= 0) ? stringf("%d", midiModule->channel + 1) : "All";
  204. }
  205. #endif