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.

430 lines
8.9KB

  1. #include <audio.hpp>
  2. #include <string.hpp>
  3. namespace rack {
  4. namespace audio {
  5. static std::vector<std::pair<int, Driver*>> drivers;
  6. static std::string getDetailTemplate(std::string name, int numInputs, int numOutputs, int offset, int maxChannels) {
  7. std::string text = name;
  8. text += " (";
  9. if (offset < numInputs) {
  10. text += string::f("%d-%d in", offset + 1, std::min(offset + maxChannels, numInputs));
  11. }
  12. if (offset < numInputs && offset < numOutputs) {
  13. text += ", ";
  14. }
  15. if (offset < numOutputs) {
  16. text += string::f("%d-%d out", offset + 1, std::min(offset + maxChannels, numOutputs));
  17. }
  18. text += ")";
  19. return text;
  20. }
  21. ////////////////////
  22. // Driver
  23. ////////////////////
  24. std::string Driver::getDeviceDetail(int deviceId, int offset, int maxChannels) {
  25. if (deviceId < 0)
  26. return "";
  27. return getDetailTemplate(getDeviceName(deviceId), getDeviceNumInputs(deviceId), getDeviceNumOutputs(deviceId), offset, maxChannels);
  28. }
  29. ////////////////////
  30. // Device
  31. ////////////////////
  32. void Device::subscribe(Port* port) {
  33. subscribed.insert(port);
  34. }
  35. void Device::unsubscribe(Port* port) {
  36. auto it = subscribed.find(port);
  37. if (it != subscribed.end())
  38. subscribed.erase(it);
  39. }
  40. std::string Device::getDetail(int offset, int maxChannels) {
  41. return getDetailTemplate(getName(), getNumInputs(), getNumOutputs(), offset, maxChannels);
  42. }
  43. void Device::processBuffer(const float* input, int inputStride, float* output, int outputStride, int frames) {
  44. for (Port* port : subscribed) {
  45. // Setting the thread context should probably be the responsibility of Port, but because processInput() etc are overridden, this is the only good place for it.
  46. contextSet(port->context);
  47. port->processInput(input + port->offset, inputStride, frames);
  48. }
  49. for (Port* port : subscribed) {
  50. contextSet(port->context);
  51. port->processBuffer(input + port->offset, inputStride, output + port->offset, outputStride, frames);
  52. }
  53. for (Port* port : subscribed) {
  54. contextSet(port->context);
  55. port->processOutput(output + port->offset, outputStride, frames);
  56. }
  57. }
  58. void Device::onOpenStream() {
  59. for (Port* port : subscribed) {
  60. contextSet(port->context);
  61. port->onOpenStream();
  62. }
  63. }
  64. void Device::onCloseStream() {
  65. for (Port* port : subscribed) {
  66. contextSet(port->context);
  67. port->onCloseStream();
  68. }
  69. }
  70. ////////////////////
  71. // Port
  72. ////////////////////
  73. Port::Port() {
  74. context = contextGet();
  75. reset();
  76. }
  77. Port::~Port() {
  78. setDriverId(-1);
  79. }
  80. void Port::reset() {
  81. // Get default driver
  82. int firstDriverId = -1;
  83. std::vector<int> driverIds = getDriverIds();
  84. if (!driverIds.empty())
  85. firstDriverId = driverIds[0];
  86. setDriverId(firstDriverId);
  87. offset = 0;
  88. }
  89. Driver* Port::getDriver() {
  90. return driver;
  91. }
  92. int Port::getDriverId() {
  93. return driverId;
  94. }
  95. void Port::setDriverId(int driverId) {
  96. if (driverId == this->driverId)
  97. return;
  98. // Unset device and driver
  99. setDeviceId(-1);
  100. driver = NULL;
  101. this->driverId = -1;
  102. // Find driver by ID
  103. driver = audio::getDriver(driverId);
  104. if (driver) {
  105. this->driverId = driverId;
  106. }
  107. else {
  108. // Set first driver as default
  109. driver = drivers[0].second;
  110. this->driverId = drivers[0].first;
  111. }
  112. }
  113. std::string Port::getDriverName() {
  114. if (!driver)
  115. return "";
  116. try {
  117. return driver->getName();
  118. }
  119. catch (Exception& e) {
  120. WARN("Audio port could not get driver name: %s", e.what());
  121. return "";
  122. }
  123. }
  124. Device* Port::getDevice() {
  125. return device;
  126. }
  127. std::vector<int> Port::getDeviceIds() {
  128. if (!driver)
  129. return {};
  130. try {
  131. return driver->getDeviceIds();
  132. }
  133. catch (Exception& e) {
  134. WARN("Audio port could not get device IDs: %s", e.what());
  135. return {};
  136. }
  137. }
  138. int Port::getDeviceId() {
  139. return deviceId;
  140. }
  141. void Port::setDeviceId(int deviceId) {
  142. if (deviceId == this->deviceId)
  143. return;
  144. // Destroy device
  145. if (driver && this->deviceId >= 0) {
  146. try {
  147. driver->unsubscribe(this->deviceId, this);
  148. }
  149. catch (Exception& e) {
  150. WARN("Audio port could not unsubscribe from device: %s", e.what());
  151. }
  152. }
  153. device = NULL;
  154. this->deviceId = -1;
  155. // Create device
  156. if (driver && deviceId >= 0) {
  157. try {
  158. device = driver->subscribe(deviceId, this);
  159. this->deviceId = deviceId;
  160. }
  161. catch (Exception& e) {
  162. WARN("Audio port could not subscribe to device: %s", e.what());
  163. }
  164. }
  165. }
  166. int Port::getDeviceNumInputs(int deviceId) {
  167. if (!driver)
  168. return 0;
  169. try {
  170. return driver->getDeviceNumInputs(deviceId);
  171. }
  172. catch (Exception& e) {
  173. WARN("Audio port could not get device number of inputs: %s", e.what());
  174. return 0;
  175. }
  176. }
  177. int Port::getDeviceNumOutputs(int deviceId) {
  178. if (!driver)
  179. return 0;
  180. try {
  181. return driver->getDeviceNumOutputs(deviceId);
  182. }
  183. catch (Exception& e) {
  184. WARN("Audio port could not get device number of outputs: %s", e.what());
  185. return 0;
  186. }
  187. }
  188. std::string Port::getDeviceName(int deviceId) {
  189. if (!driver)
  190. return "";
  191. try {
  192. return driver->getDeviceName(deviceId);
  193. }
  194. catch (Exception& e) {
  195. WARN("Audio port could not get device name: %s", e.what());
  196. return 0;
  197. }
  198. }
  199. std::string Port::getDeviceDetail(int deviceId, int offset) {
  200. if (!driver)
  201. return "";
  202. try {
  203. // Use maxChannels from Port.
  204. return driver->getDeviceDetail(deviceId, offset, maxChannels);
  205. }
  206. catch (Exception& e) {
  207. WARN("Audio port could not get device detail: %s", e.what());
  208. return 0;
  209. }
  210. }
  211. std::set<int> Port::getSampleRates() {
  212. if (!device)
  213. return {};
  214. try {
  215. return device->getSampleRates();
  216. }
  217. catch (Exception& e) {
  218. WARN("Audio port could not get device sample rates: %s", e.what());
  219. return {};
  220. }
  221. }
  222. int Port::getSampleRate() {
  223. if (!device)
  224. return 0;
  225. try {
  226. return device->getSampleRate();
  227. }
  228. catch (Exception& e) {
  229. WARN("Audio port could not get device sample rate: %s", e.what());
  230. return 0;
  231. }
  232. }
  233. void Port::setSampleRate(int sampleRate) {
  234. if (!device)
  235. return;
  236. try {
  237. device->setSampleRate(sampleRate);
  238. }
  239. catch (Exception& e) {
  240. WARN("Audio port could not set device sample rate: %s", e.what());
  241. }
  242. }
  243. std::set<int> Port::getBlockSizes() {
  244. if (!device)
  245. return {};
  246. try {
  247. return device->getBlockSizes();
  248. }
  249. catch (Exception& e) {
  250. WARN("Audio port could not get device block sizes: %s", e.what());
  251. return {};
  252. }
  253. }
  254. int Port::getBlockSize() {
  255. if (!device)
  256. return 0;
  257. try {
  258. return device->getBlockSize();
  259. }
  260. catch (Exception& e) {
  261. WARN("Audio port could not get device block size: %s", e.what());
  262. return 0;
  263. }
  264. }
  265. void Port::setBlockSize(int blockSize) {
  266. if (!device)
  267. return;
  268. try {
  269. device->setBlockSize(blockSize);
  270. }
  271. catch (Exception& e) {
  272. WARN("Audio port could not set device block size: %s", e.what());
  273. }
  274. }
  275. int Port::getNumInputs() {
  276. if (!device)
  277. return 0;
  278. try {
  279. return std::min(device->getNumInputs() - offset, maxChannels);
  280. }
  281. catch (Exception& e) {
  282. WARN("Audio port could not get device number of inputs: %s", e.what());
  283. return 0;
  284. }
  285. }
  286. int Port::getNumOutputs() {
  287. if (!device)
  288. return 0;
  289. try {
  290. return std::min(device->getNumOutputs() - offset, maxChannels);
  291. }
  292. catch (Exception& e) {
  293. WARN("Audio port could not get device number of outputs: %s", e.what());
  294. return 0;
  295. }
  296. }
  297. json_t* Port::toJson() {
  298. json_t* rootJ = json_object();
  299. json_object_set_new(rootJ, "driver", json_integer(getDriverId()));
  300. if (device) {
  301. std::string deviceName = device->getName();
  302. json_object_set_new(rootJ, "deviceName", json_string(deviceName.c_str()));
  303. }
  304. json_object_set_new(rootJ, "sampleRate", json_integer(getSampleRate()));
  305. json_object_set_new(rootJ, "blockSize", json_integer(getBlockSize()));
  306. json_object_set_new(rootJ, "offset", json_integer(offset));
  307. return rootJ;
  308. }
  309. void Port::fromJson(json_t* rootJ) {
  310. setDriverId(-1);
  311. json_t* driverJ = json_object_get(rootJ, "driver");
  312. if (driverJ)
  313. setDriverId(json_number_value(driverJ));
  314. if (driver) {
  315. json_t* deviceNameJ = json_object_get(rootJ, "deviceName");
  316. if (deviceNameJ) {
  317. std::string deviceName = json_string_value(deviceNameJ);
  318. // Search for device ID with equal name
  319. for (int deviceId : getDeviceIds()) {
  320. std::string deviceNameCurr = getDeviceName(deviceId);
  321. if (deviceNameCurr == "")
  322. continue;
  323. if (deviceNameCurr == deviceName) {
  324. setDeviceId(deviceId);
  325. break;
  326. }
  327. }
  328. }
  329. }
  330. json_t* sampleRateJ = json_object_get(rootJ, "sampleRate");
  331. if (sampleRateJ)
  332. setSampleRate(json_integer_value(sampleRateJ));
  333. json_t* blockSizeJ = json_object_get(rootJ, "blockSize");
  334. if (blockSizeJ)
  335. setBlockSize(json_integer_value(blockSizeJ));
  336. json_t* offsetJ = json_object_get(rootJ, "offset");
  337. if (offsetJ)
  338. offset = json_integer_value(offsetJ);
  339. }
  340. ////////////////////
  341. // audio
  342. ////////////////////
  343. void init() {
  344. }
  345. void destroy() {
  346. for (auto& pair : drivers) {
  347. delete pair.second;
  348. }
  349. drivers.clear();
  350. }
  351. void addDriver(int driverId, Driver* driver) {
  352. assert(driver);
  353. drivers.push_back(std::make_pair(driverId, driver));
  354. }
  355. std::vector<int> getDriverIds() {
  356. std::vector<int> driverIds;
  357. for (auto& pair : drivers) {
  358. driverIds.push_back(pair.first);
  359. }
  360. return driverIds;
  361. }
  362. Driver* getDriver(int driverId) {
  363. // Search for driver by ID
  364. for (auto& pair : drivers) {
  365. if (pair.first == driverId)
  366. return pair.second;
  367. }
  368. return NULL;
  369. }
  370. } // namespace audio
  371. } // namespace rack