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.

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