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.

840 lines
20KB

  1. /*
  2. * Carla 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. #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, const 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_RETURN(dataPendingMutex.tryLock(),);
  429. dataPendingRT.append(e);
  430. dataPendingMutex.unlock();
  431. }
  432. void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept
  433. {
  434. if (dataMutex.tryLock())
  435. {
  436. if (dataPendingRT.count() > 0)
  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
  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. lib(nullptr),
  492. uiLib(nullptr),
  493. ctrlChannel(0),
  494. extraHints(0x0),
  495. transientTryCounter(0),
  496. name(nullptr),
  497. filename(nullptr),
  498. iconName(nullptr),
  499. audioIn(),
  500. audioOut(),
  501. cvIn(),
  502. cvOut(),
  503. event(),
  504. param(),
  505. prog(),
  506. midiprog(),
  507. custom(),
  508. masterMutex(),
  509. singleMutex(),
  510. stateSave(),
  511. extNotes(),
  512. latency(),
  513. postRtEvents(),
  514. postUiEvents()
  515. #ifndef BUILD_BRIDGE
  516. , postProc()
  517. #endif
  518. {}
  519. CarlaPlugin::ProtectedData::~ProtectedData() noexcept
  520. {
  521. CARLA_SAFE_ASSERT(! (active && needsReset));
  522. CARLA_SAFE_ASSERT(transientTryCounter == 0);
  523. {
  524. // mutex MUST have been locked before
  525. const bool lockMaster(masterMutex.tryLock());
  526. const bool lockSingle(singleMutex.tryLock());
  527. CARLA_SAFE_ASSERT(! lockMaster);
  528. CARLA_SAFE_ASSERT(! lockSingle);
  529. }
  530. if (client != nullptr)
  531. {
  532. if (client->isActive())
  533. {
  534. // must not happen
  535. carla_safe_assert("client->isActive()", __FILE__, __LINE__);
  536. client->deactivate();
  537. }
  538. clearBuffers();
  539. delete client;
  540. client = nullptr;
  541. }
  542. if (name != nullptr)
  543. {
  544. delete[] name;
  545. name = nullptr;
  546. }
  547. if (filename != nullptr)
  548. {
  549. delete[] filename;
  550. filename = nullptr;
  551. }
  552. if (iconName != nullptr)
  553. {
  554. delete[] iconName;
  555. iconName = nullptr;
  556. }
  557. for (LinkedList<CustomData>::Itenerator it = custom.begin2(); it.valid(); it.next())
  558. {
  559. CustomData& customData(it.getValue(kCustomDataFallbackNC));
  560. //CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  561. if (customData.type != nullptr)
  562. {
  563. delete[] customData.type;
  564. customData.type = nullptr;
  565. }
  566. else
  567. carla_safe_assert("customData.type != nullptr", __FILE__, __LINE__);
  568. if (customData.key != nullptr)
  569. {
  570. delete[] customData.key;
  571. customData.key = nullptr;
  572. }
  573. else
  574. carla_safe_assert("customData.key != nullptr", __FILE__, __LINE__);
  575. if (customData.value != nullptr)
  576. {
  577. delete[] customData.value;
  578. customData.value = nullptr;
  579. }
  580. else
  581. carla_safe_assert("customData.value != nullptr", __FILE__, __LINE__);
  582. }
  583. prog.clear();
  584. midiprog.clear();
  585. custom.clear();
  586. // MUST have been locked before
  587. masterMutex.unlock();
  588. singleMutex.unlock();
  589. if (lib != nullptr)
  590. libClose();
  591. CARLA_SAFE_ASSERT(uiLib == nullptr);
  592. }
  593. // -----------------------------------------------------------------------
  594. // Buffer functions
  595. void CarlaPlugin::ProtectedData::clearBuffers() noexcept
  596. {
  597. audioIn.clear();
  598. audioOut.clear();
  599. cvIn.clear();
  600. cvOut.clear();
  601. param.clear();
  602. event.clear();
  603. #ifndef BUILD_BRIDGE
  604. latency.clearBuffers();
  605. #endif
  606. }
  607. // -----------------------------------------------------------------------
  608. // Post-poned events
  609. void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept
  610. {
  611. CARLA_SAFE_ASSERT_RETURN(rtEvent.type != kPluginPostRtEventNull,);
  612. postRtEvents.appendRT(rtEvent);
  613. }
  614. void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEventType type, const int32_t value1, const int32_t value2, const float value3) noexcept
  615. {
  616. CARLA_SAFE_ASSERT_RETURN(type != kPluginPostRtEventNull,);
  617. PluginPostRtEvent rtEvent = { type, value1, value2, value3 };
  618. postRtEvents.appendRT(rtEvent);
  619. }
  620. // -----------------------------------------------------------------------
  621. // Library functions
  622. static LibCounter sLibCounter;
  623. const char* CarlaPlugin::ProtectedData::libError(const char* const fname) noexcept
  624. {
  625. return lib_error(fname);
  626. }
  627. bool CarlaPlugin::ProtectedData::libOpen(const char* const fname) noexcept
  628. {
  629. lib = sLibCounter.open(fname);
  630. return (lib != nullptr);
  631. }
  632. bool CarlaPlugin::ProtectedData::libClose() noexcept
  633. {
  634. const bool ret = sLibCounter.close(lib);
  635. lib = nullptr;
  636. return ret;
  637. }
  638. bool CarlaPlugin::ProtectedData::uiLibOpen(const char* const fname, const bool canDelete) noexcept
  639. {
  640. uiLib = sLibCounter.open(fname, canDelete);
  641. return (uiLib != nullptr);
  642. }
  643. bool CarlaPlugin::ProtectedData::uiLibClose() noexcept
  644. {
  645. const bool ret = sLibCounter.close(uiLib);
  646. uiLib = nullptr;
  647. return ret;
  648. }
  649. // -----------------------------------------------------------------------
  650. #ifndef BUILD_BRIDGE
  651. void CarlaPlugin::ProtectedData::tryTransient() noexcept
  652. {
  653. if (engine->getOptions().frontendWinId != 0)
  654. transientTryCounter = 1;
  655. }
  656. #endif
  657. void CarlaPlugin::ProtectedData::updateParameterValues(CarlaPlugin* const plugin, const bool sendOsc, const bool sendCallback, const bool useDefault) noexcept
  658. {
  659. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback || useDefault,);
  660. for (uint32_t i=0; i < param.count; ++i)
  661. {
  662. const float value(param.ranges[i].getFixedValue(plugin->getParameterValue(i)));
  663. if (useDefault)
  664. param.ranges[i].def = value;
  665. #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
  666. if (sendOsc && i < 50)
  667. {
  668. if (useDefault)
  669. engine->oscSend_control_set_default_value(id, i, value);
  670. engine->oscSend_control_set_parameter_value(id, static_cast<int32_t>(i), value);
  671. }
  672. #endif
  673. if (sendCallback)
  674. {
  675. if (useDefault)
  676. engine->callback(ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, id, static_cast<int>(i), 0, value, nullptr);
  677. engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, id, static_cast<int>(i), 0, value, nullptr);
  678. }
  679. }
  680. // may be unused
  681. return; (void)sendOsc;
  682. }
  683. void CarlaPlugin::ProtectedData::updateDefaultParameterValues(CarlaPlugin* const plugin) noexcept
  684. {
  685. for (uint32_t i=0; i < param.count; ++i)
  686. param.ranges[i].def = param.ranges[i].getFixedValue(plugin->getParameterValue(i));
  687. }
  688. // -----------------------------------------------------------------------
  689. CARLA_BACKEND_END_NAMESPACE