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.

425 lines
8.3KB

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