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.

CarlaPluginInternal.cpp 18KB

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