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

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