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.

780 lines
19KB

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