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.

CarlaEngineBridge.cpp 68KB

10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2023 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. #ifndef BUILD_BRIDGE
  18. # error This file should not be compiled if not building bridge
  19. #endif
  20. // must be first so we can undef CARLA_SAFE_*_RETURN_ERR* macros
  21. #include "CarlaPluginInternal.hpp"
  22. #undef CARLA_SAFE_ASSERT_RETURN_ERR
  23. #undef CARLA_SAFE_ASSERT_RETURN_ERRN
  24. #undef CARLA_SAFE_EXCEPTION_RETURN_ERR
  25. #undef CARLA_SAFE_EXCEPTION_RETURN_ERRN
  26. #include "CarlaEngineClient.hpp"
  27. #include "CarlaEngineInit.hpp"
  28. #include "CarlaBackendUtils.hpp"
  29. #include "CarlaBase64Utils.hpp"
  30. #include "CarlaBridgeUtils.hpp"
  31. #include "CarlaTimeUtils.hpp"
  32. #include "CarlaMIDI.h"
  33. #ifdef __SSE2_MATH__
  34. # include <xmmintrin.h>
  35. #endif
  36. #include "water/files/File.h"
  37. #include "water/misc/Time.h"
  38. // must be last
  39. #include "jackbridge/JackBridge.hpp"
  40. using water::File;
  41. using water::MemoryBlock;
  42. using water::String;
  43. CARLA_BACKEND_START_NAMESPACE
  44. // -----------------------------------------------------------------------
  45. // Bridge Engine client
  46. struct LatencyChangedCallback {
  47. virtual ~LatencyChangedCallback() noexcept {}
  48. virtual void latencyChanged(const uint32_t samples) noexcept = 0;
  49. };
  50. class CarlaEngineBridgeClient : public CarlaEngineClientForSubclassing
  51. {
  52. public:
  53. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  54. CarlaEngineBridgeClient(const CarlaEngine& engine,
  55. EngineInternalGraph& egraph,
  56. const CarlaPluginPtr plugin,
  57. LatencyChangedCallback* const cb)
  58. : CarlaEngineClientForSubclassing(engine, egraph, plugin),
  59. fLatencyCallback(cb) {}
  60. #else
  61. CarlaEngineBridgeClient(const CarlaEngine& engine, LatencyChangedCallback* const cb)
  62. : CarlaEngineClientForSubclassing(engine),
  63. fLatencyCallback(cb) {}
  64. #endif
  65. protected:
  66. void setLatency(const uint32_t samples) noexcept override
  67. {
  68. if (getLatency() == samples)
  69. return;
  70. fLatencyCallback->latencyChanged(samples);
  71. CarlaEngineClient::setLatency(samples);
  72. }
  73. private:
  74. LatencyChangedCallback* const fLatencyCallback;
  75. CARLA_DECLARE_NON_COPYABLE(CarlaEngineBridgeClient)
  76. };
  77. // -------------------------------------------------------------------
  78. struct BridgeTextReader {
  79. char* text;
  80. BridgeTextReader(BridgeNonRtClientControl& nonRtClientCtrl)
  81. : text(nullptr)
  82. {
  83. const uint32_t size = nonRtClientCtrl.readUInt();
  84. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  85. text = new char[size + 1];
  86. nonRtClientCtrl.readCustomData(text, size);
  87. text[size] = '\0';
  88. }
  89. BridgeTextReader(BridgeNonRtClientControl& nonRtClientCtrl, const uint32_t size)
  90. : text(nullptr)
  91. {
  92. text = new char[size + 1];
  93. if (size != 0)
  94. nonRtClientCtrl.readCustomData(text, size);
  95. text[size] = '\0';
  96. }
  97. ~BridgeTextReader() noexcept
  98. {
  99. delete[] text;
  100. }
  101. CARLA_DECLARE_NON_COPYABLE(BridgeTextReader)
  102. };
  103. // -------------------------------------------------------------------
  104. class CarlaEngineBridge : public CarlaEngine,
  105. private CarlaThread,
  106. private LatencyChangedCallback
  107. {
  108. public:
  109. CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
  110. : CarlaEngine(),
  111. CarlaThread("CarlaEngineBridge"),
  112. fShmAudioPool(),
  113. fShmRtClientControl(),
  114. fShmNonRtClientControl(),
  115. fShmNonRtServerControl(),
  116. fBaseNameAudioPool(audioPoolBaseName),
  117. fBaseNameRtClientControl(rtClientBaseName),
  118. fBaseNameNonRtClientControl(nonRtClientBaseName),
  119. fBaseNameNonRtServerControl(nonRtServerBaseName),
  120. fClosingDown(false),
  121. fIsOffline(false),
  122. fFirstIdle(true),
  123. fBridgeVersion(0),
  124. fLastPingTime(UINT32_MAX)
  125. {
  126. carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
  127. }
  128. ~CarlaEngineBridge() noexcept override
  129. {
  130. carla_debug("CarlaEngineBridge::~CarlaEngineBridge()");
  131. clear();
  132. }
  133. // -------------------------------------
  134. // CarlaEngine virtual calls
  135. bool init(const char* const clientName) override
  136. {
  137. carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);
  138. if (! pData->init(clientName))
  139. {
  140. setLastError("Failed to init internal data");
  141. return false;
  142. }
  143. if (! fShmAudioPool.attachClient(fBaseNameAudioPool))
  144. {
  145. pData->close();
  146. setLastError("Failed to attach to audio pool shared memory");
  147. return false;
  148. }
  149. if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl))
  150. {
  151. pData->close();
  152. clear();
  153. setLastError("Failed to attach to rt client control shared memory");
  154. return false;
  155. }
  156. if (! fShmRtClientControl.mapData())
  157. {
  158. pData->close();
  159. clear();
  160. setLastError("Failed to map rt client control shared memory");
  161. return false;
  162. }
  163. if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl))
  164. {
  165. pData->close();
  166. clear();
  167. setLastError("Failed to attach to non-rt client control shared memory");
  168. return false;
  169. }
  170. if (! fShmNonRtClientControl.mapData())
  171. {
  172. pData->close();
  173. clear();
  174. setLastError("Failed to map non-rt control client shared memory");
  175. return false;
  176. }
  177. if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl))
  178. {
  179. pData->close();
  180. clear();
  181. setLastError("Failed to attach to non-rt server control shared memory");
  182. return false;
  183. }
  184. if (! fShmNonRtServerControl.mapData())
  185. {
  186. pData->close();
  187. clear();
  188. setLastError("Failed to map non-rt control server shared memory");
  189. return false;
  190. }
  191. PluginBridgeNonRtClientOpcode opcode;
  192. opcode = fShmNonRtClientControl.readOpcode();
  193. CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientVersion, false);
  194. const uint32_t apiVersion = fShmNonRtClientControl.readUInt();
  195. CARLA_SAFE_ASSERT_RETURN(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM, false);
  196. const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt();
  197. CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData));
  198. const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt();
  199. CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData));
  200. const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt();
  201. CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData));
  202. if (shmRtClientDataSize != sizeof(BridgeRtClientData) ||
  203. shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) ||
  204. shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
  205. {
  206. pData->close();
  207. clear();
  208. setLastError("Shared memory data size mismatch");
  209. return false;
  210. }
  211. opcode = fShmNonRtClientControl.readOpcode();
  212. CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientInitialSetup, false);
  213. pData->bufferSize = fShmNonRtClientControl.readUInt();
  214. pData->sampleRate = fShmNonRtClientControl.readDouble();
  215. if (pData->bufferSize == 0 || carla_isZero(pData->sampleRate))
  216. {
  217. pData->close();
  218. clear();
  219. setLastError("Shared memory has invalid data");
  220. return false;
  221. }
  222. pData->initTime(nullptr);
  223. // tell backend we're live
  224. {
  225. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  226. // kPluginBridgeNonRtServerVersion was added in API 7
  227. if (apiVersion >= 7)
  228. {
  229. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerVersion);
  230. fShmNonRtServerControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT);
  231. }
  232. else
  233. {
  234. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  235. }
  236. fShmNonRtServerControl.commitWrite();
  237. }
  238. startThread(true);
  239. return true;
  240. }
  241. bool close() override
  242. {
  243. carla_debug("CarlaEngineBridge::close()");
  244. fLastPingTime = UINT32_MAX;
  245. CarlaEngine::close();
  246. stopThread(5000);
  247. clear();
  248. return true;
  249. }
  250. bool hasIdleOnMainThread() const noexcept override
  251. {
  252. return true;
  253. }
  254. bool isRunning() const noexcept override
  255. {
  256. if (fClosingDown)
  257. return false;
  258. return isThreadRunning() || ! fFirstIdle;
  259. }
  260. bool isOffline() const noexcept override
  261. {
  262. return fIsOffline;
  263. }
  264. EngineType getType() const noexcept override
  265. {
  266. return kEngineTypeBridge;
  267. }
  268. const char* getCurrentDriverName() const noexcept override
  269. {
  270. return "Bridge";
  271. }
  272. void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept override
  273. {
  274. CARLA_SAFE_ASSERT_RETURN(id == 0,);
  275. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  276. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterTouch);
  277. fShmNonRtServerControl.writeUInt(parameterId);
  278. fShmNonRtServerControl.writeBool(touch);
  279. fShmNonRtServerControl.commitWrite();
  280. }
  281. CarlaEngineClient* addClient(const CarlaPluginPtr plugin) override
  282. {
  283. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  284. return new CarlaEngineBridgeClient(*this, pData->graph, plugin, this);
  285. #else
  286. return new CarlaEngineBridgeClient(*this, this);
  287. // unused
  288. (void)plugin;
  289. #endif
  290. }
  291. void idle() noexcept override
  292. {
  293. const CarlaPluginPtr plugin = pData->plugins[0].plugin;
  294. if (plugin.get() == nullptr)
  295. {
  296. if (const uint32_t length = static_cast<uint32_t>(pData->lastError.length()))
  297. {
  298. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  299. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  300. fShmNonRtServerControl.writeUInt(length);
  301. fShmNonRtServerControl.writeCustomData(pData->lastError.buffer(), length);
  302. fShmNonRtServerControl.commitWrite();
  303. }
  304. signalThreadShouldExit();
  305. callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr);
  306. return;
  307. }
  308. const bool wasFirstIdle = fFirstIdle;
  309. if (wasFirstIdle)
  310. {
  311. fFirstIdle = false;
  312. fLastPingTime = carla_gettime_ms();
  313. char bufStr[STR_MAX+1];
  314. carla_zeroChars(bufStr, STR_MAX+1);
  315. uint32_t bufStrSize;
  316. const CarlaEngineClient* const client(plugin->getEngineClient());
  317. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  318. // kPluginBridgeNonRtServerPluginInfo1
  319. {
  320. // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  321. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo1);
  322. fShmNonRtServerControl.writeUInt(plugin->getCategory());
  323. fShmNonRtServerControl.writeUInt(plugin->getHints());
  324. fShmNonRtServerControl.writeUInt(plugin->getOptionsAvailable());
  325. fShmNonRtServerControl.writeUInt(plugin->getOptionsEnabled());
  326. fShmNonRtServerControl.writeLong(plugin->getUniqueId());
  327. fShmNonRtServerControl.commitWrite();
  328. }
  329. // kPluginBridgeNonRtServerPluginInfo2
  330. {
  331. // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  332. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo2);
  333. if (! plugin->getRealName(bufStr))
  334. bufStr[0] = '\0';
  335. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  336. fShmNonRtServerControl.writeUInt(bufStrSize);
  337. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  338. if (! plugin->getLabel(bufStr))
  339. bufStr[0] = '\0';
  340. bufStrSize = carla_fixedValue(1U, 256U, static_cast<uint32_t>(std::strlen(bufStr)));
  341. fShmNonRtServerControl.writeUInt(bufStrSize);
  342. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  343. if (! plugin->getMaker(bufStr))
  344. bufStr[0] = '\0';
  345. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  346. fShmNonRtServerControl.writeUInt(bufStrSize);
  347. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  348. if (! plugin->getCopyright(bufStr))
  349. bufStr[0] = '\0';
  350. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  351. fShmNonRtServerControl.writeUInt(bufStrSize);
  352. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  353. fShmNonRtServerControl.commitWrite();
  354. }
  355. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  356. // kPluginBridgeNonRtServerAudioCount
  357. {
  358. const uint32_t aIns = plugin->getAudioInCount();
  359. const uint32_t aOuts = plugin->getAudioOutCount();
  360. // uint/ins, uint/outs
  361. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerAudioCount);
  362. fShmNonRtServerControl.writeUInt(aIns);
  363. fShmNonRtServerControl.writeUInt(aOuts);
  364. fShmNonRtServerControl.commitWrite();
  365. // kPluginBridgeNonRtServerPortName
  366. for (uint32_t i=0; i<aIns; ++i)
  367. {
  368. const char* const portName(client->getAudioPortName(true, i));
  369. CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
  370. // byte/type, uint/index, uint/size, str[] (name)
  371. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
  372. fShmNonRtServerControl.writeByte(kPluginBridgePortAudioInput);
  373. fShmNonRtServerControl.writeUInt(i);
  374. bufStrSize = static_cast<uint32_t>(std::strlen(portName));
  375. fShmNonRtServerControl.writeUInt(bufStrSize);
  376. fShmNonRtServerControl.writeCustomData(portName, bufStrSize);
  377. }
  378. // kPluginBridgeNonRtServerPortName
  379. for (uint32_t i=0; i<aOuts; ++i)
  380. {
  381. const char* const portName(client->getAudioPortName(false, i));
  382. CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
  383. // byte/type, uint/index, uint/size, str[] (name)
  384. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
  385. fShmNonRtServerControl.writeByte(kPluginBridgePortAudioOutput);
  386. fShmNonRtServerControl.writeUInt(i);
  387. bufStrSize = static_cast<uint32_t>(std::strlen(portName));
  388. fShmNonRtServerControl.writeUInt(bufStrSize);
  389. fShmNonRtServerControl.writeCustomData(portName, bufStrSize);
  390. }
  391. }
  392. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  393. // kPluginBridgeNonRtServerMidiCount
  394. {
  395. // uint/ins, uint/outs
  396. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiCount);
  397. fShmNonRtServerControl.writeUInt(plugin->getMidiInCount());
  398. fShmNonRtServerControl.writeUInt(plugin->getMidiOutCount());
  399. fShmNonRtServerControl.commitWrite();
  400. }
  401. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  402. // kPluginBridgeNonRtServerCvCount
  403. {
  404. // uint/ins, uint/outs
  405. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCvCount);
  406. fShmNonRtServerControl.writeUInt(plugin->getCVInCount());
  407. fShmNonRtServerControl.writeUInt(plugin->getCVOutCount());
  408. fShmNonRtServerControl.commitWrite();
  409. }
  410. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  411. // kPluginBridgeNonRtServerParameter*
  412. if (const uint32_t count = plugin->getParameterCount())
  413. {
  414. // uint/count
  415. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterCount);
  416. fShmNonRtServerControl.writeUInt(count);
  417. fShmNonRtServerControl.commitWrite();
  418. for (uint32_t i=0; i<count; ++i)
  419. {
  420. const ParameterData& paramData(plugin->getParameterData(i));
  421. if (paramData.type != PARAMETER_INPUT && paramData.type != PARAMETER_OUTPUT)
  422. continue;
  423. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  424. continue;
  425. // kPluginBridgeNonRtServerParameterData1
  426. {
  427. // uint/index, int/rindex, uint/type, uint/hints, short/cc
  428. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterData1);
  429. fShmNonRtServerControl.writeUInt(i);
  430. fShmNonRtServerControl.writeInt(paramData.rindex);
  431. fShmNonRtServerControl.writeUInt(paramData.type);
  432. fShmNonRtServerControl.writeUInt(paramData.hints);
  433. fShmNonRtServerControl.writeShort(paramData.mappedControlIndex);
  434. fShmNonRtServerControl.commitWrite();
  435. }
  436. // kPluginBridgeNonRtServerParameterData2
  437. {
  438. // uint/index, uint/size, str[] (name), uint/size, str[] (symbol), uint/size, str[] (unit)
  439. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterData2);
  440. fShmNonRtServerControl.writeUInt(i);
  441. if (! plugin->getParameterName(i, bufStr))
  442. std::snprintf(bufStr, STR_MAX, "Param %u", i+1);
  443. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(bufStr)));
  444. fShmNonRtServerControl.writeUInt(bufStrSize);
  445. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  446. if (! plugin->getParameterSymbol(i, bufStr))
  447. bufStr[0] = '\0';
  448. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  449. fShmNonRtServerControl.writeUInt(bufStrSize);
  450. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  451. if (! plugin->getParameterUnit(i, bufStr))
  452. bufStr[0] = '\0';
  453. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(bufStr)));
  454. fShmNonRtServerControl.writeUInt(bufStrSize);
  455. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  456. fShmNonRtServerControl.commitWrite();
  457. }
  458. // kPluginBridgeNonRtServerParameterRanges
  459. {
  460. const ParameterRanges& paramRanges(plugin->getParameterRanges(i));
  461. // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
  462. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterRanges);
  463. fShmNonRtServerControl.writeUInt(i);
  464. fShmNonRtServerControl.writeFloat(paramRanges.def);
  465. fShmNonRtServerControl.writeFloat(paramRanges.min);
  466. fShmNonRtServerControl.writeFloat(paramRanges.max);
  467. fShmNonRtServerControl.writeFloat(paramRanges.step);
  468. fShmNonRtServerControl.writeFloat(paramRanges.stepSmall);
  469. fShmNonRtServerControl.writeFloat(paramRanges.stepLarge);
  470. fShmNonRtServerControl.commitWrite();
  471. }
  472. // kPluginBridgeNonRtServerParameterValue2
  473. {
  474. // uint/index float/value (used for init/output parameters only, don't resend values)
  475. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue2);
  476. fShmNonRtServerControl.writeUInt(i);
  477. fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i));
  478. fShmNonRtServerControl.commitWrite();
  479. }
  480. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  481. }
  482. }
  483. // kPluginBridgeNonRtServerProgram*
  484. if (const uint32_t count = plugin->getProgramCount())
  485. {
  486. // uint/count
  487. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerProgramCount);
  488. fShmNonRtServerControl.writeUInt(count);
  489. fShmNonRtServerControl.commitWrite();
  490. for (uint32_t i=0; i < count; ++i)
  491. {
  492. // uint/index, uint/size, str[] (name)
  493. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerProgramName);
  494. fShmNonRtServerControl.writeUInt(i);
  495. if (! plugin->getProgramName(i, bufStr))
  496. bufStr[0] = '\0';
  497. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(bufStr)));
  498. fShmNonRtServerControl.writeUInt(bufStrSize);
  499. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  500. fShmNonRtServerControl.commitWrite();
  501. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  502. }
  503. }
  504. // kPluginBridgeNonRtServerMidiProgram*
  505. if (const uint32_t count = plugin->getMidiProgramCount())
  506. {
  507. // uint/count
  508. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiProgramCount);
  509. fShmNonRtServerControl.writeUInt(count);
  510. fShmNonRtServerControl.commitWrite();
  511. for (uint32_t i=0; i < count; ++i)
  512. {
  513. const MidiProgramData& mpData(plugin->getMidiProgramData(i));
  514. CARLA_SAFE_ASSERT_CONTINUE(mpData.name != nullptr);
  515. // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  516. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiProgramData);
  517. fShmNonRtServerControl.writeUInt(i);
  518. fShmNonRtServerControl.writeUInt(mpData.bank);
  519. fShmNonRtServerControl.writeUInt(mpData.program);
  520. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(mpData.name)));
  521. fShmNonRtServerControl.writeUInt(bufStrSize);
  522. fShmNonRtServerControl.writeCustomData(mpData.name, bufStrSize);
  523. fShmNonRtServerControl.commitWrite();
  524. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  525. }
  526. }
  527. if (const uint32_t latency = plugin->getLatencyInFrames())
  528. {
  529. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetLatency);
  530. fShmNonRtServerControl.writeUInt(latency);
  531. fShmNonRtServerControl.commitWrite();
  532. }
  533. // ready!
  534. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
  535. fShmNonRtServerControl.commitWrite();
  536. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  537. carla_stdout("Carla Bridge Ready!");
  538. fLastPingTime = carla_gettime_ms();
  539. }
  540. // send parameter outputs
  541. if (const uint32_t count = plugin->getParameterCount())
  542. {
  543. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  544. for (uint32_t i=0; i < count; ++i)
  545. {
  546. if (! plugin->isParameterOutput(i))
  547. continue;
  548. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue2);
  549. fShmNonRtServerControl.writeUInt(i);
  550. fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i));
  551. // parameter outputs are not that important, we can skip some
  552. if (! fShmNonRtServerControl.commitWrite())
  553. break;
  554. }
  555. }
  556. CarlaEngine::idle();
  557. try {
  558. handleNonRtData();
  559. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  560. if (fLastPingTime != UINT32_MAX && carla_gettime_ms() > fLastPingTime + 30000 && ! wasFirstIdle)
  561. {
  562. carla_stderr("Did not receive ping message from server for 30 secs, closing...");
  563. signalThreadShouldExit();
  564. callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr);
  565. }
  566. }
  567. void callback(const bool sendHost, const bool sendOsc,
  568. const EngineCallbackOpcode action, const uint pluginId,
  569. const int value1, const int value2, const int value3,
  570. const float valuef, const char* const valueStr) noexcept override
  571. {
  572. CarlaEngine::callback(sendHost, sendOsc, action, pluginId, value1, value2, value3, valuef, valueStr);
  573. if (fClosingDown || ! sendHost)
  574. return;
  575. switch (action)
  576. {
  577. // uint/index float/value
  578. case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: {
  579. CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
  580. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  581. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue);
  582. fShmNonRtServerControl.writeUInt(static_cast<uint>(value1));
  583. fShmNonRtServerControl.writeFloat(valuef);
  584. fShmNonRtServerControl.commitWrite();
  585. } break;
  586. // uint/index float/value
  587. case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: {
  588. CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
  589. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  590. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerDefaultValue);
  591. fShmNonRtServerControl.writeUInt(static_cast<uint>(value1));
  592. fShmNonRtServerControl.writeFloat(valuef);
  593. fShmNonRtServerControl.commitWrite();
  594. } break;
  595. // int/index
  596. case ENGINE_CALLBACK_PROGRAM_CHANGED: {
  597. CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
  598. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  599. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCurrentProgram);
  600. fShmNonRtServerControl.writeInt(value1);
  601. fShmNonRtServerControl.commitWrite();
  602. } break;
  603. // int/index
  604. case ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED: {
  605. CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
  606. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  607. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCurrentMidiProgram);
  608. fShmNonRtServerControl.writeInt(value1);
  609. fShmNonRtServerControl.commitWrite();
  610. } break;
  611. case ENGINE_CALLBACK_UI_STATE_CHANGED:
  612. if (value1 != 1)
  613. {
  614. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  615. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
  616. fShmNonRtServerControl.commitWrite();
  617. }
  618. break;
  619. case ENGINE_CALLBACK_EMBED_UI_RESIZED: {
  620. CARLA_SAFE_ASSERT_BREAK(value1 > 1);
  621. CARLA_SAFE_ASSERT_BREAK(value2 > 1);
  622. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  623. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerResizeEmbedUI);
  624. fShmNonRtServerControl.writeUInt(static_cast<uint>(value1));
  625. fShmNonRtServerControl.writeUInt(static_cast<uint>(value2));
  626. fShmNonRtServerControl.commitWrite();
  627. } break;
  628. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  629. if (const CarlaPluginPtr plugin = pData->plugins[0].plugin)
  630. {
  631. if (const uint32_t count = plugin->getParameterCount())
  632. {
  633. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  634. for (uint32_t i=0; i<count; ++i)
  635. {
  636. const ParameterData& paramData(plugin->getParameterData(i));
  637. if (paramData.type != PARAMETER_INPUT && paramData.type != PARAMETER_OUTPUT)
  638. continue;
  639. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  640. continue;
  641. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue);
  642. fShmNonRtServerControl.writeUInt(i);
  643. fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i));
  644. fShmNonRtServerControl.commitWrite();
  645. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  646. }
  647. }
  648. }
  649. break;
  650. default:
  651. break;
  652. }
  653. }
  654. // -------------------------------------------------------------------
  655. void clear() noexcept
  656. {
  657. fShmAudioPool.clear();
  658. fShmRtClientControl.clear();
  659. fShmNonRtClientControl.clear();
  660. fShmNonRtServerControl.clear();
  661. }
  662. void handleNonRtData()
  663. {
  664. const CarlaPluginPtr plugin = pData->plugins[0].plugin;
  665. CARLA_SAFE_ASSERT_RETURN(plugin.get() != nullptr,);
  666. for (; fShmNonRtClientControl.isDataAvailableForReading();)
  667. {
  668. const PluginBridgeNonRtClientOpcode opcode = fShmNonRtClientControl.readOpcode();
  669. #ifdef DEBUG
  670. if (opcode != kPluginBridgeNonRtClientPing) {
  671. carla_debug("CarlaEngineBridge::handleNonRtData() - got opcode: %i:%s",
  672. opcode, PluginBridgeNonRtClientOpcode2str(opcode));
  673. }
  674. #endif
  675. if (opcode != kPluginBridgeNonRtClientNull &&
  676. opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime != UINT32_MAX)
  677. fLastPingTime = carla_gettime_ms();
  678. switch (opcode)
  679. {
  680. case kPluginBridgeNonRtClientNull:
  681. break;
  682. case kPluginBridgeNonRtClientVersion: {
  683. fBridgeVersion = fShmNonRtServerControl.readUInt();
  684. CARLA_SAFE_ASSERT_UINT2(fBridgeVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM,
  685. fBridgeVersion, CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM);
  686. } break;
  687. case kPluginBridgeNonRtClientPing: {
  688. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  689. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  690. fShmNonRtServerControl.commitWrite();
  691. } break;
  692. case kPluginBridgeNonRtClientPingOnOff:
  693. fLastPingTime = fShmNonRtClientControl.readBool() ? carla_gettime_ms() : UINT32_MAX;
  694. break;
  695. case kPluginBridgeNonRtClientActivate:
  696. if (plugin->isEnabled())
  697. plugin->setActive(true, false, false);
  698. break;
  699. case kPluginBridgeNonRtClientDeactivate:
  700. if (plugin->isEnabled())
  701. plugin->setActive(false, false, false);
  702. break;
  703. case kPluginBridgeNonRtClientInitialSetup:
  704. // should never happen!!
  705. fShmNonRtServerControl.readUInt();
  706. fShmNonRtServerControl.readDouble();
  707. break;
  708. case kPluginBridgeNonRtClientSetParameterValue: {
  709. const uint32_t index(fShmNonRtClientControl.readUInt());
  710. const float value(fShmNonRtClientControl.readFloat());
  711. if (plugin->isEnabled())
  712. plugin->setParameterValue(index, value, false, false, false);
  713. break;
  714. }
  715. case kPluginBridgeNonRtClientSetParameterMidiChannel: {
  716. const uint32_t index(fShmNonRtClientControl.readUInt());
  717. const uint8_t channel(fShmNonRtClientControl.readByte());
  718. if (plugin->isEnabled())
  719. plugin->setParameterMidiChannel(index, channel, false, false);
  720. break;
  721. }
  722. case kPluginBridgeNonRtClientSetParameterMappedControlIndex: {
  723. const uint32_t index(fShmNonRtClientControl.readUInt());
  724. const int16_t ctrl(fShmNonRtClientControl.readShort());
  725. if (plugin->isEnabled())
  726. plugin->setParameterMappedControlIndex(index, ctrl, false, false, true);
  727. break;
  728. }
  729. case kPluginBridgeNonRtClientSetParameterMappedRange: {
  730. const uint32_t index = fShmNonRtClientControl.readUInt();
  731. const float minimum = fShmNonRtClientControl.readFloat();
  732. const float maximum = fShmNonRtClientControl.readFloat();
  733. if (plugin->isEnabled())
  734. plugin->setParameterMappedRange(index, minimum, maximum, false, false);
  735. break;
  736. }
  737. case kPluginBridgeNonRtClientSetProgram: {
  738. const int32_t index(fShmNonRtClientControl.readInt());
  739. if (plugin->isEnabled())
  740. plugin->setProgram(index, true, false, false);
  741. break;
  742. }
  743. case kPluginBridgeNonRtClientSetMidiProgram: {
  744. const int32_t index(fShmNonRtClientControl.readInt());
  745. if (plugin->isEnabled())
  746. plugin->setMidiProgram(index, true, false, false);
  747. break;
  748. }
  749. case kPluginBridgeNonRtClientSetCustomData: {
  750. const uint32_t maxLocalValueLen = fBridgeVersion >= 10 ? 4096 : 16384;
  751. // type
  752. const BridgeTextReader type(fShmNonRtClientControl);
  753. // key
  754. const BridgeTextReader key(fShmNonRtClientControl);
  755. // value
  756. const uint32_t valueSize = fShmNonRtClientControl.readUInt();
  757. if (valueSize > 0)
  758. {
  759. if (valueSize > maxLocalValueLen)
  760. {
  761. const BridgeTextReader bigValueFilePathTry(fShmNonRtClientControl, valueSize);
  762. CARLA_SAFE_ASSERT_BREAK(bigValueFilePathTry.text[0] != '\0');
  763. if (! plugin->isEnabled()) break;
  764. String bigValueFilePath(bigValueFilePathTry.text);
  765. #ifdef CARLA_OS_WIN
  766. // check if running under Wine
  767. if (bigValueFilePath.startsWith("/"))
  768. bigValueFilePath = bigValueFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  769. #endif
  770. File bigValueFile(bigValueFilePath);
  771. CARLA_SAFE_ASSERT_BREAK(bigValueFile.existsAsFile());
  772. plugin->setCustomData(type.text, key.text, bigValueFile.loadFileAsString().toRawUTF8(), true);
  773. bigValueFile.deleteFile();
  774. }
  775. else
  776. {
  777. const BridgeTextReader value(fShmNonRtClientControl, valueSize);
  778. if (plugin->isEnabled())
  779. plugin->setCustomData(type.text, key.text, value.text, true);
  780. }
  781. }
  782. else
  783. {
  784. if (plugin->isEnabled())
  785. plugin->setCustomData(type.text, key.text, "", true);
  786. }
  787. break;
  788. }
  789. case kPluginBridgeNonRtClientSetChunkDataFile: {
  790. const uint32_t size = fShmNonRtClientControl.readUInt();
  791. CARLA_SAFE_ASSERT_BREAK(size > 0);
  792. const BridgeTextReader chunkFilePathTry(fShmNonRtClientControl, size);
  793. CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry.text[0] != '\0');
  794. if (! plugin->isEnabled()) break;
  795. String chunkFilePath(chunkFilePathTry.text);
  796. #ifdef CARLA_OS_WIN
  797. // check if running under Wine
  798. if (chunkFilePath.startsWith("/"))
  799. chunkFilePath = chunkFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  800. #endif
  801. File chunkFile(chunkFilePath);
  802. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  803. String chunkDataBase64(chunkFile.loadFileAsString());
  804. chunkFile.deleteFile();
  805. CARLA_SAFE_ASSERT_BREAK(chunkDataBase64.isNotEmpty());
  806. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(chunkDataBase64.toRawUTF8()));
  807. #ifdef CARLA_PROPER_CPP11_SUPPORT
  808. plugin->setChunkData(chunk.data(), chunk.size());
  809. #else
  810. plugin->setChunkData(&chunk.front(), chunk.size());
  811. #endif
  812. break;
  813. }
  814. case kPluginBridgeNonRtClientSetCtrlChannel: {
  815. const int16_t channel(fShmNonRtClientControl.readShort());
  816. CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS);
  817. if (plugin->isEnabled())
  818. plugin->setCtrlChannel(static_cast<int8_t>(channel), false, false);
  819. break;
  820. }
  821. case kPluginBridgeNonRtClientSetOption: {
  822. const uint32_t option(fShmNonRtClientControl.readUInt());
  823. const bool yesNo(fShmNonRtClientControl.readBool());
  824. if (plugin->isEnabled())
  825. plugin->setOption(option, yesNo, false);
  826. break;
  827. }
  828. case kPluginBridgeNonRtClientSetOptions: {
  829. const uint32_t options(fShmNonRtClientControl.readUInt());
  830. plugin->pData->options = options;
  831. break;
  832. }
  833. case kPluginBridgeNonRtClientSetWindowTitle: {
  834. const BridgeTextReader title(fShmNonRtClientControl);
  835. plugin->setCustomUITitle(title.text);
  836. break;
  837. }
  838. case kPluginBridgeNonRtClientGetParameterText: {
  839. const int32_t index = fShmNonRtClientControl.readInt();
  840. if (index >= 0 && plugin->isEnabled())
  841. {
  842. char bufStr[STR_MAX+1];
  843. carla_zeroChars(bufStr, STR_MAX+1);
  844. if (! plugin->getParameterText(static_cast<uint32_t>(index), bufStr))
  845. bufStr[0] = '\0';
  846. const uint32_t bufStrLen = static_cast<uint32_t>(std::strlen(bufStr));
  847. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  848. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetParameterText);
  849. fShmNonRtServerControl.writeInt(index);
  850. fShmNonRtServerControl.writeUInt(bufStrLen);
  851. fShmNonRtServerControl.writeCustomData(bufStr, bufStrLen);
  852. fShmNonRtServerControl.commitWrite();
  853. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  854. }
  855. else
  856. {
  857. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  858. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetParameterText);
  859. fShmNonRtServerControl.writeInt(index);
  860. fShmNonRtServerControl.writeUInt(0);
  861. fShmNonRtServerControl.commitWrite();
  862. }
  863. break;
  864. }
  865. case kPluginBridgeNonRtClientPrepareForSave: {
  866. if (! plugin->isEnabled())
  867. {
  868. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  869. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  870. fShmNonRtServerControl.commitWrite();
  871. return;
  872. }
  873. plugin->prepareForSave(false);
  874. const uint32_t maxLocalValueLen = fBridgeVersion >= 10 ? 4096 : 16384;
  875. for (uint32_t i=0, count=plugin->getCustomDataCount(); i<count; ++i)
  876. {
  877. const CustomData& cdata(plugin->getCustomData(i));
  878. if (std::strcmp(cdata.type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
  879. continue;
  880. const uint32_t typeLen = static_cast<uint32_t>(std::strlen(cdata.type));
  881. const uint32_t keyLen = static_cast<uint32_t>(std::strlen(cdata.key));
  882. const uint32_t valueLen = static_cast<uint32_t>(std::strlen(cdata.value));
  883. {
  884. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  885. if (valueLen > maxLocalValueLen)
  886. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  887. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetCustomData);
  888. fShmNonRtServerControl.writeUInt(typeLen);
  889. fShmNonRtServerControl.writeCustomData(cdata.type, typeLen);
  890. fShmNonRtServerControl.writeUInt(keyLen);
  891. fShmNonRtServerControl.writeCustomData(cdata.key, keyLen);
  892. fShmNonRtServerControl.writeUInt(valueLen);
  893. if (valueLen > 0)
  894. {
  895. if (valueLen > maxLocalValueLen)
  896. {
  897. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  898. filePath += CARLA_OS_SEP_STR ".CarlaCustomData_";
  899. filePath += fShmAudioPool.getFilenameSuffix();
  900. if (File(filePath).replaceWithText(cdata.value))
  901. {
  902. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  903. fShmNonRtServerControl.writeUInt(ulength);
  904. fShmNonRtServerControl.writeCustomData(filePath.toRawUTF8(), ulength);
  905. }
  906. else
  907. {
  908. fShmNonRtServerControl.writeUInt(0);
  909. }
  910. }
  911. else
  912. {
  913. fShmNonRtServerControl.writeCustomData(cdata.value, valueLen);
  914. }
  915. }
  916. fShmNonRtServerControl.commitWrite();
  917. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  918. }
  919. }
  920. if (plugin->getOptionsEnabled() & PLUGIN_OPTION_USE_CHUNKS)
  921. {
  922. void* data = nullptr;
  923. if (const std::size_t dataSize = plugin->getChunkData(&data))
  924. {
  925. CARLA_SAFE_ASSERT_BREAK(data != nullptr);
  926. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  927. CARLA_SAFE_ASSERT_BREAK(dataBase64.length() > 0);
  928. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  929. filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
  930. filePath += fShmAudioPool.getFilenameSuffix();
  931. if (File(filePath).replaceWithText(dataBase64.buffer()))
  932. {
  933. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  934. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  935. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetChunkDataFile);
  936. fShmNonRtServerControl.writeUInt(ulength);
  937. fShmNonRtServerControl.writeCustomData(filePath.toRawUTF8(), ulength);
  938. fShmNonRtServerControl.commitWrite();
  939. }
  940. }
  941. }
  942. {
  943. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  944. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  945. fShmNonRtServerControl.commitWrite();
  946. }
  947. break;
  948. }
  949. case kPluginBridgeNonRtClientRestoreLV2State:
  950. if (plugin->isEnabled())
  951. plugin->restoreLV2State(false);
  952. break;
  953. case kPluginBridgeNonRtClientShowUI:
  954. if (plugin->isEnabled())
  955. plugin->showCustomUI(true);
  956. break;
  957. case kPluginBridgeNonRtClientHideUI:
  958. if (plugin->isEnabled())
  959. plugin->showCustomUI(false);
  960. break;
  961. case kPluginBridgeNonRtClientEmbedUI: {
  962. const uint64_t winId = fShmNonRtClientControl.readULong();
  963. uint64_t resp = 0;
  964. if (plugin->isEnabled())
  965. resp = reinterpret_cast<uint64_t>(plugin->embedCustomUI(reinterpret_cast<void*>(winId)));
  966. if (resp == 0)
  967. resp = 1;
  968. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  969. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerRespEmbedUI);
  970. fShmNonRtServerControl.writeULong(resp);
  971. fShmNonRtServerControl.commitWrite();
  972. break;
  973. }
  974. case kPluginBridgeNonRtClientUiParameterChange: {
  975. const uint32_t index = fShmNonRtClientControl.readUInt();
  976. const float value = fShmNonRtClientControl.readFloat();
  977. if (plugin->isEnabled())
  978. plugin->uiParameterChange(index, value);
  979. break;
  980. }
  981. case kPluginBridgeNonRtClientUiProgramChange: {
  982. const uint32_t index(fShmNonRtClientControl.readUInt());
  983. if (plugin->isEnabled())
  984. plugin->uiProgramChange(index);
  985. break;
  986. }
  987. case kPluginBridgeNonRtClientUiMidiProgramChange: {
  988. const uint32_t index(fShmNonRtClientControl.readUInt());
  989. if (plugin->isEnabled())
  990. plugin->uiMidiProgramChange(index);
  991. break;
  992. }
  993. case kPluginBridgeNonRtClientUiNoteOn: {
  994. const uint8_t chnl(fShmNonRtClientControl.readByte());
  995. const uint8_t note(fShmNonRtClientControl.readByte());
  996. const uint8_t velo(fShmNonRtClientControl.readByte());
  997. if (plugin->isEnabled())
  998. plugin->uiNoteOn(chnl, note, velo);
  999. break;
  1000. }
  1001. case kPluginBridgeNonRtClientUiNoteOff: {
  1002. const uint8_t chnl(fShmNonRtClientControl.readByte());
  1003. const uint8_t note(fShmNonRtClientControl.readByte());
  1004. if (plugin->isEnabled())
  1005. plugin->uiNoteOff(chnl, note);
  1006. break;
  1007. }
  1008. case kPluginBridgeNonRtClientQuit:
  1009. fClosingDown = true;
  1010. signalThreadShouldExit();
  1011. callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr);
  1012. break;
  1013. case kPluginBridgeNonRtClientReload:
  1014. fFirstIdle = true;
  1015. break;
  1016. }
  1017. }
  1018. }
  1019. // -------------------------------------------------------------------
  1020. protected:
  1021. void run() override
  1022. {
  1023. #ifdef __SSE2_MATH__
  1024. // Set FTZ and DAZ flags
  1025. _mm_setcsr(_mm_getcsr() | 0x8040);
  1026. #endif
  1027. bool quitReceived = false;
  1028. for (; ! shouldThreadExit();)
  1029. {
  1030. const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl);
  1031. if (! helper.ok)
  1032. continue;
  1033. for (; fShmRtClientControl.isDataAvailableForReading();)
  1034. {
  1035. const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
  1036. const CarlaPluginPtr plugin = pData->plugins[0].plugin;
  1037. #ifdef DEBUG
  1038. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent) {
  1039. carla_debug("CarlaEngineBridgeRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
  1040. }
  1041. #endif
  1042. switch (opcode)
  1043. {
  1044. case kPluginBridgeRtClientNull:
  1045. break;
  1046. case kPluginBridgeRtClientSetAudioPool: {
  1047. if (fShmAudioPool.data != nullptr)
  1048. {
  1049. jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data);
  1050. fShmAudioPool.data = nullptr;
  1051. }
  1052. const uint64_t poolSize(fShmRtClientControl.readULong());
  1053. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  1054. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  1055. break;
  1056. }
  1057. case kPluginBridgeRtClientSetBufferSize: {
  1058. const uint32_t bufferSize(fShmRtClientControl.readUInt());
  1059. pData->bufferSize = bufferSize;
  1060. bufferSizeChanged(bufferSize);
  1061. break;
  1062. }
  1063. case kPluginBridgeRtClientSetSampleRate: {
  1064. const double sampleRate(fShmRtClientControl.readDouble());
  1065. pData->sampleRate = sampleRate;
  1066. sampleRateChanged(sampleRate);
  1067. break;
  1068. }
  1069. case kPluginBridgeRtClientSetOnline:
  1070. fIsOffline = fShmRtClientControl.readBool();
  1071. offlineModeChanged(fIsOffline);
  1072. break;
  1073. // NOTE this is never used
  1074. case kPluginBridgeRtClientControlEventParameter: {
  1075. const uint32_t time(fShmRtClientControl.readUInt());
  1076. const uint8_t channel(fShmRtClientControl.readByte());
  1077. const uint16_t param(fShmRtClientControl.readUShort());
  1078. const float value(fShmRtClientControl.readFloat());
  1079. if (EngineEvent* const event = getNextFreeInputEvent())
  1080. {
  1081. event->type = kEngineEventTypeControl;
  1082. event->time = time;
  1083. event->channel = channel;
  1084. event->ctrl.type = kEngineControlEventTypeParameter;
  1085. event->ctrl.param = param;
  1086. event->ctrl.midiValue = -1;
  1087. event->ctrl.normalizedValue = value;
  1088. event->ctrl.handled = true;
  1089. }
  1090. break;
  1091. }
  1092. case kPluginBridgeRtClientControlEventMidiBank: {
  1093. const uint32_t time(fShmRtClientControl.readUInt());
  1094. const uint8_t channel(fShmRtClientControl.readByte());
  1095. const uint16_t index(fShmRtClientControl.readUShort());
  1096. if (EngineEvent* const event = getNextFreeInputEvent())
  1097. {
  1098. event->type = kEngineEventTypeControl;
  1099. event->time = time;
  1100. event->channel = channel;
  1101. event->ctrl.type = kEngineControlEventTypeMidiBank;
  1102. event->ctrl.param = index;
  1103. event->ctrl.midiValue = -1;
  1104. event->ctrl.normalizedValue = 0.0f;
  1105. event->ctrl.handled = true;
  1106. }
  1107. break;
  1108. }
  1109. case kPluginBridgeRtClientControlEventMidiProgram: {
  1110. const uint32_t time(fShmRtClientControl.readUInt());
  1111. const uint8_t channel(fShmRtClientControl.readByte());
  1112. const uint16_t index(fShmRtClientControl.readUShort());
  1113. if (EngineEvent* const event = getNextFreeInputEvent())
  1114. {
  1115. event->type = kEngineEventTypeControl;
  1116. event->time = time;
  1117. event->channel = channel;
  1118. event->ctrl.type = kEngineControlEventTypeMidiProgram;
  1119. event->ctrl.param = index;
  1120. event->ctrl.midiValue = -1;
  1121. event->ctrl.normalizedValue = 0.0f;
  1122. event->ctrl.handled = true;
  1123. }
  1124. break;
  1125. }
  1126. case kPluginBridgeRtClientControlEventAllSoundOff: {
  1127. const uint32_t time(fShmRtClientControl.readUInt());
  1128. const uint8_t channel(fShmRtClientControl.readByte());
  1129. if (EngineEvent* const event = getNextFreeInputEvent())
  1130. {
  1131. event->type = kEngineEventTypeControl;
  1132. event->time = time;
  1133. event->channel = channel;
  1134. event->ctrl.type = kEngineControlEventTypeAllSoundOff;
  1135. event->ctrl.param = 0;
  1136. event->ctrl.midiValue = -1;
  1137. event->ctrl.normalizedValue = 0.0f;
  1138. event->ctrl.handled = true;
  1139. }
  1140. } break;
  1141. case kPluginBridgeRtClientControlEventAllNotesOff: {
  1142. const uint32_t time(fShmRtClientControl.readUInt());
  1143. const uint8_t channel(fShmRtClientControl.readByte());
  1144. if (EngineEvent* const event = getNextFreeInputEvent())
  1145. {
  1146. event->type = kEngineEventTypeControl;
  1147. event->time = time;
  1148. event->channel = channel;
  1149. event->ctrl.type = kEngineControlEventTypeAllNotesOff;
  1150. event->ctrl.param = 0;
  1151. event->ctrl.midiValue = -1;
  1152. event->ctrl.normalizedValue = 0.0f;
  1153. event->ctrl.handled = true;
  1154. }
  1155. } break;
  1156. case kPluginBridgeRtClientMidiEvent: {
  1157. const uint32_t time(fShmRtClientControl.readUInt());
  1158. const uint8_t port(fShmRtClientControl.readByte());
  1159. const uint8_t size(fShmRtClientControl.readByte());
  1160. CARLA_SAFE_ASSERT_BREAK(size > 0);
  1161. // FIXME variable-size stack
  1162. uint8_t data[4];
  1163. {
  1164. uint8_t i=0;
  1165. for (; i<size && i<4; ++i)
  1166. data[i] = fShmRtClientControl.readByte();
  1167. for (; i<size; ++i)
  1168. fShmRtClientControl.readByte();
  1169. }
  1170. if (size > 4)
  1171. continue;
  1172. if (EngineEvent* const event = getNextFreeInputEvent())
  1173. {
  1174. event->type = kEngineEventTypeMidi;
  1175. event->time = time;
  1176. event->channel = MIDI_GET_CHANNEL_FROM_DATA(data);
  1177. event->midi.port = port;
  1178. event->midi.size = size;
  1179. if (size > EngineMidiEvent::kDataSize)
  1180. {
  1181. event->midi.dataExt = data;
  1182. std::memset(event->midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize);
  1183. }
  1184. else
  1185. {
  1186. event->midi.data[0] = MIDI_GET_STATUS_FROM_DATA(data);
  1187. uint8_t i=1;
  1188. for (; i < size; ++i)
  1189. event->midi.data[i] = data[i];
  1190. for (; i < EngineMidiEvent::kDataSize; ++i)
  1191. event->midi.data[i] = 0;
  1192. event->midi.dataExt = nullptr;
  1193. }
  1194. }
  1195. break;
  1196. }
  1197. case kPluginBridgeRtClientProcess: {
  1198. const uint32_t frames(fShmRtClientControl.readUInt());
  1199. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  1200. if (plugin.get() != nullptr && plugin->isEnabled() && plugin->tryLock(fIsOffline))
  1201. {
  1202. const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  1203. const uint32_t audioInCount = plugin->getAudioInCount();
  1204. const uint32_t audioOutCount = plugin->getAudioOutCount();
  1205. const uint32_t cvInCount = plugin->getCVInCount();
  1206. const uint32_t cvOutCount = plugin->getCVOutCount();
  1207. const float* audioIn[64];
  1208. /* */ float* audioOut[64];
  1209. const float* cvIn[32];
  1210. /* */ float* cvOut[32];
  1211. float* fdata = fShmAudioPool.data;
  1212. for (uint32_t i=0; i < audioInCount; ++i, fdata += pData->bufferSize)
  1213. audioIn[i] = fdata;
  1214. for (uint32_t i=0; i < audioOutCount; ++i, fdata += pData->bufferSize)
  1215. audioOut[i] = fdata;
  1216. for (uint32_t i=0; i < cvInCount; ++i, fdata += pData->bufferSize)
  1217. cvIn[i] = fdata;
  1218. for (uint32_t i=0; i < cvOutCount; ++i, fdata += pData->bufferSize)
  1219. cvOut[i] = fdata;
  1220. EngineTimeInfo& timeInfo(pData->timeInfo);
  1221. timeInfo.playing = bridgeTimeInfo.playing;
  1222. timeInfo.frame = bridgeTimeInfo.frame;
  1223. timeInfo.usecs = bridgeTimeInfo.usecs;
  1224. timeInfo.bbt.valid = (bridgeTimeInfo.validFlags & kPluginBridgeTimeInfoValidBBT) != 0;
  1225. if (timeInfo.bbt.valid)
  1226. {
  1227. timeInfo.bbt.bar = bridgeTimeInfo.bar;
  1228. timeInfo.bbt.beat = bridgeTimeInfo.beat;
  1229. timeInfo.bbt.tick = bridgeTimeInfo.tick;
  1230. timeInfo.bbt.beatsPerBar = bridgeTimeInfo.beatsPerBar;
  1231. timeInfo.bbt.beatType = bridgeTimeInfo.beatType;
  1232. timeInfo.bbt.ticksPerBeat = bridgeTimeInfo.ticksPerBeat;
  1233. timeInfo.bbt.beatsPerMinute = bridgeTimeInfo.beatsPerMinute;
  1234. timeInfo.bbt.barStartTick = bridgeTimeInfo.barStartTick;
  1235. }
  1236. plugin->initBuffers();
  1237. plugin->process(audioIn, audioOut, cvIn, cvOut, frames);
  1238. plugin->unlock();
  1239. }
  1240. uint8_t* midiData(fShmRtClientControl.data->midiOut);
  1241. carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
  1242. std::size_t curMidiDataPos = 0;
  1243. if (pData->events.in[0].type != kEngineEventTypeNull)
  1244. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  1245. if (pData->events.out[0].type != kEngineEventTypeNull)
  1246. {
  1247. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  1248. {
  1249. const EngineEvent& event(pData->events.out[i]);
  1250. if (event.type == kEngineEventTypeNull)
  1251. break;
  1252. if (event.type == kEngineEventTypeControl)
  1253. {
  1254. uint8_t data[3];
  1255. const uint8_t size = event.ctrl.convertToMidiData(event.channel, data);
  1256. CARLA_SAFE_ASSERT_CONTINUE(size > 0 && size <= 3);
  1257. if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + size >= kBridgeRtClientDataMidiOutSize)
  1258. break;
  1259. // set time
  1260. *(uint32_t*)midiData = event.time;
  1261. midiData = midiData + 4;
  1262. curMidiDataPos += 4;
  1263. // set port
  1264. *midiData++ = 0;
  1265. ++curMidiDataPos;
  1266. // set size
  1267. *midiData++ = size;
  1268. ++curMidiDataPos;
  1269. // set data
  1270. for (uint8_t j=0; j<size; ++j)
  1271. *midiData++ = data[j];
  1272. curMidiDataPos += size;
  1273. }
  1274. else if (event.type == kEngineEventTypeMidi)
  1275. {
  1276. const EngineMidiEvent& _midiEvent(event.midi);
  1277. if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + _midiEvent.size >= kBridgeRtClientDataMidiOutSize)
  1278. break;
  1279. const uint8_t* const _midiData(_midiEvent.dataExt != nullptr ? _midiEvent.dataExt : _midiEvent.data);
  1280. // set time
  1281. *(uint32_t*)midiData = event.time;
  1282. midiData += 4;
  1283. curMidiDataPos += 4;
  1284. // set port
  1285. *midiData++ = _midiEvent.port;
  1286. ++curMidiDataPos;
  1287. // set size
  1288. *midiData++ = _midiEvent.size;
  1289. ++curMidiDataPos;
  1290. // set data
  1291. *midiData++ = uint8_t(_midiData[0] | (event.channel & MIDI_CHANNEL_BIT));
  1292. for (uint8_t j=1; j<_midiEvent.size; ++j)
  1293. *midiData++ = _midiData[j];
  1294. curMidiDataPos += _midiEvent.size;
  1295. }
  1296. }
  1297. if (curMidiDataPos != 0 &&
  1298. curMidiDataPos + kBridgeBaseMidiOutHeaderSize < kBridgeRtClientDataMidiOutSize)
  1299. carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
  1300. carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount);
  1301. }
  1302. } break;
  1303. case kPluginBridgeRtClientQuit: {
  1304. quitReceived = true;
  1305. fClosingDown = true;
  1306. signalThreadShouldExit();
  1307. } break;
  1308. }
  1309. }
  1310. }
  1311. callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0, 0.0f, nullptr);
  1312. if (! quitReceived)
  1313. {
  1314. const char* const message("Plugin bridge error, process thread has stopped");
  1315. const std::size_t messageSize(std::strlen(message));
  1316. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  1317. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  1318. fShmNonRtServerControl.writeUInt(messageSize);
  1319. fShmNonRtServerControl.writeCustomData(message, messageSize);
  1320. fShmNonRtServerControl.commitWrite();
  1321. }
  1322. }
  1323. // called from process thread above
  1324. EngineEvent* getNextFreeInputEvent() const noexcept
  1325. {
  1326. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  1327. {
  1328. EngineEvent* const event(&pData->events.in[i]);
  1329. if (event->type == kEngineEventTypeNull)
  1330. return event;
  1331. }
  1332. return nullptr;
  1333. }
  1334. void latencyChanged(const uint32_t samples) noexcept override
  1335. {
  1336. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  1337. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetLatency);
  1338. fShmNonRtServerControl.writeUInt(samples);
  1339. fShmNonRtServerControl.commitWrite();
  1340. }
  1341. // -------------------------------------------------------------------
  1342. private:
  1343. BridgeAudioPool fShmAudioPool;
  1344. BridgeRtClientControl fShmRtClientControl;
  1345. BridgeNonRtClientControl fShmNonRtClientControl;
  1346. BridgeNonRtServerControl fShmNonRtServerControl;
  1347. CarlaString fBaseNameAudioPool;
  1348. CarlaString fBaseNameRtClientControl;
  1349. CarlaString fBaseNameNonRtClientControl;
  1350. CarlaString fBaseNameNonRtServerControl;
  1351. bool fClosingDown;
  1352. bool fIsOffline;
  1353. bool fFirstIdle;
  1354. uint32_t fBridgeVersion;
  1355. uint32_t fLastPingTime;
  1356. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  1357. };
  1358. // -----------------------------------------------------------------------
  1359. namespace EngineInit {
  1360. CarlaEngine* newBridge(const char* const audioPoolBaseName,
  1361. const char* const rtClientBaseName,
  1362. const char* const nonRtClientBaseName,
  1363. const char* const nonRtServerBaseName)
  1364. {
  1365. return new CarlaEngineBridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
  1366. }
  1367. }
  1368. // -----------------------------------------------------------------------
  1369. CARLA_BACKEND_END_NAMESPACE
  1370. // -----------------------------------------------------------------------
  1371. #include "CarlaBridgeUtils.cpp"
  1372. // -----------------------------------------------------------------------