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.

500 lines
10KB

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