Audio plugin host https://kx.studio/carla
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.

CarlaEngineRtAudio.cpp 36KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  1. /*
  2. * Carla RtAudio Engine
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaEngineInternal.hpp"
  18. #include "CarlaBackendUtils.hpp"
  19. #include "CarlaMIDI.h"
  20. #include "RtList.hpp"
  21. #include "rtaudio/RtAudio.h"
  22. #include "rtmidi/RtMidi.h"
  23. CARLA_BACKEND_START_NAMESPACE
  24. #if 0
  25. } // Fix editor indentation
  26. #endif
  27. // -------------------------------------------------------------------------------------------------------------------
  28. static const char** gRetNames = nullptr;
  29. static std::vector<RtAudio::Api> gRtAudioApis;
  30. static void initRtApis()
  31. {
  32. if (gRtAudioApis.size() == 0)
  33. {
  34. RtAudio::getCompiledApi(gRtAudioApis);
  35. #ifdef HAVE_JUCE
  36. // prefer juce to handle some APIs
  37. std::vector<RtAudio::Api>::iterator it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::LINUX_ALSA);
  38. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  39. it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::MACOSX_CORE);
  40. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  41. it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::WINDOWS_ASIO);
  42. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  43. it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::WINDOWS_DS);
  44. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  45. #endif
  46. // in case rtaudio has no apis, add dummy one so that size() != 0
  47. if (gRtAudioApis.size() == 0)
  48. gRtAudioApis.push_back(RtAudio::RTAUDIO_DUMMY);
  49. }
  50. }
  51. const char* getRtAudioApiName(const RtAudio::Api api)
  52. {
  53. switch (api)
  54. {
  55. case RtAudio::UNSPECIFIED:
  56. return "Unspecified";
  57. case RtAudio::LINUX_ALSA:
  58. return "ALSA";
  59. case RtAudio::LINUX_PULSE:
  60. return "PulseAudio";
  61. case RtAudio::LINUX_OSS:
  62. return "OSS";
  63. case RtAudio::UNIX_JACK:
  64. #if defined(CARLA_OS_WIN)
  65. return "JACK with WinMM";
  66. #elif defined(CARLA_OS_MAC)
  67. return "JACK with CoreMidi";
  68. #elif defined(CARLA_OS_LINUX)
  69. return "JACK with ALSA-MIDI";
  70. #else
  71. return "JACK (RtAudio)";
  72. #endif
  73. case RtAudio::MACOSX_CORE:
  74. return "CoreAudio";
  75. case RtAudio::WINDOWS_ASIO:
  76. return "ASIO";
  77. case RtAudio::WINDOWS_DS:
  78. return "DirectSound";
  79. case RtAudio::RTAUDIO_DUMMY:
  80. return "Dummy";
  81. }
  82. carla_stderr("CarlaBackend::getRtAudioApiName(%i) - invalid API", api);
  83. return nullptr;
  84. }
  85. RtMidi::Api getMatchedAudioMidiAPi(const RtAudio::Api rtApi)
  86. {
  87. switch (rtApi)
  88. {
  89. case RtAudio::UNSPECIFIED:
  90. return RtMidi::UNSPECIFIED;
  91. case RtAudio::LINUX_ALSA:
  92. case RtAudio::LINUX_OSS:
  93. case RtAudio::LINUX_PULSE:
  94. return RtMidi::LINUX_ALSA;
  95. case RtAudio::UNIX_JACK:
  96. #if defined(CARLA_OS_WIN)
  97. return RtMidi::WINDOWS_MM;
  98. #elif defined(CARLA_OS_MAC)
  99. return RtMidi::MACOSX_CORE;
  100. #elif defined(CARLA_OS_LINUX)
  101. return RtMidi::LINUX_ALSA;
  102. #else
  103. return RtMidi::UNIX_JACK;
  104. #endif
  105. case RtAudio::MACOSX_CORE:
  106. return RtMidi::MACOSX_CORE;
  107. case RtAudio::WINDOWS_ASIO:
  108. case RtAudio::WINDOWS_DS:
  109. return RtMidi::WINDOWS_MM;
  110. case RtAudio::RTAUDIO_DUMMY:
  111. return RtMidi::RTMIDI_DUMMY;
  112. }
  113. return RtMidi::UNSPECIFIED;
  114. }
  115. // -------------------------------------------------------------------------------------------------------------------
  116. // RtAudio Engine
  117. class CarlaEngineRtAudio : public CarlaEngine
  118. {
  119. public:
  120. CarlaEngineRtAudio(const RtAudio::Api api)
  121. : CarlaEngine(),
  122. fAudio(api),
  123. fAudioBufIn(nullptr),
  124. fAudioBufOut(nullptr),
  125. fIsAudioInterleaved(false),
  126. fLastEventTime(0),
  127. fDummyMidiIn(getMatchedAudioMidiAPi(api), "Carla"),
  128. fDummyMidiOut(getMatchedAudioMidiAPi(api), "Carla")
  129. {
  130. carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api);
  131. // just to make sure
  132. pData->options.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL;
  133. }
  134. ~CarlaEngineRtAudio() override
  135. {
  136. CARLA_ASSERT(fAudioBufIn == nullptr);
  137. CARLA_ASSERT(fAudioBufOut == nullptr);
  138. carla_debug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
  139. fUsedMidiIns.clear();
  140. fUsedMidiOuts.clear();
  141. if (gRetNames != nullptr)
  142. {
  143. delete[] gRetNames;
  144. gRetNames = nullptr;
  145. }
  146. gRtAudioApis.clear();
  147. }
  148. // -------------------------------------
  149. bool init(const char* const clientName) override
  150. {
  151. CARLA_SAFE_ASSERT_RETURN(fAudioBufIn == nullptr, false);
  152. CARLA_SAFE_ASSERT_RETURN(fAudioBufOut == nullptr, false);
  153. CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
  154. carla_debug("CarlaEngineRtAudio::init(\"%s\")", clientName);
  155. if (pData->options.processMode != ENGINE_PROCESS_MODE_CONTINUOUS_RACK && pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  156. {
  157. setLastError("Invalid process mode");
  158. return false;
  159. }
  160. pData->bufAudio.usePatchbay = (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY);
  161. RtAudio::StreamParameters iParams, oParams;
  162. bool deviceSet = false;
  163. const unsigned int devCount(fAudio.getDeviceCount());
  164. if (devCount == 0)
  165. {
  166. setLastError("No audio devices available for this driver");
  167. return false;
  168. }
  169. if (pData->options.audioDevice != nullptr && pData->options.audioDevice[0] != '\0')
  170. {
  171. for (unsigned int i=0; i < devCount; ++i)
  172. {
  173. RtAudio::DeviceInfo devInfo(fAudio.getDeviceInfo(i));
  174. if (devInfo.probed && devInfo.outputChannels > 0 && devInfo.name == pData->options.audioDevice)
  175. {
  176. deviceSet = true;
  177. fDeviceName = devInfo.name.c_str();
  178. iParams.deviceId = i;
  179. oParams.deviceId = i;
  180. iParams.nChannels = devInfo.inputChannels;
  181. oParams.nChannels = devInfo.outputChannels;
  182. break;
  183. }
  184. }
  185. }
  186. if (! deviceSet)
  187. {
  188. iParams.deviceId = fAudio.getDefaultInputDevice();
  189. oParams.deviceId = fAudio.getDefaultOutputDevice();
  190. iParams.nChannels = fAudio.getDeviceInfo(iParams.deviceId).inputChannels;
  191. oParams.nChannels = fAudio.getDeviceInfo(oParams.deviceId).outputChannels;
  192. }
  193. RtAudio::StreamOptions rtOptions;
  194. rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_HOG_DEVICE | RTAUDIO_SCHEDULE_REALTIME;
  195. rtOptions.streamName = clientName;
  196. rtOptions.priority = 85;
  197. if (fAudio.getCurrentApi() != RtAudio::LINUX_PULSE)
  198. {
  199. rtOptions.flags |= RTAUDIO_NONINTERLEAVED;
  200. fIsAudioInterleaved = false;
  201. if (fAudio.getCurrentApi() == RtAudio::LINUX_ALSA && ! deviceSet)
  202. rtOptions.flags |= RTAUDIO_ALSA_USE_DEFAULT;
  203. }
  204. else
  205. fIsAudioInterleaved = true;
  206. fLastEventTime = 0;
  207. unsigned int bufferFrames = pData->options.audioBufferSize;
  208. try {
  209. fAudio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, pData->options.audioSampleRate, &bufferFrames, carla_rtaudio_process_callback, this, &rtOptions);
  210. }
  211. catch (const RtError& e)
  212. {
  213. setLastError(e.what());
  214. return false;
  215. }
  216. pData->bufferSize = bufferFrames;
  217. pData->sampleRate = fAudio.getStreamSampleRate();
  218. pData->bufAudio.inCount = iParams.nChannels;
  219. pData->bufAudio.outCount = oParams.nChannels;
  220. CARLA_ASSERT(pData->bufAudio.outCount > 0);
  221. if (pData->bufAudio.inCount > 0)
  222. {
  223. fAudioBufIn = new float*[pData->bufAudio.inCount];
  224. for (uint i=0; i < pData->bufAudio.inCount; ++i)
  225. fAudioBufIn[i] = new float[pData->bufferSize];
  226. }
  227. if (pData->bufAudio.outCount > 0)
  228. {
  229. fAudioBufOut = new float*[pData->bufAudio.outCount];
  230. for (uint i=0; i < pData->bufAudio.outCount; ++i)
  231. fAudioBufOut[i] = new float[pData->bufferSize];
  232. }
  233. pData->bufAudio.create(pData->bufferSize);
  234. try {
  235. fAudio.startStream();
  236. }
  237. catch (const RtError& e)
  238. {
  239. setLastError(e.what());
  240. fAudio.closeStream();
  241. return false;
  242. }
  243. CarlaEngine::init(clientName);
  244. patchbayRefresh();
  245. return true;
  246. }
  247. bool close() override
  248. {
  249. CARLA_ASSERT(fAudioBufOut != nullptr);
  250. carla_debug("CarlaEngineRtAudio::close()");
  251. pData->bufAudio.isReady = false;
  252. bool hasError = !CarlaEngine::close();
  253. if (fAudio.isStreamOpen())
  254. {
  255. if (fAudio.isStreamRunning())
  256. {
  257. try {
  258. fAudio.stopStream();
  259. }
  260. catch (const RtError& e)
  261. {
  262. if (! hasError)
  263. {
  264. setLastError(e.what());
  265. hasError = true;
  266. }
  267. }
  268. }
  269. fAudio.closeStream();
  270. }
  271. if (fAudioBufIn != nullptr)
  272. {
  273. for (uint i=0; i < pData->bufAudio.inCount; ++i)
  274. delete[] fAudioBufIn[i];
  275. delete[] fAudioBufIn;
  276. fAudioBufIn = nullptr;
  277. }
  278. if (fAudioBufOut != nullptr)
  279. {
  280. for (uint i=0; i < pData->bufAudio.outCount; ++i)
  281. delete[] fAudioBufOut[i];
  282. delete[] fAudioBufOut;
  283. fAudioBufOut = nullptr;
  284. }
  285. pData->bufAudio.clear();
  286. fDeviceName.clear();
  287. for (List<MidiPort>::Itenerator it = fMidiIns.begin(); it.valid(); it.next())
  288. {
  289. MidiPort& port(it.getValue());
  290. RtMidiIn* const midiInPort((RtMidiIn*)port.rtmidi);
  291. midiInPort->cancelCallback();
  292. delete midiInPort;
  293. }
  294. for (List<MidiPort>::Itenerator it = fMidiOuts.begin(); it.valid(); it.next())
  295. {
  296. MidiPort& port(it.getValue());
  297. RtMidiOut* const midiOutPort((RtMidiOut*)port.rtmidi);
  298. delete midiOutPort;
  299. }
  300. fMidiIns.clear();
  301. fMidiOuts.clear();
  302. fMidiInEvents.clear();
  303. //fMidiOutEvents.clear();
  304. return !hasError;
  305. }
  306. bool isRunning() const noexcept override
  307. {
  308. return fAudio.isStreamRunning();
  309. }
  310. bool isOffline() const noexcept override
  311. {
  312. return false;
  313. }
  314. EngineType getType() const noexcept override
  315. {
  316. return kEngineTypeRtAudio;
  317. }
  318. const char* getCurrentDriverName() const noexcept override
  319. {
  320. return CarlaBackend::getRtAudioApiName(fAudio.getCurrentApi());
  321. }
  322. // -------------------------------------------------------------------
  323. // Patchbay
  324. bool patchbayRefresh() override
  325. {
  326. CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false);
  327. fUsedMidiIns.clear();
  328. fUsedMidiOuts.clear();
  329. pData->bufAudio.initPatchbay();
  330. if (pData->bufAudio.usePatchbay)
  331. {
  332. // not implemented yet
  333. return false;
  334. }
  335. char strBuf[STR_MAX+1];
  336. strBuf[STR_MAX] = '\0';
  337. EngineRackBuffers* const rack(pData->bufAudio.rack);
  338. // Main
  339. {
  340. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_CARLA, 0, 0, 0.0f, getName());
  341. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
  342. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
  343. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
  344. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
  345. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in");
  346. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out");
  347. }
  348. // Audio In
  349. {
  350. if (fDeviceName.isNotEmpty())
  351. std::snprintf(strBuf, STR_MAX, "Capture (%s)", (const char*)fDeviceName);
  352. else
  353. std::strncpy(strBuf, "Capture", STR_MAX);
  354. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_IN, 0, 0, 0.0f, strBuf);
  355. for (uint i=0; i < pData->bufAudio.inCount; ++i)
  356. {
  357. std::snprintf(strBuf, STR_MAX, "capture_%i", i+1);
  358. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_IN, RACK_PATCHBAY_GROUP_AUDIO_IN*1000 + i, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, strBuf);
  359. }
  360. }
  361. // Audio Out
  362. {
  363. if (fDeviceName.isNotEmpty())
  364. std::snprintf(strBuf, STR_MAX, "Playback (%s)", (const char*)fDeviceName);
  365. else
  366. std::strncpy(strBuf, "Playback", STR_MAX);
  367. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_OUT, 0, 0, 0.0f, strBuf);
  368. for (uint i=0; i < pData->bufAudio.outCount; ++i)
  369. {
  370. std::snprintf(strBuf, STR_MAX, "playback_%i", i+1);
  371. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_OUT, RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 + i, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, strBuf);
  372. }
  373. }
  374. // MIDI In
  375. {
  376. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_MIDI_IN, 0, 0, 0.0f, "Readable MIDI ports");
  377. for (unsigned int i=0, count=fDummyMidiIn.getPortCount(); i < count; ++i)
  378. {
  379. PortNameToId portNameToId;
  380. portNameToId.portId = RACK_PATCHBAY_GROUP_MIDI_IN*1000 + i;
  381. std::strncpy(portNameToId.name, fDummyMidiIn.getPortName(i).c_str(), STR_MAX);
  382. fUsedMidiIns.append(portNameToId);
  383. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_MIDI_IN, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI, 0.0f, portNameToId.name);
  384. }
  385. }
  386. #if 0 // midi-out not implemented yet
  387. // MIDI Out
  388. {
  389. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, RACK_PATCHBAY_GROUP_MIDI_OUT, 0, 0.0f, "Writable MIDI ports");
  390. for (unsigned int i=0, count=fDummyMidiOut.getPortCount(); i < count; ++i)
  391. {
  392. PortNameToId portNameToId;
  393. portNameToId.portId = RACK_PATCHBAY_GROUP_MIDI_OUT*1000 + i;
  394. std::strncpy(portNameToId.name, fDummyMidiOut.getPortName(i).c_str(), STR_MAX);
  395. fUsedMidiOuts.append(portNameToId);
  396. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, RACK_PATCHBAY_GROUP_MIDI_OUT, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, portNameToId.name);
  397. }
  398. }
  399. #endif
  400. // Connections
  401. rack->connectLock.lock();
  402. for (List<uint>::Itenerator it = rack->connectedIns[0].begin(); it.valid(); it.next())
  403. {
  404. const uint& port(it.getConstValue());
  405. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.inCount);
  406. ConnectionToId connectionToId;
  407. connectionToId.id = rack->lastConnectionId;
  408. connectionToId.portOut = RACK_PATCHBAY_GROUP_AUDIO_IN*1000 + port;
  409. connectionToId.portIn = RACK_PATCHBAY_PORT_AUDIO_IN1;
  410. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  411. rack->usedConnections.append(connectionToId);
  412. rack->lastConnectionId++;
  413. }
  414. for (List<uint>::Itenerator it = rack->connectedIns[1].begin(); it.valid(); it.next())
  415. {
  416. const uint& port(it.getConstValue());
  417. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.inCount);
  418. ConnectionToId connectionToId;
  419. connectionToId.id = rack->lastConnectionId;
  420. connectionToId.portOut = RACK_PATCHBAY_GROUP_AUDIO_IN*1000 + port;
  421. connectionToId.portIn = RACK_PATCHBAY_PORT_AUDIO_IN2;
  422. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  423. rack->usedConnections.append(connectionToId);
  424. rack->lastConnectionId++;
  425. }
  426. for (List<uint>::Itenerator it = rack->connectedOuts[0].begin(); it.valid(); it.next())
  427. {
  428. const uint& port(it.getConstValue());
  429. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.outCount);
  430. ConnectionToId connectionToId;
  431. connectionToId.id = rack->lastConnectionId;
  432. connectionToId.portOut = RACK_PATCHBAY_PORT_AUDIO_OUT1;
  433. connectionToId.portIn = RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 + port;
  434. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  435. rack->usedConnections.append(connectionToId);
  436. rack->lastConnectionId++;
  437. }
  438. for (List<uint>::Itenerator it = rack->connectedOuts[1].begin(); it.valid(); it.next())
  439. {
  440. const uint& port(it.getConstValue());
  441. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.outCount);
  442. ConnectionToId connectionToId;
  443. connectionToId.id = rack->lastConnectionId;
  444. connectionToId.portOut = RACK_PATCHBAY_PORT_AUDIO_OUT2;
  445. connectionToId.portIn = RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 + port;
  446. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  447. rack->usedConnections.append(connectionToId);
  448. rack->lastConnectionId++;
  449. }
  450. pData->bufAudio.rack->connectLock.unlock();
  451. for (List<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
  452. {
  453. const MidiPort& midiPort(it.getConstValue());
  454. ConnectionToId connectionToId;
  455. connectionToId.id = rack->lastConnectionId;
  456. connectionToId.portOut = RACK_PATCHBAY_GROUP_MIDI_IN*1000 + midiPort.portId;
  457. connectionToId.portIn = RACK_PATCHBAY_PORT_MIDI_IN;
  458. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  459. rack->usedConnections.append(connectionToId);
  460. rack->lastConnectionId++;
  461. }
  462. for (List<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
  463. {
  464. const MidiPort& midiPort(it.getConstValue());
  465. ConnectionToId connectionToId;
  466. connectionToId.id = rack->lastConnectionId;
  467. connectionToId.portOut = RACK_PATCHBAY_PORT_MIDI_OUT;
  468. connectionToId.portIn = RACK_PATCHBAY_GROUP_MIDI_OUT*1000 + midiPort.portId;
  469. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  470. rack->usedConnections.append(connectionToId);
  471. rack->lastConnectionId++;
  472. }
  473. return true;
  474. }
  475. // -------------------------------------------------------------------
  476. protected:
  477. void handleAudioProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
  478. {
  479. // get buffers from RtAudio
  480. float* const insPtr = (float*)inputBuffer;
  481. float* const outsPtr = (float*)outputBuffer;
  482. // assert rtaudio buffers
  483. CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,);
  484. CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,);
  485. if (pData->bufAudio.outCount == 0 || ! pData->bufAudio.isReady)
  486. return runPendingRtEvents();
  487. // initialize rtaudio input
  488. if (fIsAudioInterleaved)
  489. {
  490. for (unsigned int i=0, j=0, count=nframes*pData->bufAudio.inCount; i < count; ++i)
  491. {
  492. fAudioBufIn[i/pData->bufAudio.inCount][j] = insPtr[i];
  493. if ((i+1) % pData->bufAudio.inCount == 0)
  494. j += 1;
  495. }
  496. }
  497. else
  498. {
  499. for (unsigned int i=0; i < pData->bufAudio.inCount; ++i)
  500. FLOAT_COPY(fAudioBufIn[i], insPtr+(nframes*i), nframes);
  501. }
  502. // initialize rtaudio output
  503. for (unsigned int i=0; i < pData->bufAudio.outCount; ++i)
  504. FLOAT_CLEAR(fAudioBufOut[i], nframes);
  505. // initialize input events
  506. carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kEngineMaxInternalEventCount);
  507. if (fMidiInEvents.mutex.tryLock())
  508. {
  509. uint32_t engineEventIndex = 0;
  510. fMidiInEvents.splice();
  511. while (! fMidiInEvents.data.isEmpty())
  512. {
  513. const RtMidiEvent& midiEvent(fMidiInEvents.data.getFirst(true));
  514. EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
  515. if (midiEvent.time < pData->timeInfo.frame)
  516. {
  517. engineEvent.time = 0;
  518. }
  519. else if (midiEvent.time >= pData->timeInfo.frame + nframes)
  520. {
  521. carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent.time, pData->timeInfo.frame);
  522. engineEvent.time = static_cast<uint32_t>(pData->timeInfo.frame) + nframes - 1;
  523. }
  524. else
  525. engineEvent.time = static_cast<uint32_t>(midiEvent.time - pData->timeInfo.frame);
  526. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data);
  527. if (engineEventIndex >= kEngineMaxInternalEventCount)
  528. break;
  529. }
  530. fMidiInEvents.mutex.unlock();
  531. }
  532. if (pData->bufAudio.usePatchbay)
  533. {
  534. }
  535. else
  536. {
  537. pData->processRackFull(fAudioBufIn, pData->bufAudio.inCount, fAudioBufOut, pData->bufAudio.outCount, nframes, false);
  538. }
  539. // output audio
  540. if (fIsAudioInterleaved)
  541. {
  542. for (unsigned int i=0, j=0; i < nframes*pData->bufAudio.outCount; ++i)
  543. {
  544. outsPtr[i] = fAudioBufOut[i/pData->bufAudio.outCount][j];
  545. if ((i+1) % pData->bufAudio.outCount == 0)
  546. j += 1;
  547. }
  548. }
  549. else
  550. {
  551. for (unsigned int i=0; i < pData->bufAudio.outCount; ++i)
  552. FLOAT_COPY(outsPtr+(nframes*i), fAudioBufOut[i], nframes);
  553. }
  554. // output events
  555. {
  556. // TODO
  557. //fMidiOutEvents...
  558. }
  559. runPendingRtEvents();
  560. return;
  561. // unused
  562. (void)streamTime;
  563. (void)status;
  564. }
  565. void handleMidiCallback(double timeStamp, std::vector<unsigned char>* const message)
  566. {
  567. if (! pData->bufAudio.isReady)
  568. return;
  569. const size_t messageSize(message->size());
  570. if (messageSize == 0 || messageSize > EngineMidiEvent::kDataSize)
  571. return;
  572. timeStamp /= 2;
  573. if (timeStamp > 0.95)
  574. timeStamp = 0.95;
  575. else if (timeStamp < 0.0)
  576. timeStamp = 0.0;
  577. RtMidiEvent midiEvent;
  578. midiEvent.time = pData->timeInfo.frame + uint64_t(timeStamp * (double)pData->bufferSize);
  579. if (midiEvent.time < fLastEventTime)
  580. midiEvent.time = fLastEventTime;
  581. else
  582. fLastEventTime = midiEvent.time;
  583. midiEvent.size = static_cast<uint8_t>(messageSize);
  584. size_t i=0;
  585. for (; i < messageSize; ++i)
  586. midiEvent.data[i] = message->at(i);
  587. for (; i < EngineMidiEvent::kDataSize; ++i)
  588. midiEvent.data[i] = 0;
  589. fMidiInEvents.append(midiEvent);
  590. }
  591. // -------------------------------------------------------------------
  592. bool connectRackMidiInPort(const int portId) override
  593. {
  594. CARLA_SAFE_ASSERT_RETURN(fUsedMidiIns.count() > 0, false);
  595. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  596. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiIns.count(), false);
  597. carla_debug("CarlaEngineRtAudio::connectRackMidiInPort(%i)", portId);
  598. const char* const portName(fUsedMidiIns.getAt(portId).name);
  599. char newPortName[STR_MAX+1];
  600. std::snprintf(newPortName, STR_MAX, "%s:in-%i", (const char*)getName(), portId+1);
  601. int rtMidiPortIndex = -1;
  602. RtMidiIn* const rtMidiIn(new RtMidiIn(getMatchedAudioMidiAPi(fAudio.getCurrentApi()), newPortName, 512));
  603. rtMidiIn->ignoreTypes();
  604. rtMidiIn->setCallback(carla_rtmidi_callback, this);
  605. for (unsigned int i=0, count=rtMidiIn->getPortCount(); i < count; ++i)
  606. {
  607. if (rtMidiIn->getPortName(i) == portName)
  608. {
  609. rtMidiPortIndex = i;
  610. break;
  611. }
  612. }
  613. if (rtMidiPortIndex == -1)
  614. {
  615. delete rtMidiIn;
  616. return false;
  617. }
  618. rtMidiIn->openPort(rtMidiPortIndex, newPortName+(std::strlen(getName())+1));
  619. MidiPort midiPort;
  620. midiPort.portId = portId;
  621. midiPort.rtmidi = rtMidiIn;
  622. fMidiIns.append(midiPort);
  623. return true;
  624. }
  625. bool connectRackMidiOutPort(const int portId) override
  626. {
  627. CARLA_SAFE_ASSERT_RETURN(fUsedMidiOuts.count() > 0, false);
  628. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  629. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiOuts.count(), false);
  630. carla_debug("CarlaEngineRtAudio::connectRackMidiOutPort(%i)", portId);
  631. const char* const portName(fUsedMidiOuts.getAt(portId).name);
  632. char newPortName[STR_MAX+1];
  633. std::snprintf(newPortName, STR_MAX, "%s:out-%i", (const char*)getName(), portId+1);
  634. int rtMidiPortIndex = -1;
  635. RtMidiOut* const rtMidiOut(new RtMidiOut(getMatchedAudioMidiAPi(fAudio.getCurrentApi()), newPortName));
  636. for (unsigned int i=0, count=rtMidiOut->getPortCount(); i < count; ++i)
  637. {
  638. if (rtMidiOut->getPortName(i) == portName)
  639. {
  640. rtMidiPortIndex = i;
  641. break;
  642. }
  643. }
  644. if (rtMidiPortIndex == -1)
  645. {
  646. delete rtMidiOut;
  647. return false;
  648. }
  649. rtMidiOut->openPort(rtMidiPortIndex, newPortName+(std::strlen(getName())+1));
  650. MidiPort midiPort;
  651. midiPort.portId = portId;
  652. midiPort.rtmidi = rtMidiOut;
  653. fMidiOuts.append(midiPort);
  654. return true;
  655. }
  656. bool disconnectRackMidiInPort(const int portId) override
  657. {
  658. CARLA_SAFE_ASSERT_RETURN(fUsedMidiIns.count() > 0, false);
  659. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  660. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiIns.count(), false);
  661. carla_debug("CarlaEngineRtAudio::connectRackMidiInPort(%i)", portId);
  662. for (List<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
  663. {
  664. MidiPort& midiPort(it.getValue());
  665. if (midiPort.portId == portId)
  666. {
  667. RtMidiOut* const midiOutPort((RtMidiOut*)midiPort.rtmidi);
  668. delete midiOutPort;
  669. fMidiOuts.remove(it);
  670. return true;
  671. }
  672. }
  673. return false;
  674. }
  675. bool disconnectRackMidiOutPort(const int portId) override
  676. {
  677. CARLA_SAFE_ASSERT_RETURN(fUsedMidiOuts.count() > 0, false);
  678. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  679. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiOuts.count(), false);
  680. carla_debug("CarlaEngineRtAudio::disconnectRackMidiOutPort(%i)", portId);
  681. for (List<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
  682. {
  683. MidiPort& midiPort(it.getValue());
  684. if (midiPort.portId == portId)
  685. {
  686. RtMidiIn* const midiInPort((RtMidiIn*)midiPort.rtmidi);
  687. midiInPort->cancelCallback();
  688. delete midiInPort;
  689. fMidiIns.remove(it);
  690. return true;
  691. }
  692. }
  693. return false;
  694. }
  695. // -------------------------------------
  696. private:
  697. RtAudio fAudio;
  698. // audio copy to split and de-interleave rtaudio buffers
  699. float** fAudioBufIn;
  700. float** fAudioBufOut;
  701. // useful info
  702. bool fIsAudioInterleaved;
  703. uint64_t fLastEventTime;
  704. // current device name
  705. CarlaString fDeviceName;
  706. // dummy rtmidi to scan available ports
  707. RtMidiIn fDummyMidiIn;
  708. RtMidiOut fDummyMidiOut;
  709. List<PortNameToId> fUsedMidiIns;
  710. List<PortNameToId> fUsedMidiOuts;
  711. struct MidiPort {
  712. RtMidi* rtmidi;
  713. int portId;
  714. };
  715. List<MidiPort> fMidiIns;
  716. List<MidiPort> fMidiOuts;
  717. struct RtMidiEvent {
  718. uint64_t time; // needs to compare to internal time
  719. uint8_t size;
  720. uint8_t data[EngineMidiEvent::kDataSize];
  721. };
  722. struct RtMidiEvents {
  723. CarlaMutex mutex;
  724. RtList<RtMidiEvent>::Pool dataPool;
  725. RtList<RtMidiEvent> data;
  726. RtList<RtMidiEvent> dataPending;
  727. RtMidiEvents()
  728. : dataPool(512, 512),
  729. data(dataPool),
  730. dataPending(dataPool) {}
  731. ~RtMidiEvents()
  732. {
  733. clear();
  734. }
  735. void append(const RtMidiEvent& event)
  736. {
  737. mutex.lock();
  738. dataPending.append(event);
  739. mutex.unlock();
  740. }
  741. void clear()
  742. {
  743. mutex.lock();
  744. data.clear();
  745. dataPending.clear();
  746. mutex.unlock();
  747. }
  748. void splice()
  749. {
  750. dataPending.spliceAppend(data);
  751. }
  752. };
  753. RtMidiEvents fMidiInEvents;
  754. //RtMidiEvents fMidiOutEvents;
  755. #define handlePtr ((CarlaEngineRtAudio*)userData)
  756. static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
  757. {
  758. handlePtr->handleAudioProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
  759. return 0;
  760. }
  761. static void carla_rtmidi_callback(double timeStamp, std::vector<unsigned char>* message, void* userData)
  762. {
  763. handlePtr->handleMidiCallback(timeStamp, message);
  764. }
  765. #undef handlePtr
  766. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudio)
  767. };
  768. // -----------------------------------------
  769. CarlaEngine* CarlaEngine::newRtAudio(AudioApi api)
  770. {
  771. initRtApis();
  772. RtAudio::Api rtApi(RtAudio::UNSPECIFIED);
  773. switch (api)
  774. {
  775. case AUDIO_API_NULL:
  776. rtApi = RtAudio::RTAUDIO_DUMMY;
  777. break;
  778. case AUDIO_API_JACK:
  779. rtApi = RtAudio::UNIX_JACK;
  780. break;
  781. case AUDIO_API_ALSA:
  782. rtApi = RtAudio::LINUX_ALSA;
  783. break;
  784. case AUDIO_API_OSS:
  785. rtApi = RtAudio::LINUX_OSS;
  786. break;
  787. case AUDIO_API_PULSE:
  788. rtApi = RtAudio::LINUX_PULSE;
  789. break;
  790. case AUDIO_API_CORE:
  791. rtApi = RtAudio::MACOSX_CORE;
  792. break;
  793. case AUDIO_API_ASIO:
  794. rtApi = RtAudio::WINDOWS_ASIO;
  795. break;
  796. case AUDIO_API_DS:
  797. rtApi = RtAudio::WINDOWS_DS;
  798. break;
  799. }
  800. return new CarlaEngineRtAudio(rtApi);
  801. }
  802. unsigned int CarlaEngine::getRtAudioApiCount()
  803. {
  804. initRtApis();
  805. return static_cast<unsigned int>(gRtAudioApis.size());
  806. }
  807. const char* CarlaEngine::getRtAudioApiName(const unsigned int index)
  808. {
  809. initRtApis();
  810. if (index >= gRtAudioApis.size())
  811. return nullptr;
  812. return CarlaBackend::getRtAudioApiName(gRtAudioApis[index]);
  813. }
  814. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const unsigned int index)
  815. {
  816. initRtApis();
  817. if (index >= gRtAudioApis.size())
  818. return nullptr;
  819. const RtAudio::Api& api(gRtAudioApis[index]);
  820. RtAudio rtAudio(api);
  821. const unsigned int devCount(rtAudio.getDeviceCount());
  822. if (devCount == 0)
  823. return nullptr;
  824. List<const char*> devNames;
  825. for (unsigned int i=0; i < devCount; ++i)
  826. {
  827. RtAudio::DeviceInfo devInfo(rtAudio.getDeviceInfo(i));
  828. if (devInfo.probed && devInfo.outputChannels > 0 /*&& (devInfo.nativeFormats & RTAUDIO_FLOAT32) != 0*/)
  829. devNames.append(carla_strdup(devInfo.name.c_str()));
  830. }
  831. const size_t realDevCount(devNames.count());
  832. if (gRetNames != nullptr)
  833. {
  834. for (int i=0; gRetNames[i] != nullptr; ++i)
  835. delete[] gRetNames[i];
  836. delete[] gRetNames;
  837. }
  838. gRetNames = new const char*[realDevCount+1];
  839. for (size_t i=0; i < realDevCount; ++i)
  840. gRetNames[i] = devNames.getAt(i);
  841. gRetNames[realDevCount] = nullptr;
  842. devNames.clear();
  843. return gRetNames;
  844. }
  845. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const unsigned int index, const char* const deviceName)
  846. {
  847. initRtApis();
  848. carla_stderr("here 000");
  849. if (index >= gRtAudioApis.size())
  850. {
  851. carla_stderr("here 001");
  852. return nullptr;
  853. }
  854. const RtAudio::Api& api(gRtAudioApis[index]);
  855. RtAudio rtAudio(api);
  856. const unsigned int devCount(rtAudio.getDeviceCount());
  857. if (devCount == 0)
  858. {
  859. carla_stderr("here 002");
  860. return nullptr;
  861. }
  862. unsigned int i;
  863. RtAudio::DeviceInfo rtAudioDevInfo;
  864. for (i=0; i < devCount; ++i)
  865. {
  866. rtAudioDevInfo = rtAudio.getDeviceInfo(i);
  867. if (rtAudioDevInfo.name == deviceName)
  868. break;
  869. }
  870. if (i == devCount)
  871. {
  872. carla_stderr("here 003");
  873. return nullptr;
  874. }
  875. static EngineDriverDeviceInfo devInfo = { 0x0, nullptr, nullptr };
  876. static uint32_t dummyBufferSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 };
  877. static double dummySampleRates[14] = { 22050.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 0.0 };
  878. // reset
  879. devInfo.hints = 0x0;
  880. devInfo.bufferSizes = dummyBufferSizes;
  881. // cleanup
  882. if (devInfo.sampleRates != nullptr && devInfo.sampleRates != dummySampleRates)
  883. {
  884. delete[] devInfo.sampleRates;
  885. devInfo.sampleRates = nullptr;
  886. }
  887. if (size_t sampleRatesCount = rtAudioDevInfo.sampleRates.size())
  888. {
  889. double* const sampleRates(new double[sampleRatesCount+1]);
  890. for (size_t i=0; i < sampleRatesCount; ++i)
  891. sampleRates[i] = rtAudioDevInfo.sampleRates[i];
  892. sampleRates[sampleRatesCount] = 0.0;
  893. devInfo.sampleRates = sampleRates;
  894. }
  895. else
  896. {
  897. devInfo.sampleRates = dummySampleRates;
  898. }
  899. carla_stderr("here 004");
  900. return &devInfo;
  901. }
  902. // -----------------------------------------
  903. CARLA_BACKEND_END_NAMESPACE