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.

860 lines
21KB

  1. /*
  2. * Carla Plugin
  3. * Copyright (C) 2011-2019 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. #include "CarlaLibCounter.hpp"
  20. #include "CarlaMathUtils.hpp"
  21. CARLA_BACKEND_START_NAMESPACE
  22. // -------------------------------------------------------------------
  23. // Fallback data
  24. static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr };
  25. static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr };
  26. // -----------------------------------------------------------------------
  27. // PluginAudioData
  28. PluginAudioData::PluginAudioData() noexcept
  29. : count(0),
  30. ports(nullptr) {}
  31. PluginAudioData::~PluginAudioData() noexcept
  32. {
  33. CARLA_SAFE_ASSERT_INT(count == 0, count);
  34. CARLA_SAFE_ASSERT(ports == nullptr);
  35. }
  36. void PluginAudioData::createNew(const uint32_t newCount)
  37. {
  38. CARLA_SAFE_ASSERT_INT(count == 0, count);
  39. CARLA_SAFE_ASSERT_RETURN(ports == nullptr,);
  40. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  41. ports = new PluginAudioPort[newCount];
  42. carla_zeroStructs(ports, newCount);
  43. count = newCount;
  44. }
  45. void PluginAudioData::clear() noexcept
  46. {
  47. if (ports != nullptr)
  48. {
  49. for (uint32_t i=0; i < count; ++i)
  50. {
  51. if (ports[i].port != nullptr)
  52. {
  53. delete ports[i].port;
  54. ports[i].port = nullptr;
  55. }
  56. }
  57. delete[] ports;
  58. ports = nullptr;
  59. }
  60. count = 0;
  61. }
  62. void PluginAudioData::initBuffers() const noexcept
  63. {
  64. for (uint32_t i=0; i < count; ++i)
  65. {
  66. if (ports[i].port != nullptr)
  67. ports[i].port->initBuffer();
  68. }
  69. }
  70. // -----------------------------------------------------------------------
  71. // PluginCVData
  72. PluginCVData::PluginCVData() noexcept
  73. : count(0),
  74. ports(nullptr) {}
  75. PluginCVData::~PluginCVData() noexcept
  76. {
  77. CARLA_SAFE_ASSERT_INT(count == 0, count);
  78. CARLA_SAFE_ASSERT(ports == nullptr);
  79. }
  80. void PluginCVData::createNew(const uint32_t newCount)
  81. {
  82. CARLA_SAFE_ASSERT_INT(count == 0, count);
  83. CARLA_SAFE_ASSERT_RETURN(ports == nullptr,);
  84. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  85. ports = new PluginCVPort[newCount];
  86. carla_zeroStructs(ports, newCount);
  87. count = newCount;
  88. }
  89. void PluginCVData::clear() noexcept
  90. {
  91. if (ports != nullptr)
  92. {
  93. for (uint32_t i=0; i < count; ++i)
  94. {
  95. if (ports[i].port != nullptr)
  96. {
  97. delete ports[i].port;
  98. ports[i].port = nullptr;
  99. }
  100. }
  101. delete[] ports;
  102. ports = nullptr;
  103. }
  104. count = 0;
  105. }
  106. void PluginCVData::initBuffers() const noexcept
  107. {
  108. for (uint32_t i=0; i < count; ++i)
  109. {
  110. if (ports[i].port != nullptr)
  111. ports[i].port->initBuffer();
  112. }
  113. }
  114. // -----------------------------------------------------------------------
  115. // PluginEventData
  116. PluginEventData::PluginEventData() noexcept
  117. : portIn(nullptr),
  118. portOut(nullptr) {}
  119. PluginEventData::~PluginEventData() noexcept
  120. {
  121. CARLA_SAFE_ASSERT(portIn == nullptr);
  122. CARLA_SAFE_ASSERT(portOut == nullptr);
  123. }
  124. void PluginEventData::clear() noexcept
  125. {
  126. if (portIn != nullptr)
  127. {
  128. delete portIn;
  129. portIn = nullptr;
  130. }
  131. if (portOut != nullptr)
  132. {
  133. delete portOut;
  134. portOut = nullptr;
  135. }
  136. }
  137. void PluginEventData::initBuffers() const noexcept
  138. {
  139. if (portIn != nullptr)
  140. portIn->initBuffer();
  141. if (portOut != nullptr)
  142. portOut->initBuffer();
  143. }
  144. // -----------------------------------------------------------------------
  145. // PluginParameterData
  146. PluginParameterData::PluginParameterData() noexcept
  147. : count(0),
  148. data(nullptr),
  149. ranges(nullptr),
  150. special(nullptr) {}
  151. PluginParameterData::~PluginParameterData() noexcept
  152. {
  153. CARLA_SAFE_ASSERT_INT(count == 0, count);
  154. CARLA_SAFE_ASSERT(data == nullptr);
  155. CARLA_SAFE_ASSERT(ranges == nullptr);
  156. CARLA_SAFE_ASSERT(special == nullptr);
  157. }
  158. void PluginParameterData::createNew(const uint32_t newCount, const bool withSpecial)
  159. {
  160. CARLA_SAFE_ASSERT_INT(count == 0, count);
  161. CARLA_SAFE_ASSERT_RETURN(data == nullptr,);
  162. CARLA_SAFE_ASSERT_RETURN(ranges == nullptr,);
  163. CARLA_SAFE_ASSERT_RETURN(special == nullptr,);
  164. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  165. data = new ParameterData[newCount];
  166. carla_zeroStructs(data, newCount);
  167. for (uint32_t i=0; i < newCount; ++i)
  168. {
  169. data[i].index = PARAMETER_NULL;
  170. data[i].rindex = PARAMETER_NULL;
  171. data[i].midiCC = -1;
  172. }
  173. ranges = new ParameterRanges[newCount];
  174. carla_zeroStructs(ranges, newCount);
  175. if (withSpecial)
  176. {
  177. special = new SpecialParameterType[newCount];
  178. carla_zeroStructs(special, newCount);
  179. }
  180. count = newCount;
  181. }
  182. void PluginParameterData::clear() noexcept
  183. {
  184. if (data != nullptr)
  185. {
  186. delete[] data;
  187. data = nullptr;
  188. }
  189. if (ranges != nullptr)
  190. {
  191. delete[] ranges;
  192. ranges = nullptr;
  193. }
  194. if (special != nullptr)
  195. {
  196. delete[] special;
  197. special = nullptr;
  198. }
  199. count = 0;
  200. }
  201. float PluginParameterData::getFixedValue(const uint32_t parameterId, float value) const noexcept
  202. {
  203. CARLA_SAFE_ASSERT_RETURN(parameterId < count, 0.0f);
  204. const uint paramHints (data[parameterId].hints);
  205. const ParameterRanges& paramRanges(ranges[parameterId]);
  206. // if boolean, return either min or max
  207. if (paramHints & PARAMETER_IS_BOOLEAN)
  208. {
  209. const float middlePoint = paramRanges.min + (paramRanges.max-paramRanges.min)/2.0f;
  210. return value >= middlePoint ? paramRanges.max : paramRanges.min;
  211. }
  212. // if integer, round first
  213. if (paramHints & PARAMETER_IS_INTEGER)
  214. return paramRanges.getFixedValue(std::round(value));
  215. // normal mode
  216. return paramRanges.getFixedValue(value);
  217. }
  218. // -----------------------------------------------------------------------
  219. // PluginProgramData
  220. PluginProgramData::PluginProgramData() noexcept
  221. : count(0),
  222. current(-1),
  223. names(nullptr) {}
  224. PluginProgramData::~PluginProgramData() noexcept
  225. {
  226. CARLA_SAFE_ASSERT_INT(count == 0, count);
  227. CARLA_SAFE_ASSERT_INT(current == -1, current);
  228. CARLA_SAFE_ASSERT(names == nullptr);
  229. }
  230. void PluginProgramData::createNew(const uint32_t newCount)
  231. {
  232. CARLA_SAFE_ASSERT_INT(count == 0, count);
  233. CARLA_SAFE_ASSERT_INT(current == -1, current);
  234. CARLA_SAFE_ASSERT_RETURN(names == nullptr,);
  235. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  236. names = new ProgramName[newCount];
  237. carla_zeroStructs(names, newCount);
  238. count = newCount;
  239. current = -1;
  240. }
  241. void PluginProgramData::clear() noexcept
  242. {
  243. if (names != nullptr)
  244. {
  245. for (uint32_t i=0; i < count; ++i)
  246. {
  247. if (names[i] != nullptr)
  248. {
  249. delete[] names[i];
  250. names[i] = nullptr;
  251. }
  252. }
  253. delete[] names;
  254. names = nullptr;
  255. }
  256. count = 0;
  257. current = -1;
  258. }
  259. // -----------------------------------------------------------------------
  260. // PluginMidiProgramData
  261. PluginMidiProgramData::PluginMidiProgramData() noexcept
  262. : count(0),
  263. current(-1),
  264. data(nullptr) {}
  265. PluginMidiProgramData::~PluginMidiProgramData() noexcept
  266. {
  267. CARLA_SAFE_ASSERT_INT(count == 0, count);
  268. CARLA_SAFE_ASSERT_INT(current == -1, current);
  269. CARLA_SAFE_ASSERT(data == nullptr);
  270. }
  271. void PluginMidiProgramData::createNew(const uint32_t newCount)
  272. {
  273. CARLA_SAFE_ASSERT_INT(count == 0, count);
  274. CARLA_SAFE_ASSERT_INT(current == -1, current);
  275. CARLA_SAFE_ASSERT_RETURN(data == nullptr,);
  276. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  277. data = new MidiProgramData[newCount];
  278. carla_zeroStructs(data, newCount);
  279. count = newCount;
  280. current = -1;
  281. }
  282. void PluginMidiProgramData::clear() noexcept
  283. {
  284. if (data != nullptr)
  285. {
  286. for (uint32_t i=0; i < count; ++i)
  287. {
  288. if (data[i].name != nullptr)
  289. {
  290. delete[] data[i].name;
  291. data[i].name = nullptr;
  292. }
  293. }
  294. delete[] data;
  295. data = nullptr;
  296. }
  297. count = 0;
  298. current = -1;
  299. }
  300. const MidiProgramData& PluginMidiProgramData::getCurrent() const noexcept
  301. {
  302. CARLA_SAFE_ASSERT_RETURN(current >= 0 && current < static_cast<int32_t>(count), kMidiProgramDataNull);
  303. return data[current];
  304. }
  305. // -----------------------------------------------------------------------
  306. // ProtectedData::ExternalNotes
  307. CarlaPlugin::ProtectedData::ExternalNotes::ExternalNotes() noexcept
  308. : mutex(),
  309. dataPool(32, 152),
  310. data(dataPool) {}
  311. CarlaPlugin::ProtectedData::ExternalNotes::~ExternalNotes() noexcept
  312. {
  313. clear();
  314. }
  315. void CarlaPlugin::ProtectedData::ExternalNotes::appendNonRT(const ExternalMidiNote& note) noexcept
  316. {
  317. mutex.lock();
  318. data.append_sleepy(note);
  319. mutex.unlock();
  320. }
  321. void CarlaPlugin::ProtectedData::ExternalNotes::clear() noexcept
  322. {
  323. mutex.lock();
  324. data.clear();
  325. mutex.unlock();
  326. }
  327. // -----------------------------------------------------------------------
  328. // ProtectedData::Latency
  329. CarlaPlugin::ProtectedData::Latency::Latency() noexcept
  330. #ifdef BUILD_BRIDGE
  331. : frames(0) {}
  332. #else
  333. : frames(0),
  334. channels(0),
  335. buffers(nullptr) {}
  336. #endif
  337. #ifndef BUILD_BRIDGE
  338. CarlaPlugin::ProtectedData::Latency::~Latency() noexcept
  339. {
  340. clearBuffers();
  341. }
  342. void CarlaPlugin::ProtectedData::Latency::clearBuffers() noexcept
  343. {
  344. if (buffers != nullptr)
  345. {
  346. for (uint32_t i=0; i < channels; ++i)
  347. {
  348. CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr);
  349. delete[] buffers[i];
  350. buffers[i] = nullptr;
  351. }
  352. delete[] buffers;
  353. buffers = nullptr;
  354. }
  355. channels = 0;
  356. frames = 0;
  357. }
  358. void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChannels, const uint32_t newFrames)
  359. {
  360. CARLA_SAFE_ASSERT_RETURN(channels != newChannels || frames != newFrames,);
  361. const bool retrieveOldBuffer = (channels == newChannels && channels > 0 && frames > 0 && newFrames > 0);
  362. float** const oldBuffers = buffers;
  363. const uint32_t oldFrames = frames;
  364. channels = newChannels;
  365. frames = newFrames;
  366. if (channels > 0 && frames > 0)
  367. {
  368. buffers = new float*[channels];
  369. for (uint32_t i=0; i < channels; ++i)
  370. {
  371. buffers[i] = new float[frames];
  372. if (retrieveOldBuffer)
  373. {
  374. if (oldFrames > frames)
  375. {
  376. const uint32_t diff = oldFrames - frames;
  377. carla_copyFloats(buffers[i], oldBuffers[i] + diff, frames);
  378. }
  379. else
  380. {
  381. const uint32_t diff = frames - oldFrames;
  382. carla_zeroFloats(buffers[i], diff);
  383. carla_copyFloats(buffers[i] + diff, oldBuffers[i], oldFrames);
  384. }
  385. }
  386. else
  387. {
  388. carla_zeroFloats(buffers[i], frames);
  389. }
  390. }
  391. }
  392. else
  393. {
  394. buffers = nullptr;
  395. }
  396. // delete old buffer
  397. if (oldBuffers != nullptr)
  398. {
  399. for (uint32_t i=0; i < channels; ++i)
  400. {
  401. CARLA_SAFE_ASSERT_CONTINUE(oldBuffers[i] != nullptr);
  402. delete[] oldBuffers[i];
  403. oldBuffers[i] = nullptr;
  404. }
  405. delete[] oldBuffers;
  406. }
  407. }
  408. #endif
  409. // -----------------------------------------------------------------------
  410. // ProtectedData::PostRtEvents
  411. CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept
  412. : dataPool(128, 128),
  413. dataPendingRT(dataPool),
  414. data(dataPool),
  415. dataMutex(),
  416. dataPendingMutex() {}
  417. CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept
  418. {
  419. dataMutex.lock();
  420. data.clear();
  421. dataMutex.unlock();
  422. dataPendingMutex.lock();
  423. dataPendingRT.clear();
  424. dataPendingMutex.unlock();
  425. }
  426. void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept
  427. {
  428. CARLA_SAFE_ASSERT_INT2_RETURN(dataPendingMutex.tryLock(), e.type, e.value1,);
  429. dataPendingRT.append(e);
  430. dataPendingMutex.unlock();
  431. }
  432. void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept
  433. {
  434. const CarlaMutexTryLocker cmtl(dataPendingMutex);
  435. if (cmtl.wasLocked() && dataPendingRT.count() > 0 && dataMutex.tryLock())
  436. {
  437. dataPendingRT.moveTo(data, true);
  438. dataMutex.unlock();
  439. }
  440. }
  441. void CarlaPlugin::ProtectedData::PostRtEvents::clearData() noexcept
  442. {
  443. const bool tryLockOk(dataMutex.tryLock());
  444. CARLA_SAFE_ASSERT(! tryLockOk);
  445. data.clear();
  446. if (tryLockOk)
  447. dataMutex.unlock();
  448. }
  449. // -----------------------------------------------------------------------
  450. // ProtectedData::PostUiEvents
  451. CarlaPlugin::ProtectedData::PostUiEvents::PostUiEvents() noexcept
  452. : mutex(),
  453. data() {}
  454. CarlaPlugin::ProtectedData::PostUiEvents::~PostUiEvents() noexcept
  455. {
  456. clear();
  457. }
  458. void CarlaPlugin::ProtectedData::PostUiEvents::append(const PluginPostRtEvent& e) noexcept
  459. {
  460. mutex.lock();
  461. data.append(e);
  462. mutex.unlock();
  463. }
  464. void CarlaPlugin::ProtectedData::PostUiEvents::clear() noexcept
  465. {
  466. mutex.lock();
  467. data.clear();
  468. mutex.unlock();
  469. }
  470. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  471. // -----------------------------------------------------------------------
  472. // ProtectedData::PostProc
  473. CarlaPlugin::ProtectedData::PostProc::PostProc() noexcept
  474. : dryWet(1.0f),
  475. volume(1.0f),
  476. balanceLeft(-1.0f),
  477. balanceRight(1.0f),
  478. panning(0.0f) {}
  479. #endif
  480. // -----------------------------------------------------------------------
  481. CarlaPlugin::ProtectedData::ProtectedData(CarlaEngine* const eng, const uint idx) noexcept
  482. : engine(eng),
  483. client(nullptr),
  484. id(idx),
  485. hints(0x0),
  486. options(0x0),
  487. nodeId(0),
  488. active(false),
  489. enabled(false),
  490. needsReset(false),
  491. engineBridged(eng->getType() == kEngineTypeBridge),
  492. enginePlugin(eng->getType() == kEngineTypePlugin),
  493. lib(nullptr),
  494. uiLib(nullptr),
  495. ctrlChannel(0),
  496. extraHints(0x0),
  497. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  498. transientTryCounter(0),
  499. transientFirstTry(true),
  500. #endif
  501. name(nullptr),
  502. filename(nullptr),
  503. iconName(nullptr),
  504. audioIn(),
  505. audioOut(),
  506. cvIn(),
  507. cvOut(),
  508. event(),
  509. param(),
  510. prog(),
  511. midiprog(),
  512. custom(),
  513. masterMutex(),
  514. singleMutex(),
  515. stateSave(),
  516. extNotes(),
  517. latency(),
  518. postRtEvents(),
  519. postUiEvents()
  520. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  521. , postProc()
  522. #endif
  523. {}
  524. CarlaPlugin::ProtectedData::~ProtectedData() noexcept
  525. {
  526. CARLA_SAFE_ASSERT(! (active && needsReset));
  527. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  528. CARLA_SAFE_ASSERT(transientTryCounter == 0);
  529. #endif
  530. {
  531. // mutex MUST have been locked before
  532. const bool lockMaster(masterMutex.tryLock());
  533. const bool lockSingle(singleMutex.tryLock());
  534. CARLA_SAFE_ASSERT(! lockMaster);
  535. CARLA_SAFE_ASSERT(! lockSingle);
  536. }
  537. if (client != nullptr)
  538. {
  539. if (client->isActive())
  540. {
  541. // must not happen
  542. carla_safe_assert("client->isActive()", __FILE__, __LINE__);
  543. client->deactivate();
  544. }
  545. clearBuffers();
  546. delete client;
  547. client = nullptr;
  548. }
  549. if (name != nullptr)
  550. {
  551. delete[] name;
  552. name = nullptr;
  553. }
  554. if (filename != nullptr)
  555. {
  556. delete[] filename;
  557. filename = nullptr;
  558. }
  559. if (iconName != nullptr)
  560. {
  561. delete[] iconName;
  562. iconName = nullptr;
  563. }
  564. for (LinkedList<CustomData>::Itenerator it = custom.begin2(); it.valid(); it.next())
  565. {
  566. CustomData& customData(it.getValue(kCustomDataFallbackNC));
  567. //CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  568. if (customData.type != nullptr)
  569. {
  570. delete[] customData.type;
  571. customData.type = nullptr;
  572. }
  573. else
  574. carla_safe_assert("customData.type != nullptr", __FILE__, __LINE__);
  575. if (customData.key != nullptr)
  576. {
  577. delete[] customData.key;
  578. customData.key = nullptr;
  579. }
  580. else
  581. carla_safe_assert("customData.key != nullptr", __FILE__, __LINE__);
  582. if (customData.value != nullptr)
  583. {
  584. delete[] customData.value;
  585. customData.value = nullptr;
  586. }
  587. else
  588. carla_safe_assert("customData.value != nullptr", __FILE__, __LINE__);
  589. }
  590. prog.clear();
  591. midiprog.clear();
  592. custom.clear();
  593. // MUST have been locked before
  594. masterMutex.unlock();
  595. singleMutex.unlock();
  596. CARLA_SAFE_ASSERT(uiLib == nullptr);
  597. if (lib != nullptr)
  598. libClose();
  599. }
  600. // -----------------------------------------------------------------------
  601. // Buffer functions
  602. void CarlaPlugin::ProtectedData::clearBuffers() noexcept
  603. {
  604. audioIn.clear();
  605. audioOut.clear();
  606. cvIn.clear();
  607. cvOut.clear();
  608. param.clear();
  609. event.clear();
  610. #ifndef BUILD_BRIDGE
  611. latency.clearBuffers();
  612. #endif
  613. }
  614. // -----------------------------------------------------------------------
  615. // Post-poned events
  616. void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept
  617. {
  618. CARLA_SAFE_ASSERT_RETURN(rtEvent.type != kPluginPostRtEventNull,);
  619. postRtEvents.appendRT(rtEvent);
  620. }
  621. void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEventType type,
  622. const bool sendCallbackLater,
  623. const int32_t value1,
  624. const int32_t value2,
  625. const int32_t value3,
  626. const float valuef) noexcept
  627. {
  628. CARLA_SAFE_ASSERT_RETURN(type != kPluginPostRtEventNull,);
  629. PluginPostRtEvent rtEvent = { type, sendCallbackLater, value1, value2, value3, valuef };
  630. postRtEvents.appendRT(rtEvent);
  631. }
  632. // -----------------------------------------------------------------------
  633. // Library functions
  634. static LibCounter sLibCounter;
  635. const char* CarlaPlugin::ProtectedData::libError(const char* const fname) noexcept
  636. {
  637. return lib_error(fname);
  638. }
  639. bool CarlaPlugin::ProtectedData::libOpen(const char* const fname) noexcept
  640. {
  641. lib = sLibCounter.open(fname);
  642. return (lib != nullptr);
  643. }
  644. bool CarlaPlugin::ProtectedData::libClose() noexcept
  645. {
  646. const bool ret = sLibCounter.close(lib);
  647. lib = nullptr;
  648. return ret;
  649. }
  650. void CarlaPlugin::ProtectedData::setCanDeleteLib(const bool canDelete) noexcept
  651. {
  652. sLibCounter.setCanDelete(lib, canDelete);
  653. }
  654. bool CarlaPlugin::ProtectedData::uiLibOpen(const char* const fname, const bool canDelete) noexcept
  655. {
  656. uiLib = sLibCounter.open(fname, canDelete);
  657. return (uiLib != nullptr);
  658. }
  659. bool CarlaPlugin::ProtectedData::uiLibClose() noexcept
  660. {
  661. const bool ret = sLibCounter.close(uiLib);
  662. uiLib = nullptr;
  663. return ret;
  664. }
  665. // -----------------------------------------------------------------------
  666. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  667. void CarlaPlugin::ProtectedData::tryTransient() noexcept
  668. {
  669. if (engine->getOptions().frontendWinId != 0)
  670. transientTryCounter = 1;
  671. }
  672. #endif
  673. void CarlaPlugin::ProtectedData::updateParameterValues(CarlaPlugin* const plugin,
  674. const bool sendCallback,
  675. const bool sendOsc,
  676. const bool useDefault) noexcept
  677. {
  678. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback || useDefault,);
  679. for (uint32_t i=0; i < param.count; ++i)
  680. {
  681. const float value(param.ranges[i].getFixedValue(plugin->getParameterValue(i)));
  682. if (useDefault)
  683. param.ranges[i].def = value;
  684. if (useDefault) {
  685. engine->callback(sendCallback, sendOsc,
  686. ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED,
  687. id,
  688. static_cast<int>(i),
  689. 0, 0,
  690. value,
  691. nullptr);
  692. }
  693. engine->callback(sendCallback, sendOsc,
  694. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  695. id,
  696. static_cast<int>(i),
  697. 0, 0,
  698. value,
  699. nullptr);
  700. }
  701. }
  702. void CarlaPlugin::ProtectedData::updateDefaultParameterValues(CarlaPlugin* const plugin) noexcept
  703. {
  704. for (uint32_t i=0; i < param.count; ++i)
  705. param.ranges[i].def = param.ranges[i].getFixedValue(plugin->getParameterValue(i));
  706. }
  707. // -----------------------------------------------------------------------
  708. CARLA_BACKEND_END_NAMESPACE