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.

503 lines
10KB

  1. #include <map>
  2. #include <utility>
  3. #include <queue>
  4. #include <mutex>
  5. #include <tuple>
  6. #include <midi.hpp>
  7. #include <string.hpp>
  8. #include <system.hpp>
  9. #include <context.hpp>
  10. #include <engine/Engine.hpp>
  11. namespace rack {
  12. namespace midi {
  13. static std::vector<std::pair<int, Driver*>> drivers;
  14. std::string Message::toString() const {
  15. std::string s;
  16. for (size_t i = 0; i < bytes.size(); i++) {
  17. if (i > 0)
  18. s += " ";
  19. uint8_t b = bytes[i];
  20. // We could use string::f() here, but use faster method instead.
  21. // s += string::f("%02x", b);
  22. uint8_t b1 = (b & 0x0f) >> 0;
  23. uint8_t b2 = (b & 0xf0) >> 4;
  24. s += b2 < 0xa ? ('0' + b2) : ('a' + b2 - 0xa);
  25. s += b1 < 0xa ? ('0' + b1) : ('a' + b1 - 0xa);
  26. }
  27. return s;
  28. }
  29. ////////////////////
  30. // Device
  31. ////////////////////
  32. void InputDevice::subscribe(Input* input) {
  33. subscribed.insert(input);
  34. }
  35. void InputDevice::unsubscribe(Input* input) {
  36. // Remove Input from subscriptions
  37. auto it = subscribed.find(input);
  38. if (it != subscribed.end())
  39. subscribed.erase(it);
  40. }
  41. void InputDevice::onMessage(const Message& message) {
  42. for (Input* input : subscribed) {
  43. // Filter channel if message is not a system MIDI message
  44. if (message.getStatus() != 0xf && input->channel >= 0 && message.getChannel() != input->channel)
  45. continue;
  46. // We're probably in the MIDI driver's thread, so set the Rack context.
  47. contextSet(input->context);
  48. // Set timestamp to now if unset
  49. if (message.getFrame() < 0) {
  50. Message msg = message;
  51. double deltaTime = system::getTime() - APP->engine->getBlockTime();
  52. int64_t deltaFrames = std::floor(deltaTime * APP->engine->getSampleRate());
  53. // Delay message by current Engine block size
  54. deltaFrames += APP->engine->getBlockFrames();
  55. msg.setFrame(APP->engine->getBlockFrame() + deltaFrames);
  56. // Pass message to Input port
  57. input->onMessage(msg);
  58. }
  59. else {
  60. // Pass message to Input port
  61. input->onMessage(message);
  62. }
  63. }
  64. }
  65. void OutputDevice::subscribe(Output* output) {
  66. subscribed.insert(output);
  67. }
  68. void OutputDevice::unsubscribe(Output* output) {
  69. auto it = subscribed.find(output);
  70. if (it != subscribed.end())
  71. subscribed.erase(it);
  72. }
  73. ////////////////////
  74. // Port
  75. ////////////////////
  76. Port::Port() {
  77. context = contextGet();
  78. }
  79. Port::~Port() {
  80. }
  81. Driver* Port::getDriver() {
  82. return driver;
  83. }
  84. int Port::getDriverId() {
  85. return driverId;
  86. }
  87. void Port::setDriverId(int driverId) {
  88. // Unset device and driver
  89. setDeviceId(-1);
  90. driver = NULL;
  91. this->driverId = -1;
  92. // Find driver by ID
  93. driver = midi::getDriver(driverId);
  94. if (driver) {
  95. this->driverId = driverId;
  96. }
  97. else if (!drivers.empty()) {
  98. // Set first driver as default
  99. driver = drivers[0].second;
  100. this->driverId = drivers[0].first;
  101. }
  102. else {
  103. // No fallback drivers
  104. return;
  105. }
  106. // Set default device if exists
  107. int defaultDeviceId = getDefaultDeviceId();
  108. if (defaultDeviceId >= 0)
  109. setDeviceId(defaultDeviceId);
  110. }
  111. Device* Port::getDevice() {
  112. return device;
  113. }
  114. int Port::getDeviceId() {
  115. return deviceId;
  116. }
  117. int Port::getChannel() {
  118. return channel;
  119. }
  120. void Port::setChannel(int channel) {
  121. this->channel = channel;
  122. }
  123. std::string Port::getChannelName(int channel) {
  124. if (channel < 0)
  125. return "All channels";
  126. else
  127. return string::f("Channel %d", channel + 1);
  128. }
  129. json_t* Port::toJson() {
  130. json_t* rootJ = json_object();
  131. json_object_set_new(rootJ, "driver", json_integer(getDriverId()));
  132. if (device) {
  133. std::string deviceName = device->getName();
  134. if (!deviceName.empty())
  135. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  136. }
  137. json_object_set_new(rootJ, "channel", json_integer(getChannel()));
  138. return rootJ;
  139. }
  140. void Port::fromJson(json_t* rootJ) {
  141. setDriverId(-1);
  142. json_t* driverJ = json_object_get(rootJ, "driver");
  143. if (driverJ)
  144. setDriverId(json_integer_value(driverJ));
  145. if (driver) {
  146. json_t* deviceNameJ = json_object_get(rootJ, "deviceName");
  147. if (deviceNameJ) {
  148. std::string deviceName = json_string_value(deviceNameJ);
  149. // Search for device ID with equal name
  150. for (int deviceId : getDeviceIds()) {
  151. if (getDeviceName(deviceId) == deviceName) {
  152. setDeviceId(deviceId);
  153. break;
  154. }
  155. }
  156. }
  157. }
  158. json_t* channelJ = json_object_get(rootJ, "channel");
  159. if (channelJ)
  160. channel = json_integer_value(channelJ);
  161. }
  162. ////////////////////
  163. // Input
  164. ////////////////////
  165. Input::Input() {
  166. reset();
  167. }
  168. Input::~Input() {
  169. setDeviceId(-1);
  170. }
  171. void Input::reset() {
  172. setDriverId(-1);
  173. channel = -1;
  174. }
  175. std::vector<int> Input::getDeviceIds() {
  176. if (!driver)
  177. return {};
  178. try {
  179. return driver->getInputDeviceIds();
  180. }
  181. catch (Exception& e) {
  182. WARN("MIDI port could not get input device IDs: %s", e.what());
  183. return {};
  184. }
  185. }
  186. int Input::getDefaultDeviceId() {
  187. if (!driver)
  188. return -1;
  189. try {
  190. return driver->getDefaultInputDeviceId();
  191. }
  192. catch (Exception& e) {
  193. WARN("MIDI port get default input device ID: %s", e.what());
  194. return -1;
  195. }
  196. }
  197. void Input::setDeviceId(int deviceId) {
  198. // Destroy device
  199. if (driver && this->deviceId >= 0) {
  200. try {
  201. driver->unsubscribeInput(this->deviceId, this);
  202. }
  203. catch (Exception& e) {
  204. WARN("MIDI port could not unsubscribe from input: %s", e.what());
  205. }
  206. }
  207. device = inputDevice = NULL;
  208. this->deviceId = -1;
  209. // Create device
  210. if (driver && deviceId >= 0) {
  211. try {
  212. device = inputDevice = driver->subscribeInput(deviceId, this);
  213. if (device) {
  214. this->deviceId = deviceId;
  215. }
  216. }
  217. catch (Exception& e) {
  218. WARN("MIDI port could not subscribe to input: %s", e.what());
  219. }
  220. }
  221. }
  222. std::string Input::getDeviceName(int deviceId) {
  223. if (!driver)
  224. return "";
  225. try {
  226. return driver->getInputDeviceName(deviceId);
  227. }
  228. catch (Exception& e) {
  229. WARN("MIDI port could not get input device name: %s", e.what());
  230. return "";
  231. }
  232. }
  233. std::vector<int> Input::getChannels() {
  234. std::vector<int> channels;
  235. for (int c = -1; c < 16; c++) {
  236. channels.push_back(c);
  237. }
  238. return channels;
  239. }
  240. ////////////////////
  241. // InputQueue
  242. ////////////////////
  243. struct SeqMessage {
  244. Message message;
  245. uint64_t seq;
  246. /** Returns whether `this` is LATER in time than `other`.
  247. If frame is same, compares `seq`.
  248. */
  249. bool operator<(const SeqMessage& other) const {
  250. return std::make_tuple(message.getFrame(), seq) > std::make_tuple(other.message.getFrame(), other.seq);
  251. }
  252. };
  253. static const size_t InputQueue_maxSize = 8192;
  254. struct InputQueue::Internal {
  255. std::priority_queue<SeqMessage> queue;
  256. std::mutex mutex;
  257. /** Index to preserve ordering for priority_queue since it's unstable.
  258. */
  259. uint64_t nextSeq = 0;
  260. };
  261. InputQueue::InputQueue() {
  262. internal = new Internal;
  263. }
  264. InputQueue::~InputQueue() {
  265. delete internal;
  266. }
  267. void InputQueue::onMessage(const Message& message) {
  268. std::lock_guard<std::mutex> lock(internal->mutex);
  269. // Reject MIDI message if queue is full
  270. if (internal->queue.size() >= InputQueue_maxSize)
  271. return;
  272. // Push to queue
  273. internal->queue.push({message, internal->nextSeq});
  274. internal->nextSeq++;
  275. }
  276. bool InputQueue::tryPop(Message* messageOut, int64_t maxFrame) {
  277. // Check if queue is empty before locking, to avoid frequent unnecessary locking
  278. if (internal->queue.empty())
  279. return false;
  280. std::lock_guard<std::mutex> lock(internal->mutex);
  281. if (internal->queue.empty())
  282. return false;
  283. const SeqMessage& s = internal->queue.top();
  284. if (s.message.getFrame() <= maxFrame) {
  285. *messageOut = s.message;
  286. internal->queue.pop();
  287. return true;
  288. }
  289. return false;
  290. }
  291. size_t InputQueue::size() {
  292. return internal->queue.size();
  293. }
  294. ////////////////////
  295. // Output
  296. ////////////////////
  297. Output::Output() {
  298. reset();
  299. }
  300. Output::~Output() {
  301. setDeviceId(-1);
  302. }
  303. void Output::reset() {
  304. setDriverId(-1);
  305. channel = 0;
  306. }
  307. std::vector<int> Output::getDeviceIds() {
  308. if (!driver)
  309. return {};
  310. try {
  311. return driver->getOutputDeviceIds();
  312. }
  313. catch (Exception& e) {
  314. WARN("MIDI port could not get output device IDs: %s", e.what());
  315. return {};
  316. }
  317. }
  318. void Output::setDeviceId(int deviceId) {
  319. // Destroy device
  320. if (driver && this->deviceId >= 0) {
  321. try {
  322. driver->unsubscribeOutput(this->deviceId, this);
  323. }
  324. catch (Exception& e) {
  325. WARN("MIDI port could not unsubscribe from output: %s", e.what());
  326. }
  327. }
  328. device = outputDevice = NULL;
  329. this->deviceId = -1;
  330. // Create device
  331. if (driver && deviceId >= 0) {
  332. try {
  333. device = outputDevice = driver->subscribeOutput(deviceId, this);
  334. if (device) {
  335. this->deviceId = deviceId;
  336. }
  337. }
  338. catch (Exception& e) {
  339. WARN("MIDI port could not subscribe to output: %s", e.what());
  340. }
  341. }
  342. }
  343. int Output::getDefaultDeviceId() {
  344. if (!driver)
  345. return -1;
  346. try {
  347. return driver->getDefaultOutputDeviceId();
  348. }
  349. catch (Exception& e) {
  350. WARN("MIDI port get default output device ID: %s", e.what());
  351. return -1;
  352. }
  353. }
  354. std::string Output::getDeviceName(int deviceId) {
  355. if (!driver)
  356. return "";
  357. try {
  358. return driver->getOutputDeviceName(deviceId);
  359. }
  360. catch (Exception& e) {
  361. WARN("MIDI port could not get output device name: %s", e.what());
  362. return "";
  363. }
  364. }
  365. std::vector<int> Output::getChannels() {
  366. std::vector<int> channels;
  367. for (int c = 0; c < 16; c++) {
  368. channels.push_back(c);
  369. }
  370. return channels;
  371. }
  372. void Output::sendMessage(const Message& message) {
  373. if (!outputDevice)
  374. return;
  375. // Set channel if message is not a system MIDI message
  376. Message msg = message;
  377. if (msg.getStatus() != 0xf && channel >= 0) {
  378. msg.setChannel(channel);
  379. }
  380. // DEBUG("sendMessage %02x %02x %02x", msg.cmd, msg.data1, msg.data2);
  381. try {
  382. outputDevice->sendMessage(msg);
  383. }
  384. catch (Exception& e) {
  385. // Don't log error because it could flood the log.
  386. // WARN("MIDI port could not be sent MIDI message: %s", e.what());
  387. // TODO Perhaps `setDevice(-1)` if sending message fails?
  388. }
  389. }
  390. ////////////////////
  391. // midi
  392. ////////////////////
  393. void init() {
  394. }
  395. void destroy() {
  396. for (auto& pair : drivers) {
  397. delete pair.second;
  398. }
  399. drivers.clear();
  400. }
  401. void addDriver(int driverId, Driver* driver) {
  402. assert(driver);
  403. drivers.push_back(std::make_pair(driverId, driver));
  404. }
  405. std::vector<int> getDriverIds() {
  406. std::vector<int> driverIds;
  407. for (auto& pair : drivers) {
  408. driverIds.push_back(pair.first);
  409. }
  410. return driverIds;
  411. }
  412. Driver* getDriver(int driverId) {
  413. // Search for driver by ID
  414. for (auto& pair : drivers) {
  415. if (pair.first == driverId)
  416. return pair.second;
  417. }
  418. return NULL;
  419. }
  420. } // namespace midi
  421. } // namespace rack