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.

504 lines
10KB

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