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.

2386 lines
80KB

  1. /*
  2. * Carla Plugin Bridge
  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. #ifdef BUILD_BRIDGE
  18. # error This file should be used under bridge mode
  19. #endif
  20. #include "CarlaPluginInternal.hpp"
  21. #include "CarlaEngine.hpp"
  22. #include "CarlaBackendUtils.hpp"
  23. #include "CarlaBase64Utils.hpp"
  24. #include "CarlaBridgeUtils.hpp"
  25. #include "CarlaMathUtils.hpp"
  26. #include "CarlaShmUtils.hpp"
  27. #include "CarlaThread.hpp"
  28. #include "jackbridge/JackBridge.hpp"
  29. #include <ctime>
  30. // -------------------------------------------------------------------------------------------------------------------
  31. using juce::ChildProcess;
  32. using juce::File;
  33. using juce::ScopedPointer;
  34. using juce::String;
  35. using juce::StringArray;
  36. CARLA_BACKEND_START_NAMESPACE
  37. // -------------------------------------------------------------------------------------------------------------------
  38. struct BridgeAudioPool {
  39. CarlaString filename;
  40. std::size_t size;
  41. float* data;
  42. shm_t shm;
  43. BridgeAudioPool() noexcept
  44. : filename(),
  45. size(0),
  46. data(nullptr)
  47. #ifdef CARLA_PROPER_CPP11_SUPPORT
  48. , shm(shm_t_INIT) {}
  49. #else
  50. {
  51. shm = shm_t_INIT;
  52. }
  53. #endif
  54. ~BridgeAudioPool() noexcept
  55. {
  56. // should be cleared by now
  57. CARLA_SAFE_ASSERT(data == nullptr);
  58. clear();
  59. }
  60. bool initialize() noexcept
  61. {
  62. char tmpFileBase[64];
  63. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "XXXXXX");
  64. shm = carla_shm_create_temp(tmpFileBase);
  65. if (! carla_is_shm_valid(shm))
  66. return false;
  67. filename = tmpFileBase;
  68. return true;
  69. }
  70. void clear() noexcept
  71. {
  72. filename.clear();
  73. if (! carla_is_shm_valid(shm))
  74. {
  75. CARLA_SAFE_ASSERT(data == nullptr);
  76. return;
  77. }
  78. if (data != nullptr)
  79. {
  80. carla_shm_unmap(shm, data);
  81. data = nullptr;
  82. }
  83. size = 0;
  84. carla_shm_close(shm);
  85. carla_shm_init(shm);
  86. }
  87. void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept
  88. {
  89. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm),);
  90. if (data != nullptr)
  91. carla_shm_unmap(shm, data);
  92. size = (audioPortCount+cvPortCount)*bufferSize*sizeof(float);
  93. if (size == 0)
  94. size = sizeof(float);
  95. data = (float*)carla_shm_map(shm, size);
  96. }
  97. CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
  98. };
  99. // -------------------------------------------------------------------------------------------------------------------
  100. struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
  101. BridgeRtClientData* data;
  102. CarlaString filename;
  103. bool needsSemDestroy;
  104. shm_t shm;
  105. BridgeRtClientControl()
  106. : data(nullptr),
  107. filename(),
  108. needsSemDestroy(false),
  109. #ifdef CARLA_PROPER_CPP11_SUPPORT
  110. shm(shm_t_INIT) {}
  111. #else
  112. {
  113. shm = shm_t_INIT;
  114. }
  115. #endif
  116. ~BridgeRtClientControl() noexcept override
  117. {
  118. // should be cleared by now
  119. CARLA_SAFE_ASSERT(data == nullptr);
  120. clear();
  121. }
  122. bool initialize() noexcept
  123. {
  124. char tmpFileBase[64];
  125. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "XXXXXX");
  126. shm = carla_shm_create_temp(tmpFileBase);
  127. if (! carla_is_shm_valid(shm))
  128. return false;
  129. if (! mapData())
  130. {
  131. carla_shm_close(shm);
  132. carla_shm_init(shm);
  133. return false;
  134. }
  135. CARLA_SAFE_ASSERT(data != nullptr);
  136. if (! jackbridge_sem_init(&data->sem.server))
  137. {
  138. unmapData();
  139. carla_shm_close(shm);
  140. carla_shm_init(shm);
  141. return false;
  142. }
  143. if (! jackbridge_sem_init(&data->sem.client))
  144. {
  145. jackbridge_sem_destroy(&data->sem.server);
  146. unmapData();
  147. carla_shm_close(shm);
  148. carla_shm_init(shm);
  149. return false;
  150. }
  151. filename = tmpFileBase;
  152. needsSemDestroy = true;
  153. return true;
  154. }
  155. void clear() noexcept
  156. {
  157. filename.clear();
  158. if (needsSemDestroy)
  159. {
  160. jackbridge_sem_destroy(&data->sem.client);
  161. jackbridge_sem_destroy(&data->sem.server);
  162. needsSemDestroy = false;
  163. }
  164. if (data != nullptr)
  165. unmapData();
  166. if (! carla_is_shm_valid(shm))
  167. {
  168. CARLA_SAFE_ASSERT(data == nullptr);
  169. return;
  170. }
  171. carla_shm_close(shm);
  172. carla_shm_init(shm);
  173. }
  174. bool mapData() noexcept
  175. {
  176. CARLA_SAFE_ASSERT(data == nullptr);
  177. if (carla_shm_map<BridgeRtClientData>(shm, data))
  178. {
  179. carla_zeroStruct(data->sem);
  180. carla_zeroStruct(data->timeInfo);
  181. carla_zeroBytes(data->midiOut, kBridgeRtClientDataMidiOutSize);
  182. setRingBuffer(&data->ringBuffer, true);
  183. return true;
  184. }
  185. return false;
  186. }
  187. void unmapData() noexcept
  188. {
  189. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  190. carla_shm_unmap(shm, data);
  191. data = nullptr;
  192. setRingBuffer(nullptr, false);
  193. }
  194. bool waitForClient(const uint secs) noexcept
  195. {
  196. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  197. jackbridge_sem_post(&data->sem.server);
  198. return jackbridge_sem_timedwait(&data->sem.client, secs);
  199. }
  200. void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
  201. {
  202. writeUInt(static_cast<uint32_t>(opcode));
  203. }
  204. CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
  205. };
  206. // -------------------------------------------------------------------------------------------------------------------
  207. struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
  208. BridgeNonRtClientData* data;
  209. CarlaString filename;
  210. CarlaMutex mutex;
  211. shm_t shm;
  212. BridgeNonRtClientControl() noexcept
  213. : data(nullptr),
  214. filename(),
  215. mutex()
  216. #ifdef CARLA_PROPER_CPP11_SUPPORT
  217. , shm(shm_t_INIT) {}
  218. #else
  219. {
  220. shm = shm_t_INIT;
  221. }
  222. #endif
  223. ~BridgeNonRtClientControl() noexcept override
  224. {
  225. // should be cleared by now
  226. CARLA_SAFE_ASSERT(data == nullptr);
  227. clear();
  228. }
  229. bool initialize() noexcept
  230. {
  231. char tmpFileBase[64];
  232. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "XXXXXX");
  233. shm = carla_shm_create_temp(tmpFileBase);
  234. if (! carla_is_shm_valid(shm))
  235. return false;
  236. if (! mapData())
  237. {
  238. carla_shm_close(shm);
  239. carla_shm_init(shm);
  240. return false;
  241. }
  242. CARLA_SAFE_ASSERT(data != nullptr);
  243. filename = tmpFileBase;
  244. return true;
  245. }
  246. void clear() noexcept
  247. {
  248. filename.clear();
  249. if (data != nullptr)
  250. unmapData();
  251. if (! carla_is_shm_valid(shm))
  252. {
  253. CARLA_SAFE_ASSERT(data == nullptr);
  254. return;
  255. }
  256. carla_shm_close(shm);
  257. carla_shm_init(shm);
  258. }
  259. bool mapData() noexcept
  260. {
  261. CARLA_SAFE_ASSERT(data == nullptr);
  262. if (carla_shm_map<BridgeNonRtClientData>(shm, data))
  263. {
  264. setRingBuffer(&data->ringBuffer, true);
  265. return true;
  266. }
  267. return false;
  268. }
  269. void unmapData() noexcept
  270. {
  271. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  272. carla_shm_unmap(shm, data);
  273. data = nullptr;
  274. setRingBuffer(nullptr, false);
  275. }
  276. void writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept
  277. {
  278. writeUInt(static_cast<uint32_t>(opcode));
  279. }
  280. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl)
  281. };
  282. // -------------------------------------------------------------------------------------------------------------------
  283. struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> {
  284. BridgeNonRtServerData* data;
  285. CarlaString filename;
  286. shm_t shm;
  287. BridgeNonRtServerControl() noexcept
  288. : data(nullptr),
  289. filename()
  290. #ifdef CARLA_PROPER_CPP11_SUPPORT
  291. , shm(shm_t_INIT) {}
  292. #else
  293. {
  294. shm = shm_t_INIT;
  295. }
  296. #endif
  297. ~BridgeNonRtServerControl() noexcept override
  298. {
  299. // should be cleared by now
  300. CARLA_SAFE_ASSERT(data == nullptr);
  301. clear();
  302. }
  303. bool initialize() noexcept
  304. {
  305. char tmpFileBase[64];
  306. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "XXXXXX");
  307. shm = carla_shm_create_temp(tmpFileBase);
  308. if (! carla_is_shm_valid(shm))
  309. return false;
  310. if (! mapData())
  311. {
  312. carla_shm_close(shm);
  313. carla_shm_init(shm);
  314. return false;
  315. }
  316. CARLA_SAFE_ASSERT(data != nullptr);
  317. filename = tmpFileBase;
  318. return true;
  319. }
  320. void clear() noexcept
  321. {
  322. filename.clear();
  323. if (data != nullptr)
  324. unmapData();
  325. if (! carla_is_shm_valid(shm))
  326. {
  327. CARLA_SAFE_ASSERT(data == nullptr);
  328. return;
  329. }
  330. carla_shm_close(shm);
  331. carla_shm_init(shm);
  332. }
  333. bool mapData() noexcept
  334. {
  335. CARLA_SAFE_ASSERT(data == nullptr);
  336. if (carla_shm_map<BridgeNonRtServerData>(shm, data))
  337. {
  338. setRingBuffer(&data->ringBuffer, true);
  339. return true;
  340. }
  341. return false;
  342. }
  343. void unmapData() noexcept
  344. {
  345. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  346. carla_shm_unmap(shm, data);
  347. data = nullptr;
  348. setRingBuffer(nullptr, false);
  349. }
  350. PluginBridgeNonRtServerOpcode readOpcode() noexcept
  351. {
  352. return static_cast<PluginBridgeNonRtServerOpcode>(readUInt());
  353. }
  354. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl)
  355. };
  356. // -------------------------------------------------------------------------------------------------------------------
  357. struct BridgeParamInfo {
  358. float value;
  359. CarlaString name;
  360. CarlaString unit;
  361. BridgeParamInfo() noexcept
  362. : value(0.0f),
  363. name(),
  364. unit() {}
  365. CARLA_DECLARE_NON_COPY_STRUCT(BridgeParamInfo)
  366. };
  367. // -------------------------------------------------------------------------------------------------------------------
  368. class CarlaPluginBridgeThread : public CarlaThread
  369. {
  370. public:
  371. CarlaPluginBridgeThread(CarlaEngine* const engine, CarlaPlugin* const plugin) noexcept
  372. : CarlaThread("CarlaPluginBridgeThread"),
  373. kEngine(engine),
  374. kPlugin(plugin),
  375. fBinary(),
  376. fLabel(),
  377. fShmIds(),
  378. fPluginType(PLUGIN_NONE),
  379. fProcess(),
  380. leakDetector_CarlaPluginBridgeThread() {}
  381. void setData(const char* const binary, const char* const label, const char* const shmIds, const PluginType ptype) noexcept
  382. {
  383. CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',);
  384. CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0',);
  385. CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',);
  386. CARLA_SAFE_ASSERT(! isThreadRunning());
  387. fBinary = binary;
  388. fLabel = binary;
  389. fShmIds = shmIds;
  390. fPluginType = ptype;
  391. }
  392. protected:
  393. void run()
  394. {
  395. if (fProcess == nullptr)
  396. {
  397. fProcess = new ChildProcess();
  398. }
  399. else if (fProcess->isRunning())
  400. {
  401. carla_stderr("CarlaPluginBridgeThread::run() - already running, giving up...");
  402. }
  403. String name(kPlugin->getName());
  404. String filename(kPlugin->getFilename());
  405. if (name.isEmpty())
  406. name = "(none)";
  407. if (filename.isEmpty())
  408. filename = "\"\"";
  409. StringArray arguments;
  410. #ifndef CARLA_OS_WIN
  411. // start with "wine" if needed
  412. if (fBinary.endsWith(".exe"))
  413. arguments.add("wine");
  414. #endif
  415. // binary
  416. arguments.add(fBinary.buffer());
  417. #if 0
  418. /* stype */ arguments.add(fExtra1.buffer());
  419. /* filename */ arguments.add(filename);
  420. /* label */ arguments.add(fLabel.buffer());
  421. /* uniqueId */ arguments.add(String(static_cast<juce::int64>(fPlugin->getUniqueId())));
  422. carla_setenv("ENGINE_BRIDGE_SHM_IDS", fShmIds.buffer());
  423. carla_setenv("WINEDEBUG", "-all");
  424. #endif
  425. }
  426. private:
  427. CarlaEngine* const kEngine;
  428. CarlaPlugin* const kPlugin;
  429. CarlaString fBinary;
  430. CarlaString fLabel;
  431. CarlaString fShmIds;
  432. PluginType fPluginType;
  433. ScopedPointer<ChildProcess> fProcess;
  434. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridgeThread)
  435. };
  436. // -------------------------------------------------------------------------------------------------------------------
  437. class CarlaPluginBridge : public CarlaPlugin
  438. {
  439. public:
  440. CarlaPluginBridge(CarlaEngine* const engine, const uint id, const BinaryType btype, const PluginType ptype)
  441. : CarlaPlugin(engine, id),
  442. fBinaryType(btype),
  443. fPluginType(ptype),
  444. fInitiated(false),
  445. fInitError(false),
  446. fSaved(false),
  447. fTimedOut(false),
  448. fLastPongCounter(-1),
  449. fBridgeBinary(),
  450. fBridgeThread(engine, this),
  451. fShmAudioPool(),
  452. fShmRtClientControl(),
  453. fShmNonRtClientControl(),
  454. fShmNonRtServerControl(),
  455. fInfo(),
  456. fParams(nullptr),
  457. leakDetector_CarlaPluginBridge()
  458. {
  459. carla_debug("CarlaPluginBridge::CarlaPluginBridge(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  460. pData->hints |= PLUGIN_IS_BRIDGE;
  461. }
  462. ~CarlaPluginBridge() override
  463. {
  464. carla_debug("CarlaPluginBridge::~CarlaPluginBridge()");
  465. // close UI
  466. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  467. pData->transientTryCounter = 0;
  468. pData->singleMutex.lock();
  469. pData->masterMutex.lock();
  470. if (pData->client != nullptr && pData->client->isActive())
  471. pData->client->deactivate();
  472. if (pData->active)
  473. {
  474. deactivate();
  475. pData->active = false;
  476. }
  477. if (fBridgeThread.isThreadRunning())
  478. {
  479. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientQuit);
  480. fShmNonRtClientControl.commitWrite();
  481. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientQuit);
  482. fShmRtClientControl.commitWrite();
  483. if (! fTimedOut)
  484. fShmRtClientControl.waitForClient(3);
  485. }
  486. fBridgeThread.stopThread(3000);
  487. fShmNonRtServerControl.clear();
  488. fShmNonRtClientControl.clear();
  489. fShmRtClientControl.clear();
  490. fShmAudioPool.clear();
  491. clearBuffers();
  492. fInfo.chunk.clear();
  493. }
  494. // -------------------------------------------------------------------
  495. // Information (base)
  496. BinaryType getBinaryType() const noexcept
  497. {
  498. return fBinaryType;
  499. }
  500. PluginType getType() const noexcept override
  501. {
  502. return fPluginType;
  503. }
  504. PluginCategory getCategory() const noexcept override
  505. {
  506. return fInfo.category;
  507. }
  508. int64_t getUniqueId() const noexcept override
  509. {
  510. return fInfo.uniqueId;
  511. }
  512. // -------------------------------------------------------------------
  513. // Information (count)
  514. uint32_t getMidiInCount() const noexcept override
  515. {
  516. return fInfo.mIns;
  517. }
  518. uint32_t getMidiOutCount() const noexcept override
  519. {
  520. return fInfo.mOuts;
  521. }
  522. // -------------------------------------------------------------------
  523. // Information (current data)
  524. std::size_t getChunkData(void** const dataPtr) noexcept override
  525. {
  526. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  527. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  528. CARLA_SAFE_ASSERT_RETURN(fInfo.chunk.size() > 0, 0);
  529. *dataPtr = fInfo.chunk.data();
  530. return fInfo.chunk.size();
  531. }
  532. // -------------------------------------------------------------------
  533. // Information (per-plugin data)
  534. uint getOptionsAvailable() const noexcept override
  535. {
  536. return fInfo.optionsAvailable;
  537. }
  538. float getParameterValue(const uint32_t parameterId) const noexcept override
  539. {
  540. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  541. return fParams[parameterId].value;
  542. }
  543. void getLabel(char* const strBuf) const noexcept override
  544. {
  545. std::strncpy(strBuf, fInfo.label, STR_MAX);
  546. }
  547. void getMaker(char* const strBuf) const noexcept override
  548. {
  549. std::strncpy(strBuf, fInfo.maker, STR_MAX);
  550. }
  551. void getCopyright(char* const strBuf) const noexcept override
  552. {
  553. std::strncpy(strBuf, fInfo.copyright, STR_MAX);
  554. }
  555. void getRealName(char* const strBuf) const noexcept override
  556. {
  557. std::strncpy(strBuf, fInfo.name, STR_MAX);
  558. }
  559. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  560. {
  561. CARLA_ASSERT(parameterId < pData->param.count);
  562. std::strncpy(strBuf, fParams[parameterId].name.buffer(), STR_MAX);
  563. }
  564. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  565. {
  566. CARLA_ASSERT(parameterId < pData->param.count);
  567. std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX);
  568. }
  569. // -------------------------------------------------------------------
  570. // Set data (state)
  571. void prepareForSave() override
  572. {
  573. fSaved = false;
  574. {
  575. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  576. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPrepareForSave);
  577. fShmNonRtClientControl.commitWrite();
  578. }
  579. carla_stdout("CarlaPluginBridge::prepareForSave() - sent, now waiting...");
  580. for (int i=0; i < 200; ++i)
  581. {
  582. if (fSaved)
  583. break;
  584. carla_msleep(30);
  585. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  586. pData->engine->idle();
  587. }
  588. if (! fSaved)
  589. carla_stderr("CarlaPluginBridge::prepareForSave() - Timeout while requesting save state");
  590. else
  591. carla_stdout("CarlaPluginBridge::prepareForSave() - success!");
  592. }
  593. // -------------------------------------------------------------------
  594. // Set data (internal stuff)
  595. void setOption(const uint option, const bool yesNo, const bool sendCallback) override
  596. {
  597. {
  598. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  599. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOption);
  600. fShmNonRtClientControl.writeUInt(option);
  601. fShmNonRtClientControl.writeBool(yesNo);
  602. fShmNonRtClientControl.commitWrite();
  603. }
  604. CarlaPlugin::setOption(option, yesNo, sendCallback);
  605. }
  606. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  607. {
  608. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  609. {
  610. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  611. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCtrlChannel);
  612. fShmNonRtClientControl.writeShort(channel);
  613. fShmNonRtClientControl.commitWrite();
  614. }
  615. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  616. }
  617. // -------------------------------------------------------------------
  618. // Set data (plugin-specific stuff)
  619. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  620. {
  621. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  622. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  623. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  624. fParams[parameterId].value = fixedValue;
  625. {
  626. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  627. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterValue);
  628. fShmNonRtClientControl.writeUInt(parameterId);
  629. fShmNonRtClientControl.writeFloat(value);
  630. fShmNonRtClientControl.commitWrite();
  631. }
  632. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  633. }
  634. void setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  635. {
  636. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  637. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  638. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  639. {
  640. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  641. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiChannel);
  642. fShmNonRtClientControl.writeUInt(parameterId);
  643. fShmNonRtClientControl.writeByte(channel);
  644. fShmNonRtClientControl.commitWrite();
  645. }
  646. CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback);
  647. }
  648. void setParameterMidiCC(const uint32_t parameterId, const int16_t cc, const bool sendOsc, const bool sendCallback) noexcept override
  649. {
  650. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  651. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  652. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL,);
  653. {
  654. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  655. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiCC);
  656. fShmNonRtClientControl.writeUInt(parameterId);
  657. fShmNonRtClientControl.writeShort(cc);
  658. fShmNonRtClientControl.commitWrite();
  659. }
  660. CarlaPlugin::setParameterMidiCC(parameterId, cc, sendOsc, sendCallback);
  661. }
  662. void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  663. {
  664. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  665. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  666. {
  667. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  668. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetProgram);
  669. fShmNonRtClientControl.writeInt(index);
  670. fShmNonRtClientControl.commitWrite();
  671. }
  672. CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback);
  673. }
  674. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  675. {
  676. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  677. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  678. {
  679. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  680. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram);
  681. fShmNonRtClientControl.writeInt(index);
  682. fShmNonRtClientControl.commitWrite();
  683. }
  684. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  685. }
  686. #if 0
  687. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  688. {
  689. CARLA_ASSERT(type);
  690. CARLA_ASSERT(key);
  691. CARLA_ASSERT(value);
  692. if (sendGui)
  693. {
  694. // TODO - if type is chunk|binary, store it in a file and send path instead
  695. QString cData;
  696. cData = type;
  697. cData += "·";
  698. cData += key;
  699. cData += "·";
  700. cData += value;
  701. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  702. }
  703. CarlaPlugin::setCustomData(type, key, value, sendGui);
  704. }
  705. #endif
  706. void setChunkData(const void* const data, const std::size_t dataSize) override
  707. {
  708. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  709. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  710. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  711. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  712. CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0,);
  713. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  714. filePath += CARLA_OS_SEP_STR;
  715. filePath += ".CarlaChunk_";
  716. filePath += fShmAudioPool.filename.buffer() + 18;
  717. if (File(filePath).replaceWithText(dataBase64.buffer()))
  718. {
  719. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  720. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  721. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile);
  722. fShmNonRtClientControl.writeUInt(ulength);
  723. fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength);
  724. fShmNonRtClientControl.commitWrite();
  725. }
  726. }
  727. // -------------------------------------------------------------------
  728. // Set ui stuff
  729. void showCustomUI(const bool yesNo) override
  730. {
  731. {
  732. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  733. fShmNonRtClientControl.writeOpcode(yesNo ? kPluginBridgeNonRtClientShowUI : kPluginBridgeNonRtClientHideUI);
  734. fShmNonRtClientControl.commitWrite();
  735. }
  736. if (yesNo)
  737. {
  738. pData->tryTransient();
  739. }
  740. else
  741. {
  742. pData->transientTryCounter = 0;
  743. }
  744. }
  745. void idle() override
  746. {
  747. if (fBridgeThread.isThreadRunning())
  748. {
  749. if (fTimedOut && pData->active)
  750. setActive(false, true, true);
  751. {
  752. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  753. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPing);
  754. fShmNonRtClientControl.commitWrite();
  755. }
  756. try {
  757. handleNonRtData();
  758. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  759. }
  760. else
  761. carla_stderr2("TESTING: Bridge has closed!");
  762. CarlaPlugin::idle();
  763. }
  764. // -------------------------------------------------------------------
  765. // Plugin state
  766. void reload() override
  767. {
  768. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  769. carla_debug("CarlaPluginBridge::reload() - start");
  770. const EngineProcessMode processMode(pData->engine->getProccessMode());
  771. // Safely disable plugin for reload
  772. const ScopedDisabler sd(this);
  773. bool needsCtrlIn, needsCtrlOut;
  774. needsCtrlIn = needsCtrlOut = false;
  775. if (fInfo.aIns > 0)
  776. {
  777. pData->audioIn.createNew(fInfo.aIns);
  778. }
  779. if (fInfo.aOuts > 0)
  780. {
  781. pData->audioOut.createNew(fInfo.aOuts);
  782. needsCtrlIn = true;
  783. }
  784. if (fInfo.cvIns > 0)
  785. {
  786. pData->cvIn.createNew(fInfo.cvIns);
  787. }
  788. if (fInfo.cvOuts > 0)
  789. {
  790. pData->cvOut.createNew(fInfo.cvOuts);
  791. }
  792. if (fInfo.mIns > 0)
  793. needsCtrlIn = true;
  794. if (fInfo.mOuts > 0)
  795. needsCtrlOut = true;
  796. const uint portNameSize(pData->engine->getMaxPortNameSize());
  797. CarlaString portName;
  798. // Audio Ins
  799. for (uint32_t j=0; j < fInfo.aIns; ++j)
  800. {
  801. portName.clear();
  802. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  803. {
  804. portName = pData->name;
  805. portName += ":";
  806. }
  807. if (fInfo.aIns > 1)
  808. {
  809. portName += "input_";
  810. portName += CarlaString(j+1);
  811. }
  812. else
  813. portName += "input";
  814. portName.truncate(portNameSize);
  815. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  816. pData->audioIn.ports[j].rindex = j;
  817. }
  818. // Audio Outs
  819. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  820. {
  821. portName.clear();
  822. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  823. {
  824. portName = pData->name;
  825. portName += ":";
  826. }
  827. if (fInfo.aOuts > 1)
  828. {
  829. portName += "output_";
  830. portName += CarlaString(j+1);
  831. }
  832. else
  833. portName += "output";
  834. portName.truncate(portNameSize);
  835. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  836. pData->audioOut.ports[j].rindex = j;
  837. }
  838. // TODO - CV
  839. if (needsCtrlIn)
  840. {
  841. portName.clear();
  842. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  843. {
  844. portName = pData->name;
  845. portName += ":";
  846. }
  847. portName += "event-in";
  848. portName.truncate(portNameSize);
  849. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  850. }
  851. if (needsCtrlOut)
  852. {
  853. portName.clear();
  854. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  855. {
  856. portName = pData->name;
  857. portName += ":";
  858. }
  859. portName += "event-out";
  860. portName.truncate(portNameSize);
  861. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  862. }
  863. // extra plugin hints
  864. pData->extraHints = 0x0;
  865. if (fInfo.mIns > 0)
  866. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  867. if (fInfo.mOuts > 0)
  868. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  869. if (fInfo.aIns <= 2 && fInfo.aOuts <= 2 && (fInfo.aIns == fInfo.aOuts || fInfo.aIns == 0 || fInfo.aOuts == 0))
  870. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  871. bufferSizeChanged(pData->engine->getBufferSize());
  872. reloadPrograms(true);
  873. carla_debug("CarlaPluginBridge::reload() - end");
  874. }
  875. // -------------------------------------------------------------------
  876. // Plugin processing
  877. void activate() noexcept override
  878. {
  879. {
  880. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  881. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate);
  882. fShmNonRtClientControl.commitWrite();
  883. }
  884. bool timedOut = true;
  885. try {
  886. timedOut = waitForClient(1);
  887. } CARLA_SAFE_EXCEPTION("activate - waitForClient");
  888. if (! timedOut)
  889. fTimedOut = false;
  890. }
  891. void deactivate() noexcept override
  892. {
  893. {
  894. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  895. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate);
  896. fShmNonRtClientControl.commitWrite();
  897. }
  898. bool timedOut = true;
  899. try {
  900. timedOut = waitForClient(1);
  901. } CARLA_SAFE_EXCEPTION("deactivate - waitForClient");
  902. if (! timedOut)
  903. fTimedOut = false;
  904. }
  905. void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
  906. {
  907. // --------------------------------------------------------------------------------------------------------
  908. // Check if active
  909. if (fTimedOut || ! pData->active)
  910. {
  911. // disable any output sound
  912. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  913. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  914. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  915. FloatVectorOperations::clear(cvOut[i], static_cast<int>(frames));
  916. return;
  917. }
  918. // --------------------------------------------------------------------------------------------------------
  919. // Check if needs reset
  920. if (pData->needsReset)
  921. {
  922. // TODO
  923. pData->needsReset = false;
  924. }
  925. // --------------------------------------------------------------------------------------------------------
  926. // Event Input
  927. if (pData->event.portIn != nullptr)
  928. {
  929. // ----------------------------------------------------------------------------------------------------
  930. // MIDI Input (External)
  931. if (pData->extNotes.mutex.tryLock())
  932. {
  933. for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin(); it.valid(); it.next())
  934. {
  935. const ExternalMidiNote& note(it.getValue());
  936. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  937. uint8_t data1, data2, data3;
  938. data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  939. data2 = note.note;
  940. data3 = note.velo;
  941. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  942. fShmRtClientControl.writeUInt(0); // time
  943. fShmRtClientControl.writeByte(0); // port
  944. fShmRtClientControl.writeByte(3); // size
  945. fShmRtClientControl.writeByte(data1);
  946. fShmRtClientControl.writeByte(data2);
  947. fShmRtClientControl.writeByte(data3);
  948. fShmRtClientControl.commitWrite();
  949. }
  950. pData->extNotes.data.clear();
  951. pData->extNotes.mutex.unlock();
  952. } // End of MIDI Input (External)
  953. // ----------------------------------------------------------------------------------------------------
  954. // Event Input (System)
  955. bool allNotesOffSent = false;
  956. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  957. {
  958. const EngineEvent& event(pData->event.portIn->getEvent(i));
  959. // Control change
  960. switch (event.type)
  961. {
  962. case kEngineEventTypeNull:
  963. break;
  964. case kEngineEventTypeControl: {
  965. const EngineControlEvent& ctrlEvent = event.ctrl;
  966. switch (ctrlEvent.type)
  967. {
  968. case kEngineControlEventTypeNull:
  969. break;
  970. case kEngineControlEventTypeParameter:
  971. // Control backend stuff
  972. if (event.channel == pData->ctrlChannel)
  973. {
  974. float value;
  975. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  976. {
  977. value = ctrlEvent.value;
  978. setDryWet(value, false, false);
  979. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  980. break;
  981. }
  982. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  983. {
  984. value = ctrlEvent.value*127.0f/100.0f;
  985. setVolume(value, false, false);
  986. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  987. break;
  988. }
  989. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  990. {
  991. float left, right;
  992. value = ctrlEvent.value/0.5f - 1.0f;
  993. if (value < 0.0f)
  994. {
  995. left = -1.0f;
  996. right = (value*2.0f)+1.0f;
  997. }
  998. else if (value > 0.0f)
  999. {
  1000. left = (value*2.0f)-1.0f;
  1001. right = 1.0f;
  1002. }
  1003. else
  1004. {
  1005. left = -1.0f;
  1006. right = 1.0f;
  1007. }
  1008. setBalanceLeft(left, false, false);
  1009. setBalanceRight(right, false, false);
  1010. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  1011. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  1012. break;
  1013. }
  1014. }
  1015. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventParameter);
  1016. fShmRtClientControl.writeUInt(event.time);
  1017. fShmRtClientControl.writeByte(event.channel);
  1018. fShmRtClientControl.writeUShort(event.ctrl.param);
  1019. fShmRtClientControl.writeFloat(event.ctrl.value);
  1020. fShmRtClientControl.commitWrite();
  1021. break;
  1022. case kEngineControlEventTypeMidiBank:
  1023. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  1024. {
  1025. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiBank);
  1026. fShmRtClientControl.writeUInt(event.time);
  1027. fShmRtClientControl.writeByte(event.channel);
  1028. fShmRtClientControl.writeUShort(event.ctrl.param);
  1029. fShmRtClientControl.commitWrite();
  1030. }
  1031. break;
  1032. case kEngineControlEventTypeMidiProgram:
  1033. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  1034. {
  1035. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiProgram);
  1036. fShmRtClientControl.writeUInt(event.time);
  1037. fShmRtClientControl.writeByte(event.channel);
  1038. fShmRtClientControl.writeUShort(event.ctrl.param);
  1039. fShmRtClientControl.commitWrite();
  1040. }
  1041. break;
  1042. case kEngineControlEventTypeAllSoundOff:
  1043. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1044. {
  1045. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllSoundOff);
  1046. fShmRtClientControl.writeUInt(event.time);
  1047. fShmRtClientControl.writeByte(event.channel);
  1048. fShmRtClientControl.commitWrite();
  1049. }
  1050. break;
  1051. case kEngineControlEventTypeAllNotesOff:
  1052. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1053. {
  1054. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  1055. {
  1056. allNotesOffSent = true;
  1057. sendMidiAllNotesOffToCallback();
  1058. }
  1059. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllNotesOff);
  1060. fShmRtClientControl.writeUInt(event.time);
  1061. fShmRtClientControl.writeByte(event.channel);
  1062. fShmRtClientControl.commitWrite();
  1063. }
  1064. break;
  1065. } // switch (ctrlEvent.type)
  1066. break;
  1067. } // case kEngineEventTypeControl
  1068. case kEngineEventTypeMidi: {
  1069. const EngineMidiEvent& midiEvent(event.midi);
  1070. if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE)
  1071. continue;
  1072. const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
  1073. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
  1074. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  1075. continue;
  1076. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  1077. continue;
  1078. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  1079. continue;
  1080. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  1081. continue;
  1082. // Fix bad note-off
  1083. if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
  1084. status = MIDI_STATUS_NOTE_OFF;
  1085. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  1086. fShmRtClientControl.writeUInt(event.time);
  1087. fShmRtClientControl.writeByte(midiEvent.port);
  1088. fShmRtClientControl.writeByte(midiEvent.size);
  1089. fShmRtClientControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT)));
  1090. for (uint8_t j=1; j < midiEvent.size; ++j)
  1091. fShmRtClientControl.writeByte(midiData[j]);
  1092. fShmRtClientControl.commitWrite();
  1093. if (status == MIDI_STATUS_NOTE_ON)
  1094. pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]);
  1095. else if (status == MIDI_STATUS_NOTE_OFF)
  1096. pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f);
  1097. } break;
  1098. }
  1099. }
  1100. pData->postRtEvents.trySplice();
  1101. } // End of Event Input
  1102. processSingle(audioIn, audioOut, cvIn, cvOut, frames);
  1103. }
  1104. bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames)
  1105. {
  1106. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  1107. if (pData->audioIn.count > 0)
  1108. {
  1109. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  1110. }
  1111. if (pData->audioOut.count > 0)
  1112. {
  1113. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  1114. }
  1115. if (pData->cvIn.count > 0)
  1116. {
  1117. CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
  1118. }
  1119. if (pData->cvOut.count > 0)
  1120. {
  1121. CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
  1122. }
  1123. // --------------------------------------------------------------------------------------------------------
  1124. // Try lock, silence otherwise
  1125. if (pData->engine->isOffline())
  1126. {
  1127. pData->singleMutex.lock();
  1128. }
  1129. else if (! pData->singleMutex.tryLock())
  1130. {
  1131. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1132. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  1133. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1134. FloatVectorOperations::clear(cvOut[i], static_cast<int>(frames));
  1135. return false;
  1136. }
  1137. // --------------------------------------------------------------------------------------------------------
  1138. // Reset audio buffers
  1139. for (uint32_t i=0; i < fInfo.aIns; ++i)
  1140. FloatVectorOperations::copy(fShmAudioPool.data + (i * frames), audioIn[i], static_cast<int>(frames));
  1141. // --------------------------------------------------------------------------------------------------------
  1142. // TimeInfo
  1143. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  1144. BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  1145. bridgeTimeInfo.playing = timeInfo.playing;
  1146. bridgeTimeInfo.frame = timeInfo.frame;
  1147. bridgeTimeInfo.usecs = timeInfo.usecs;
  1148. bridgeTimeInfo.valid = timeInfo.valid;
  1149. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  1150. {
  1151. bridgeTimeInfo.bar = timeInfo.bbt.bar;
  1152. bridgeTimeInfo.beat = timeInfo.bbt.beat;
  1153. bridgeTimeInfo.tick = timeInfo.bbt.tick;
  1154. bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar;
  1155. bridgeTimeInfo.beatType = timeInfo.bbt.beatType;
  1156. bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  1157. bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  1158. bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick;
  1159. }
  1160. // --------------------------------------------------------------------------------------------------------
  1161. // Run plugin
  1162. {
  1163. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientProcess);
  1164. fShmRtClientControl.commitWrite();
  1165. }
  1166. if (! waitForClient(2))
  1167. {
  1168. pData->singleMutex.unlock();
  1169. return true;
  1170. }
  1171. for (uint32_t i=0; i < fInfo.aOuts; ++i)
  1172. FloatVectorOperations::copy(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), static_cast<int>(frames));
  1173. // --------------------------------------------------------------------------------------------------------
  1174. // Post-processing (dry/wet, volume and balance)
  1175. {
  1176. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && ! carla_compareFloats(pData->postProc.volume, 1.0f);
  1177. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && ! carla_compareFloats(pData->postProc.dryWet, 1.0f);
  1178. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_compareFloats(pData->postProc.balanceLeft, -1.0f) && carla_compareFloats(pData->postProc.balanceRight, 1.0f));
  1179. bool isPair;
  1180. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1181. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1182. {
  1183. // Dry/Wet
  1184. if (doDryWet)
  1185. {
  1186. for (uint32_t k=0; k < frames; ++k)
  1187. {
  1188. bufValue = audioIn[(pData->audioIn.count == 1) ? 0 : i][k];
  1189. audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1190. }
  1191. }
  1192. // Balance
  1193. if (doBalance)
  1194. {
  1195. isPair = (i % 2 == 0);
  1196. if (isPair)
  1197. {
  1198. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1199. FloatVectorOperations::copy(oldBufLeft, audioOut[i], static_cast<int>(frames));
  1200. }
  1201. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1202. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1203. for (uint32_t k=0; k < frames; ++k)
  1204. {
  1205. if (isPair)
  1206. {
  1207. // left
  1208. audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1209. audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR);
  1210. }
  1211. else
  1212. {
  1213. // right
  1214. audioOut[i][k] = audioOut[i][k] * balRangeR;
  1215. audioOut[i][k] += oldBufLeft[k] * balRangeL;
  1216. }
  1217. }
  1218. }
  1219. // Volume (and buffer copy)
  1220. if (doVolume)
  1221. {
  1222. for (uint32_t k=0; k < frames; ++k)
  1223. audioOut[i][k] *= pData->postProc.volume;
  1224. }
  1225. }
  1226. } // End of Post-processing
  1227. // --------------------------------------------------------------------------------------------------------
  1228. pData->singleMutex.unlock();
  1229. return true;
  1230. }
  1231. void bufferSizeChanged(const uint32_t newBufferSize) override
  1232. {
  1233. resizeAudioPool(newBufferSize);
  1234. {
  1235. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1236. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetBufferSize);
  1237. fShmNonRtClientControl.writeUInt(newBufferSize);
  1238. fShmNonRtClientControl.commitWrite();
  1239. }
  1240. fShmRtClientControl.waitForClient(1);
  1241. }
  1242. void sampleRateChanged(const double newSampleRate) override
  1243. {
  1244. {
  1245. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1246. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetSampleRate);
  1247. fShmNonRtClientControl.writeDouble(newSampleRate);
  1248. fShmNonRtClientControl.commitWrite();
  1249. }
  1250. fShmRtClientControl.waitForClient(1);
  1251. }
  1252. void offlineModeChanged(const bool isOffline) override
  1253. {
  1254. {
  1255. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1256. fShmNonRtClientControl.writeOpcode(isOffline ? kPluginBridgeNonRtClientSetOffline : kPluginBridgeNonRtClientSetOnline);
  1257. fShmNonRtClientControl.commitWrite();
  1258. }
  1259. fShmRtClientControl.waitForClient(1);
  1260. }
  1261. // -------------------------------------------------------------------
  1262. // Plugin buffers
  1263. void clearBuffers() noexcept override
  1264. {
  1265. if (fParams != nullptr)
  1266. {
  1267. delete[] fParams;
  1268. fParams = nullptr;
  1269. }
  1270. CarlaPlugin::clearBuffers();
  1271. }
  1272. // -------------------------------------------------------------------
  1273. // Post-poned UI Stuff
  1274. void uiParameterChange(const uint32_t index, const float value) noexcept override
  1275. {
  1276. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  1277. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1278. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiParameterChange);
  1279. fShmNonRtClientControl.writeUInt(index);
  1280. fShmNonRtClientControl.writeFloat(value);
  1281. fShmNonRtClientControl.commitWrite();
  1282. }
  1283. void uiProgramChange(const uint32_t index) noexcept override
  1284. {
  1285. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1286. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1287. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiProgramChange);
  1288. fShmNonRtClientControl.writeUInt(index);
  1289. fShmNonRtClientControl.commitWrite();
  1290. }
  1291. void uiMidiProgramChange(const uint32_t index) noexcept override
  1292. {
  1293. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1294. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1295. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiMidiProgramChange);
  1296. fShmNonRtClientControl.writeUInt(index);
  1297. fShmNonRtClientControl.commitWrite();
  1298. }
  1299. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  1300. {
  1301. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1302. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1303. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1304. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1305. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOn);
  1306. fShmNonRtClientControl.writeByte(channel);
  1307. fShmNonRtClientControl.writeByte(note);
  1308. fShmNonRtClientControl.writeByte(velo);
  1309. fShmNonRtClientControl.commitWrite();
  1310. }
  1311. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  1312. {
  1313. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1314. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1315. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1316. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOff);
  1317. fShmNonRtClientControl.writeByte(channel);
  1318. fShmNonRtClientControl.writeByte(note);
  1319. fShmNonRtClientControl.commitWrite();
  1320. }
  1321. // -------------------------------------------------------------------
  1322. void handleNonRtData()
  1323. {
  1324. for (; fShmNonRtServerControl.isDataAvailableForReading();)
  1325. {
  1326. const PluginBridgeNonRtServerOpcode opcode(fShmNonRtServerControl.readOpcode());
  1327. #ifdef DEBUG
  1328. if (opcode != kPluginBridgeNonRtServerPong) {
  1329. carla_debug("CarlaPluginBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode));
  1330. }
  1331. #endif
  1332. switch (opcode)
  1333. {
  1334. case kPluginBridgeNonRtServerNull:
  1335. break;
  1336. case kPluginBridgeNonRtServerPong:
  1337. if (fLastPongCounter > 0)
  1338. fLastPongCounter = 0;
  1339. break;
  1340. case kPluginBridgeNonRtServerPluginInfo1: {
  1341. // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  1342. const uint32_t category = fShmNonRtServerControl.readUInt();
  1343. const uint32_t hints = fShmNonRtServerControl.readUInt();
  1344. const uint32_t optionAv = fShmNonRtServerControl.readUInt();
  1345. const uint32_t optionEn = fShmNonRtServerControl.readUInt();
  1346. const int64_t uniqueId = fShmNonRtServerControl.readLong();
  1347. pData->hints = hints | PLUGIN_IS_BRIDGE;
  1348. pData->options = optionEn;
  1349. fInfo.category = static_cast<PluginCategory>(category);
  1350. fInfo.uniqueId = uniqueId;
  1351. fInfo.optionsAvailable = optionAv;
  1352. } break;
  1353. case kPluginBridgeNonRtServerPluginInfo2: {
  1354. // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  1355. // realName
  1356. const uint32_t realNameSize(fShmNonRtServerControl.readUInt());
  1357. char realName[realNameSize+1];
  1358. carla_zeroChar(realName, realNameSize+1);
  1359. fShmNonRtServerControl.readCustomData(realName, realNameSize);
  1360. // label
  1361. const uint32_t labelSize(fShmNonRtServerControl.readUInt());
  1362. char label[labelSize+1];
  1363. carla_zeroChar(label, labelSize+1);
  1364. fShmNonRtServerControl.readCustomData(label, labelSize);
  1365. // maker
  1366. const uint32_t makerSize(fShmNonRtServerControl.readUInt());
  1367. char maker[makerSize+1];
  1368. carla_zeroChar(maker, makerSize+1);
  1369. fShmNonRtServerControl.readCustomData(maker, makerSize);
  1370. // copyright
  1371. const uint32_t copyrightSize(fShmNonRtServerControl.readUInt());
  1372. char copyright[copyrightSize+1];
  1373. carla_zeroChar(copyright, copyrightSize+1);
  1374. fShmNonRtServerControl.readCustomData(copyright, copyrightSize);
  1375. fInfo.name = realName;
  1376. fInfo.label = label;
  1377. fInfo.maker = maker;
  1378. fInfo.copyright = copyright;
  1379. if (pData->name == nullptr)
  1380. pData->name = pData->engine->getUniquePluginName(realName);
  1381. } break;
  1382. case kPluginBridgeNonRtServerAudioCount: {
  1383. // uint/ins, uint/outs
  1384. fInfo.aIns = fShmNonRtServerControl.readUInt();
  1385. fInfo.aOuts = fShmNonRtServerControl.readUInt();
  1386. } break;
  1387. case kPluginBridgeNonRtServerMidiCount: {
  1388. // uint/ins, uint/outs
  1389. fInfo.mIns = fShmNonRtServerControl.readUInt();
  1390. fInfo.mOuts = fShmNonRtServerControl.readUInt();
  1391. } break;
  1392. case kPluginBridgeNonRtServerParameterCount: {
  1393. // uint/ins, uint/outs
  1394. const uint32_t ins = fShmNonRtServerControl.readUInt();
  1395. const uint32_t outs = fShmNonRtServerControl.readUInt();
  1396. // delete old data
  1397. pData->param.clear();
  1398. if (fParams != nullptr)
  1399. {
  1400. delete[] fParams;
  1401. fParams = nullptr;
  1402. }
  1403. if (uint32_t count = ins+outs)
  1404. {
  1405. const uint32_t maxParams(pData->engine->getOptions().maxParameters);
  1406. if (count > maxParams)
  1407. {
  1408. // this is expected right now, to be handled better later
  1409. //carla_safe_assert_int2("count <= pData->engine->getOptions().maxParameters", __FILE__, __LINE__, count, maxParams);
  1410. count = maxParams;
  1411. }
  1412. pData->param.createNew(count, false);
  1413. fParams = new BridgeParamInfo[count];
  1414. }
  1415. } break;
  1416. case kPluginBridgeNonRtServerProgramCount: {
  1417. // uint/count
  1418. pData->prog.clear();
  1419. if (const uint32_t count = fShmNonRtServerControl.readUInt())
  1420. pData->prog.createNew(static_cast<uint32_t>(count));
  1421. } break;
  1422. case kPluginBridgeNonRtServerMidiProgramCount: {
  1423. // uint/count
  1424. pData->midiprog.clear();
  1425. if (const uint32_t count = fShmNonRtServerControl.readUInt())
  1426. pData->midiprog.createNew(static_cast<uint32_t>(count));
  1427. } break;
  1428. case kPluginBridgeNonRtServerParameterData1: {
  1429. // uint/index, int/rindex, uint/type, uint/hints, int/cc
  1430. const uint32_t index = fShmNonRtServerControl.readUInt();
  1431. const int32_t rindex = fShmNonRtServerControl.readInt();
  1432. const uint32_t type = fShmNonRtServerControl.readUInt();
  1433. const uint32_t hints = fShmNonRtServerControl.readUInt();
  1434. const int16_t midiCC = fShmNonRtServerControl.readShort();
  1435. CARLA_SAFE_ASSERT_BREAK(midiCC >= -1 && midiCC < MAX_MIDI_CONTROL);
  1436. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1437. if (index < pData->param.count)
  1438. {
  1439. pData->param.data[index].type = static_cast<ParameterType>(type);
  1440. pData->param.data[index].index = static_cast<int32_t>(index);
  1441. pData->param.data[index].rindex = rindex;
  1442. pData->param.data[index].hints = hints;
  1443. pData->param.data[index].midiCC = midiCC;
  1444. }
  1445. } break;
  1446. case kPluginBridgeNonRtServerParameterData2: {
  1447. // uint/index, uint/size, str[] (name), uint/size, str[] (unit)
  1448. const uint32_t index = fShmNonRtServerControl.readUInt();
  1449. // name
  1450. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1451. char name[nameSize+1];
  1452. carla_zeroChar(name, nameSize+1);
  1453. fShmNonRtServerControl.readCustomData(name, nameSize);
  1454. // unit
  1455. const uint32_t unitSize(fShmNonRtServerControl.readUInt());
  1456. char unit[unitSize+1];
  1457. carla_zeroChar(unit, unitSize+1);
  1458. fShmNonRtServerControl.readCustomData(unit, unitSize);
  1459. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1460. if (index < pData->param.count)
  1461. {
  1462. fParams[index].name = name;
  1463. fParams[index].unit = unit;
  1464. }
  1465. } break;
  1466. case kPluginBridgeNonRtServerParameterRanges1: {
  1467. // uint/index, float/def, float/min, float/max
  1468. const uint32_t index = fShmNonRtServerControl.readUInt();
  1469. const float def = fShmNonRtServerControl.readFloat();
  1470. const float min = fShmNonRtServerControl.readFloat();
  1471. const float max = fShmNonRtServerControl.readFloat();
  1472. CARLA_SAFE_ASSERT_BREAK(min < max);
  1473. CARLA_SAFE_ASSERT_BREAK(def >= min);
  1474. CARLA_SAFE_ASSERT_BREAK(def <= max);
  1475. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1476. if (index < pData->param.count)
  1477. {
  1478. pData->param.ranges[index].def = def;
  1479. pData->param.ranges[index].min = min;
  1480. pData->param.ranges[index].max = max;
  1481. }
  1482. } break;
  1483. case kPluginBridgeNonRtServerParameterRanges2: {
  1484. // uint/index float/step, float/stepSmall, float/stepLarge
  1485. const uint32_t index = fShmNonRtServerControl.readUInt();
  1486. const float step = fShmNonRtServerControl.readFloat();
  1487. const float stepSmall = fShmNonRtServerControl.readFloat();
  1488. const float stepLarge = fShmNonRtServerControl.readFloat();
  1489. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1490. if (index < pData->param.count)
  1491. {
  1492. pData->param.ranges[index].step = step;
  1493. pData->param.ranges[index].stepSmall = stepSmall;
  1494. pData->param.ranges[index].stepLarge = stepLarge;
  1495. }
  1496. } break;
  1497. case kPluginBridgeNonRtServerParameterValue: {
  1498. // uint/index float/value
  1499. const uint32_t index = fShmNonRtServerControl.readUInt();
  1500. const float value = fShmNonRtServerControl.readFloat();
  1501. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1502. if (index < pData->param.count)
  1503. {
  1504. const float fixedValue(pData->param.getFixedValue(index, value));
  1505. fParams[index].value = fixedValue;
  1506. CarlaPlugin::setParameterValue(index, fixedValue, false, true, true);
  1507. }
  1508. } break;
  1509. case kPluginBridgeNonRtServerDefaultValue: {
  1510. // uint/index float/value
  1511. const uint32_t index = fShmNonRtServerControl.readUInt();
  1512. const float value = fShmNonRtServerControl.readFloat();
  1513. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1514. if (index < pData->param.count)
  1515. pData->param.ranges[index].def = value;
  1516. } break;
  1517. case kPluginBridgeNonRtServerCurrentProgram: {
  1518. // int/index
  1519. const int32_t index = fShmNonRtServerControl.readInt();
  1520. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1521. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1522. CarlaPlugin::setProgram(index, false, true, true);
  1523. } break;
  1524. case kPluginBridgeNonRtServerCurrentMidiProgram: {
  1525. // int/index
  1526. const int32_t index = fShmNonRtServerControl.readInt();
  1527. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1528. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1529. CarlaPlugin::setMidiProgram(index, false, true, true);
  1530. } break;
  1531. case kPluginBridgeNonRtServerProgramName: {
  1532. // uint/index, uint/size, str[] (name)
  1533. const uint32_t index = fShmNonRtServerControl.readUInt();
  1534. // name
  1535. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1536. char name[nameSize+1];
  1537. carla_zeroChar(name, nameSize+1);
  1538. fShmNonRtServerControl.readCustomData(name, nameSize);
  1539. CARLA_SAFE_ASSERT_INT2(index < pData->prog.count, index, pData->prog.count);
  1540. if (index < pData->prog.count)
  1541. {
  1542. if (pData->prog.names[index] != nullptr)
  1543. delete[] pData->prog.names[index];
  1544. pData->prog.names[index] = carla_strdup(name);
  1545. }
  1546. } break;
  1547. case kPluginBridgeNonRtServerMidiProgramData: {
  1548. // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  1549. const uint32_t index = fShmNonRtServerControl.readUInt();
  1550. const uint32_t bank = fShmNonRtServerControl.readUInt();
  1551. const uint32_t program = fShmNonRtServerControl.readUInt();
  1552. // name
  1553. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1554. char name[nameSize+1];
  1555. carla_zeroChar(name, nameSize+1);
  1556. fShmNonRtServerControl.readCustomData(name, nameSize);
  1557. CARLA_SAFE_ASSERT_INT2(index < pData->midiprog.count, index, pData->midiprog.count);
  1558. if (index < pData->midiprog.count)
  1559. {
  1560. if (pData->midiprog.data[index].name != nullptr)
  1561. delete[] pData->midiprog.data[index].name;
  1562. pData->midiprog.data[index].bank = bank;
  1563. pData->midiprog.data[index].program = program;
  1564. pData->midiprog.data[index].name = carla_strdup(name);
  1565. }
  1566. } break;
  1567. case kPluginBridgeNonRtServerSetCustomData: {
  1568. // uint/size, str[], uint/size, str[], uint/size, str[] (compressed)
  1569. // type
  1570. const uint32_t typeSize(fShmNonRtServerControl.readUInt());
  1571. char type[typeSize+1];
  1572. carla_zeroChar(type, typeSize+1);
  1573. fShmNonRtServerControl.readCustomData(type, typeSize);
  1574. // key
  1575. const uint32_t keySize(fShmNonRtServerControl.readUInt());
  1576. char key[keySize+1];
  1577. carla_zeroChar(key, keySize+1);
  1578. fShmNonRtServerControl.readCustomData(key, keySize);
  1579. // value
  1580. const uint32_t valueSize(fShmNonRtServerControl.readUInt());
  1581. char value[valueSize+1];
  1582. carla_zeroChar(value, valueSize+1);
  1583. fShmNonRtServerControl.readCustomData(value, valueSize);
  1584. CarlaPlugin::setCustomData(type, key, value, false);
  1585. } break;
  1586. case kPluginBridgeNonRtServerSetChunkDataFile: {
  1587. // uint/size, str[] (filename)
  1588. // chunkFilePath
  1589. const uint32_t chunkFilePathSize(fShmNonRtServerControl.readUInt());
  1590. char chunkFilePath[chunkFilePathSize+1];
  1591. carla_zeroChar(chunkFilePath, chunkFilePathSize+1);
  1592. fShmNonRtServerControl.readCustomData(chunkFilePath, chunkFilePathSize);
  1593. String realChunkFilePath(chunkFilePath);
  1594. carla_stdout("chunk save path BEFORE => %s", realChunkFilePath.toRawUTF8());
  1595. #ifndef CARLA_OS_WIN
  1596. // Using Wine, fix temp dir
  1597. if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
  1598. {
  1599. // Get WINEPREFIX
  1600. String wineDir;
  1601. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  1602. wineDir = String(WINEPREFIX);
  1603. else
  1604. wineDir = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine";
  1605. const StringArray driveLetterSplit(StringArray::fromTokens(realChunkFilePath, ":/", ""));
  1606. realChunkFilePath = wineDir;
  1607. realChunkFilePath += "/drive_";
  1608. realChunkFilePath += driveLetterSplit[0].toLowerCase();
  1609. realChunkFilePath += "/";
  1610. realChunkFilePath += driveLetterSplit[1];
  1611. realChunkFilePath = realChunkFilePath.replace("\\", "/");
  1612. carla_stdout("chunk save path AFTER => %s", realChunkFilePath.toRawUTF8());
  1613. }
  1614. #endif
  1615. File chunkFile(realChunkFilePath);
  1616. if (chunkFile.existsAsFile())
  1617. {
  1618. fInfo.chunk = carla_getChunkFromBase64String(chunkFile.loadFileAsString().toRawUTF8());
  1619. chunkFile.deleteFile();
  1620. carla_stderr("chunk data final");
  1621. }
  1622. } break;
  1623. case kPluginBridgeNonRtServerSetLatency: {
  1624. // uint
  1625. } break;
  1626. case kPluginBridgeNonRtServerReady:
  1627. fInitiated = true;
  1628. break;
  1629. case kPluginBridgeNonRtServerSaved:
  1630. fSaved = true;
  1631. break;
  1632. case kPluginBridgeNonRtServerUiClosed:
  1633. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  1634. break;
  1635. case kPluginBridgeNonRtServerError: {
  1636. // error
  1637. const uint32_t errorSize(fShmNonRtServerControl.readUInt());
  1638. char error[errorSize+1];
  1639. carla_zeroChar(error, errorSize+1);
  1640. fShmNonRtServerControl.readCustomData(error, errorSize);
  1641. pData->engine->setLastError(error);
  1642. fInitError = true;
  1643. fInitiated = true;
  1644. } break;
  1645. }
  1646. }
  1647. }
  1648. // -------------------------------------------------------------------
  1649. const void* getExtraStuff() const noexcept override
  1650. {
  1651. return fBridgeBinary.isNotEmpty() ? fBridgeBinary.buffer() : nullptr;
  1652. }
  1653. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  1654. {
  1655. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  1656. // ---------------------------------------------------------------
  1657. // first checks
  1658. if (pData->client != nullptr)
  1659. {
  1660. pData->engine->setLastError("Plugin client is already registered");
  1661. return false;
  1662. }
  1663. // ---------------------------------------------------------------
  1664. // set info
  1665. if (name != nullptr && name[0] != '\0')
  1666. pData->name = pData->engine->getUniquePluginName(name);
  1667. pData->filename = carla_strdup(filename);
  1668. if (bridgeBinary != nullptr)
  1669. fBridgeBinary = bridgeBinary;
  1670. std::srand(static_cast<uint>(std::time(nullptr)));
  1671. // ---------------------------------------------------------------
  1672. // init sem/shm
  1673. if (! fShmAudioPool.initialize())
  1674. {
  1675. carla_stdout("Failed to initialize shared memory audio pool");
  1676. return false;
  1677. }
  1678. if (! fShmRtClientControl.initialize())
  1679. {
  1680. carla_stdout("Failed to initialize RT client control");
  1681. fShmAudioPool.clear();
  1682. return false;
  1683. }
  1684. if (! fShmNonRtClientControl.initialize())
  1685. {
  1686. carla_stdout("Failed to initialize Non-RT client control");
  1687. fShmRtClientControl.clear();
  1688. fShmAudioPool.clear();
  1689. return false;
  1690. }
  1691. if (! fShmNonRtServerControl.initialize())
  1692. {
  1693. carla_stdout("Failed to initialize Non-RT server control");
  1694. fShmNonRtClientControl.clear();
  1695. fShmRtClientControl.clear();
  1696. fShmAudioPool.clear();
  1697. return false;
  1698. }
  1699. // ---------------------------------------------------------------
  1700. carla_stdout("Carla Server Info:");
  1701. carla_stdout(" sizeof(BridgeRtClientData): " P_SIZE, sizeof(BridgeRtClientData));
  1702. carla_stdout(" sizeof(BridgeNonRtClientData): " P_SIZE, sizeof(BridgeNonRtClientData));
  1703. carla_stdout(" sizeof(BridgeNonRtServerData): " P_SIZE, sizeof(BridgeNonRtServerData));
  1704. // initial values
  1705. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientNull);
  1706. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
  1707. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
  1708. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));
  1709. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetBufferSize);
  1710. fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
  1711. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetSampleRate);
  1712. fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());
  1713. fShmNonRtClientControl.commitWrite();
  1714. // init bridge thread
  1715. {
  1716. char shmIdsStr[6*4+1];
  1717. carla_zeroChar(shmIdsStr, 6*4+1);
  1718. std::strncpy(shmIdsStr+6*0, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  1719. std::strncpy(shmIdsStr+6*1, &fShmRtClientControl.filename[fShmRtClientControl.filename.length()-6], 6);
  1720. std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6);
  1721. std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6);
  1722. fBridgeThread.setData(bridgeBinary, label, shmIdsStr, fPluginType);
  1723. fBridgeThread.startThread();
  1724. }
  1725. fInitiated = false;
  1726. fLastPongCounter = 0;
  1727. for (; fLastPongCounter++ < 500;)
  1728. {
  1729. if (fInitiated || ! fBridgeThread.isThreadRunning())
  1730. break;
  1731. carla_msleep(25);
  1732. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  1733. pData->engine->idle();
  1734. }
  1735. fLastPongCounter = -1;
  1736. if (fInitError || ! fInitiated)
  1737. {
  1738. fBridgeThread.stopThread(6000);
  1739. if (! fInitError)
  1740. pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  1741. return false;
  1742. }
  1743. // ---------------------------------------------------------------
  1744. // register client
  1745. if (pData->name == nullptr)
  1746. {
  1747. if (name != nullptr && name[0] != '\0')
  1748. pData->name = pData->engine->getUniquePluginName(name);
  1749. else if (label != nullptr && label[0] != '\0')
  1750. pData->name = pData->engine->getUniquePluginName(label);
  1751. else
  1752. pData->name = pData->engine->getUniquePluginName("unknown");
  1753. }
  1754. pData->client = pData->engine->addClient(this);
  1755. if (pData->client == nullptr || ! pData->client->isOk())
  1756. {
  1757. pData->engine->setLastError("Failed to register plugin client");
  1758. return false;
  1759. }
  1760. return true;
  1761. }
  1762. private:
  1763. const BinaryType fBinaryType;
  1764. const PluginType fPluginType;
  1765. bool fInitiated;
  1766. bool fInitError;
  1767. bool fSaved;
  1768. bool fTimedOut;
  1769. volatile int32_t fLastPongCounter;
  1770. CarlaString fBridgeBinary;
  1771. CarlaPluginBridgeThread fBridgeThread;
  1772. BridgeAudioPool fShmAudioPool;
  1773. BridgeRtClientControl fShmRtClientControl;
  1774. BridgeNonRtClientControl fShmNonRtClientControl;
  1775. BridgeNonRtServerControl fShmNonRtServerControl;
  1776. struct Info {
  1777. uint32_t aIns, aOuts;
  1778. uint32_t cvIns, cvOuts;
  1779. uint32_t mIns, mOuts;
  1780. PluginCategory category;
  1781. uint optionsAvailable;
  1782. int64_t uniqueId;
  1783. CarlaString name;
  1784. CarlaString label;
  1785. CarlaString maker;
  1786. CarlaString copyright;
  1787. std::vector<uint8_t> chunk;
  1788. Info()
  1789. : aIns(0),
  1790. aOuts(0),
  1791. cvIns(0),
  1792. cvOuts(0),
  1793. mIns(0),
  1794. mOuts(0),
  1795. category(PLUGIN_CATEGORY_NONE),
  1796. optionsAvailable(0),
  1797. uniqueId(0),
  1798. name(),
  1799. label(),
  1800. maker(),
  1801. copyright(),
  1802. chunk() {}
  1803. } fInfo;
  1804. BridgeParamInfo* fParams;
  1805. void resizeAudioPool(const uint32_t bufferSize)
  1806. {
  1807. fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);
  1808. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
  1809. fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.size));
  1810. fShmRtClientControl.commitWrite();
  1811. waitForClient();
  1812. }
  1813. bool waitForClient(const uint secs = 5)
  1814. {
  1815. CARLA_SAFE_ASSERT_RETURN(! fTimedOut, false);
  1816. if (! fShmRtClientControl.waitForClient(secs))
  1817. {
  1818. carla_stderr("waitForClient() timeout here");
  1819. fTimedOut = true;
  1820. return false;
  1821. }
  1822. return true;
  1823. }
  1824. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge)
  1825. };
  1826. CARLA_BACKEND_END_NAMESPACE
  1827. // -------------------------------------------------------------------------------------------------------------------
  1828. CARLA_BACKEND_START_NAMESPACE
  1829. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
  1830. {
  1831. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1832. if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
  1833. {
  1834. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1835. return nullptr;
  1836. }
  1837. CarlaPluginBridge* const plugin(new CarlaPluginBridge(init.engine, init.id, btype, ptype));
  1838. if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
  1839. {
  1840. delete plugin;
  1841. return nullptr;
  1842. }
  1843. plugin->reload();
  1844. bool canRun = true;
  1845. if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  1846. {
  1847. if (! plugin->canRunInRack())
  1848. {
  1849. init.engine->setLastError("Carla's rack mode can only work with Stereo Bridged plugins, sorry!");
  1850. canRun = false;
  1851. }
  1852. else if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0)
  1853. {
  1854. init.engine->setLastError("Carla's rack mode cannot work with plugins that have CV ports, sorry!");
  1855. canRun = false;
  1856. }
  1857. }
  1858. else if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_PATCHBAY && (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0))
  1859. {
  1860. init.engine->setLastError("CV ports in patchbay mode is still TODO");
  1861. canRun = false;
  1862. }
  1863. if (! canRun)
  1864. {
  1865. delete plugin;
  1866. return nullptr;
  1867. }
  1868. return plugin;
  1869. }
  1870. CARLA_BACKEND_END_NAMESPACE
  1871. // -------------------------------------------------------------------------------------------------------------------