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 57KB

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