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.

2338 lines
75KB

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