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 27KB

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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. /*
  2. * Carla Plugin
  3. * Copyright (C) 2011-2020 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 "CarlaMIDI.h"
  22. CARLA_BACKEND_START_NAMESPACE
  23. // -------------------------------------------------------------------
  24. // Fallback data
  25. static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr };
  26. static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr };
  27. // -----------------------------------------------------------------------
  28. // PluginAudioData
  29. PluginAudioData::PluginAudioData() noexcept
  30. : count(0),
  31. ports(nullptr) {}
  32. PluginAudioData::~PluginAudioData() noexcept
  33. {
  34. CARLA_SAFE_ASSERT_INT(count == 0, count);
  35. CARLA_SAFE_ASSERT(ports == nullptr);
  36. }
  37. void PluginAudioData::createNew(const uint32_t newCount)
  38. {
  39. CARLA_SAFE_ASSERT_INT(count == 0, count);
  40. CARLA_SAFE_ASSERT_RETURN(ports == nullptr,);
  41. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  42. ports = new PluginAudioPort[newCount];
  43. carla_zeroStructs(ports, newCount);
  44. count = newCount;
  45. }
  46. void PluginAudioData::clear() noexcept
  47. {
  48. if (ports != nullptr)
  49. {
  50. for (uint32_t i=0; i < count; ++i)
  51. {
  52. if (ports[i].port != nullptr)
  53. {
  54. delete ports[i].port;
  55. ports[i].port = nullptr;
  56. }
  57. }
  58. delete[] ports;
  59. ports = nullptr;
  60. }
  61. count = 0;
  62. }
  63. void PluginAudioData::initBuffers() const noexcept
  64. {
  65. for (uint32_t i=0; i < count; ++i)
  66. {
  67. if (ports[i].port != nullptr)
  68. ports[i].port->initBuffer();
  69. }
  70. }
  71. // -----------------------------------------------------------------------
  72. // PluginCVData
  73. PluginCVData::PluginCVData() noexcept
  74. : count(0),
  75. ports(nullptr) {}
  76. PluginCVData::~PluginCVData() noexcept
  77. {
  78. CARLA_SAFE_ASSERT_INT(count == 0, count);
  79. CARLA_SAFE_ASSERT(ports == nullptr);
  80. }
  81. void PluginCVData::createNew(const uint32_t newCount)
  82. {
  83. CARLA_SAFE_ASSERT_INT(count == 0, count);
  84. CARLA_SAFE_ASSERT_RETURN(ports == nullptr,);
  85. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  86. ports = new PluginCVPort[newCount];
  87. carla_zeroStructs(ports, newCount);
  88. count = newCount;
  89. }
  90. void PluginCVData::clear() noexcept
  91. {
  92. if (ports != nullptr)
  93. {
  94. for (uint32_t i=0; i < count; ++i)
  95. {
  96. if (ports[i].port != nullptr)
  97. {
  98. delete ports[i].port;
  99. ports[i].port = nullptr;
  100. }
  101. }
  102. delete[] ports;
  103. ports = nullptr;
  104. }
  105. count = 0;
  106. }
  107. void PluginCVData::initBuffers() const noexcept
  108. {
  109. for (uint32_t i=0; i < count; ++i)
  110. {
  111. if (ports[i].port != nullptr)
  112. ports[i].port->initBuffer();
  113. }
  114. }
  115. // -----------------------------------------------------------------------
  116. // PluginEventData
  117. PluginEventData::PluginEventData() noexcept
  118. : portIn(nullptr),
  119. portOut(nullptr)
  120. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  121. , cvSourcePorts(nullptr)
  122. #endif
  123. {
  124. }
  125. PluginEventData::~PluginEventData() noexcept
  126. {
  127. CARLA_SAFE_ASSERT(portIn == nullptr);
  128. CARLA_SAFE_ASSERT(portOut == nullptr);
  129. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  130. CARLA_SAFE_ASSERT(cvSourcePorts == nullptr);
  131. #endif
  132. }
  133. void PluginEventData::clear() noexcept
  134. {
  135. if (portIn != nullptr)
  136. {
  137. delete portIn;
  138. portIn = nullptr;
  139. }
  140. if (portOut != nullptr)
  141. {
  142. delete portOut;
  143. portOut = nullptr;
  144. }
  145. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  146. if (cvSourcePorts != nullptr)
  147. {
  148. cvSourcePorts->cleanup();
  149. cvSourcePorts = nullptr;
  150. }
  151. #endif
  152. }
  153. void PluginEventData::initBuffers() const noexcept
  154. {
  155. if (portIn != nullptr)
  156. portIn->initBuffer();
  157. if (portOut != nullptr)
  158. portOut->initBuffer();
  159. }
  160. // -----------------------------------------------------------------------
  161. // PluginParameterData
  162. PluginParameterData::PluginParameterData() noexcept
  163. : count(0),
  164. data(nullptr),
  165. ranges(nullptr),
  166. special(nullptr) {}
  167. PluginParameterData::~PluginParameterData() noexcept
  168. {
  169. CARLA_SAFE_ASSERT_INT(count == 0, count);
  170. CARLA_SAFE_ASSERT(data == nullptr);
  171. CARLA_SAFE_ASSERT(ranges == nullptr);
  172. CARLA_SAFE_ASSERT(special == nullptr);
  173. }
  174. void PluginParameterData::createNew(const uint32_t newCount, const bool withSpecial)
  175. {
  176. CARLA_SAFE_ASSERT_INT(count == 0, count);
  177. CARLA_SAFE_ASSERT_RETURN(data == nullptr,);
  178. CARLA_SAFE_ASSERT_RETURN(ranges == nullptr,);
  179. CARLA_SAFE_ASSERT_RETURN(special == nullptr,);
  180. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  181. data = new ParameterData[newCount];
  182. carla_zeroStructs(data, newCount);
  183. for (uint32_t i=0; i < newCount; ++i)
  184. {
  185. data[i].index = PARAMETER_NULL;
  186. data[i].rindex = PARAMETER_NULL;
  187. data[i].mappedControlIndex = CONTROL_INDEX_NONE;
  188. data[i].mappedMinimum = -1.0f;
  189. data[i].mappedMaximum = 1.0f;
  190. }
  191. ranges = new ParameterRanges[newCount];
  192. carla_zeroStructs(ranges, newCount);
  193. if (withSpecial)
  194. {
  195. special = new SpecialParameterType[newCount];
  196. carla_zeroStructs(special, newCount);
  197. }
  198. count = newCount;
  199. }
  200. void PluginParameterData::clear() noexcept
  201. {
  202. if (data != nullptr)
  203. {
  204. delete[] data;
  205. data = nullptr;
  206. }
  207. if (ranges != nullptr)
  208. {
  209. delete[] ranges;
  210. ranges = nullptr;
  211. }
  212. if (special != nullptr)
  213. {
  214. delete[] special;
  215. special = nullptr;
  216. }
  217. count = 0;
  218. }
  219. float PluginParameterData::getFixedValue(const uint32_t parameterId, float value) const noexcept
  220. {
  221. CARLA_SAFE_ASSERT_RETURN(parameterId < count, 0.0f);
  222. const uint paramHints (data[parameterId].hints);
  223. const ParameterRanges& paramRanges(ranges[parameterId]);
  224. // if boolean, return either min or max
  225. if (paramHints & PARAMETER_IS_BOOLEAN)
  226. {
  227. const float middlePoint = paramRanges.min + (paramRanges.max-paramRanges.min)/2.0f;
  228. return value >= middlePoint ? paramRanges.max : paramRanges.min;
  229. }
  230. // if integer, round first
  231. if (paramHints & PARAMETER_IS_INTEGER)
  232. return paramRanges.getFixedValue(std::round(value));
  233. // normal mode
  234. return paramRanges.getFixedValue(value);
  235. }
  236. // copied from ParameterRanges::getUnnormalizedValue
  237. static float _getUnnormalizedValue(const float min, const float max, const float value) noexcept
  238. {
  239. if (value <= 0.0f)
  240. return min;
  241. if (value >= 1.0f)
  242. return max;
  243. return value * (max - min) + min;
  244. }
  245. // copied from ParameterRanges::getUnnormalizedLogValue
  246. static float _getUnnormalizedLogValue(const float min, const float max, const float value) noexcept
  247. {
  248. if (value <= 0.0f)
  249. return min;
  250. if (value >= 1.0f)
  251. return max;
  252. float rmin = min;
  253. if (std::abs(min) < std::numeric_limits<float>::epsilon())
  254. rmin = 0.00001f;
  255. return rmin * std::pow(max/rmin, value);
  256. }
  257. float PluginParameterData::getFinalUnnormalizedValue(const uint32_t parameterId,
  258. const float normalizedValue) const noexcept
  259. {
  260. float min, max, value;
  261. if (data[parameterId].mappedControlIndex != CONTROL_INDEX_CV
  262. && (data[parameterId].hints & PARAMETER_MAPPED_RANGES_SET) != 0x0)
  263. {
  264. min = data[parameterId].mappedMinimum;
  265. max = data[parameterId].mappedMaximum;
  266. }
  267. else
  268. {
  269. min = ranges[parameterId].min;
  270. max = ranges[parameterId].max;
  271. }
  272. if (data[parameterId].hints & PARAMETER_IS_BOOLEAN)
  273. {
  274. value = (normalizedValue < 0.5f) ? min : max;
  275. }
  276. else
  277. {
  278. if (data[parameterId].hints & PARAMETER_IS_LOGARITHMIC)
  279. value = _getUnnormalizedLogValue(min, max, normalizedValue);
  280. else
  281. value = _getUnnormalizedValue(min, max, normalizedValue);
  282. if (data[parameterId].hints & PARAMETER_IS_INTEGER)
  283. value = std::rint(value);
  284. }
  285. return value;
  286. }
  287. float PluginParameterData::getFinalValueWithMidiDelta(const uint32_t parameterId,
  288. float value, int8_t delta) const noexcept
  289. {
  290. if (delta < 0)
  291. return value;
  292. if (data[parameterId].mappedControlIndex <= 0 || data[parameterId].mappedControlIndex >= MAX_MIDI_CONTROL)
  293. return value;
  294. float min, max;
  295. if ((data[parameterId].hints & PARAMETER_MAPPED_RANGES_SET) != 0x0)
  296. {
  297. min = data[parameterId].mappedMinimum;
  298. max = data[parameterId].mappedMaximum;
  299. }
  300. else
  301. {
  302. min = ranges[parameterId].min;
  303. max = ranges[parameterId].max;
  304. }
  305. if (data[parameterId].hints & PARAMETER_IS_BOOLEAN)
  306. {
  307. value = delta > 63 ? min : max;
  308. }
  309. else
  310. {
  311. if (data[parameterId].hints & PARAMETER_IS_INTEGER)
  312. {
  313. if (delta > 63)
  314. value += delta - 128.0f;
  315. else
  316. value += delta;
  317. }
  318. else
  319. {
  320. if (delta > 63)
  321. delta = static_cast<int8_t>(delta - 128);
  322. value += (max - min) * (static_cast<float>(delta) / 127.0f);
  323. }
  324. if (value < min)
  325. value = min;
  326. else if (value > max)
  327. value = max;
  328. }
  329. return value;
  330. }
  331. // -----------------------------------------------------------------------
  332. // PluginProgramData
  333. PluginProgramData::PluginProgramData() noexcept
  334. : count(0),
  335. current(-1),
  336. names(nullptr) {}
  337. PluginProgramData::~PluginProgramData() noexcept
  338. {
  339. CARLA_SAFE_ASSERT_INT(count == 0, count);
  340. CARLA_SAFE_ASSERT_INT(current == -1, current);
  341. CARLA_SAFE_ASSERT(names == nullptr);
  342. }
  343. void PluginProgramData::createNew(const uint32_t newCount)
  344. {
  345. CARLA_SAFE_ASSERT_INT(count == 0, count);
  346. CARLA_SAFE_ASSERT_INT(current == -1, current);
  347. CARLA_SAFE_ASSERT_RETURN(names == nullptr,);
  348. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  349. names = new ProgramName[newCount];
  350. carla_zeroStructs(names, newCount);
  351. count = newCount;
  352. current = -1;
  353. }
  354. void PluginProgramData::clear() noexcept
  355. {
  356. if (names != nullptr)
  357. {
  358. for (uint32_t i=0; i < count; ++i)
  359. {
  360. if (names[i] != nullptr)
  361. {
  362. delete[] names[i];
  363. names[i] = nullptr;
  364. }
  365. }
  366. delete[] names;
  367. names = nullptr;
  368. }
  369. count = 0;
  370. current = -1;
  371. }
  372. // -----------------------------------------------------------------------
  373. // PluginMidiProgramData
  374. PluginMidiProgramData::PluginMidiProgramData() noexcept
  375. : count(0),
  376. current(-1),
  377. data(nullptr) {}
  378. PluginMidiProgramData::~PluginMidiProgramData() noexcept
  379. {
  380. CARLA_SAFE_ASSERT_INT(count == 0, count);
  381. CARLA_SAFE_ASSERT_INT(current == -1, current);
  382. CARLA_SAFE_ASSERT(data == nullptr);
  383. }
  384. void PluginMidiProgramData::createNew(const uint32_t newCount)
  385. {
  386. CARLA_SAFE_ASSERT_INT(count == 0, count);
  387. CARLA_SAFE_ASSERT_INT(current == -1, current);
  388. CARLA_SAFE_ASSERT_RETURN(data == nullptr,);
  389. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  390. data = new MidiProgramData[newCount];
  391. carla_zeroStructs(data, newCount);
  392. count = newCount;
  393. current = -1;
  394. }
  395. void PluginMidiProgramData::clear() noexcept
  396. {
  397. if (data != nullptr)
  398. {
  399. for (uint32_t i=0; i < count; ++i)
  400. {
  401. if (data[i].name != nullptr)
  402. {
  403. delete[] data[i].name;
  404. data[i].name = nullptr;
  405. }
  406. }
  407. delete[] data;
  408. data = nullptr;
  409. }
  410. count = 0;
  411. current = -1;
  412. }
  413. const MidiProgramData& PluginMidiProgramData::getCurrent() const noexcept
  414. {
  415. CARLA_SAFE_ASSERT_RETURN(current >= 0 && current < static_cast<int32_t>(count), kMidiProgramDataNull);
  416. return data[current];
  417. }
  418. // -----------------------------------------------------------------------
  419. // ProtectedData::ExternalNotes
  420. CarlaPlugin::ProtectedData::ExternalNotes::ExternalNotes() noexcept
  421. : mutex(),
  422. dataPool("CarlaPlugin::ProtectedData::ExternalNotes", 32, 152),
  423. data(dataPool) {}
  424. CarlaPlugin::ProtectedData::ExternalNotes::~ExternalNotes() noexcept
  425. {
  426. clear();
  427. }
  428. void CarlaPlugin::ProtectedData::ExternalNotes::appendNonRT(const ExternalMidiNote& note) noexcept
  429. {
  430. mutex.lock();
  431. data.append_sleepy(note);
  432. mutex.unlock();
  433. }
  434. void CarlaPlugin::ProtectedData::ExternalNotes::clear() noexcept
  435. {
  436. mutex.lock();
  437. data.clear();
  438. mutex.unlock();
  439. }
  440. // -----------------------------------------------------------------------
  441. // ProtectedData::Latency
  442. CarlaPlugin::ProtectedData::Latency::Latency() noexcept
  443. #ifdef BUILD_BRIDGE
  444. : frames(0) {}
  445. #else
  446. : frames(0),
  447. channels(0),
  448. buffers(nullptr) {}
  449. #endif
  450. #ifndef BUILD_BRIDGE
  451. CarlaPlugin::ProtectedData::Latency::~Latency() noexcept
  452. {
  453. clearBuffers();
  454. }
  455. void CarlaPlugin::ProtectedData::Latency::clearBuffers() noexcept
  456. {
  457. if (buffers != nullptr)
  458. {
  459. for (uint32_t i=0; i < channels; ++i)
  460. {
  461. CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr);
  462. delete[] buffers[i];
  463. buffers[i] = nullptr;
  464. }
  465. delete[] buffers;
  466. buffers = nullptr;
  467. }
  468. channels = 0;
  469. frames = 0;
  470. }
  471. void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChannels, const uint32_t newFrames)
  472. {
  473. CARLA_SAFE_ASSERT_RETURN(channels != newChannels || frames != newFrames,);
  474. const bool retrieveOldBuffer = (channels == newChannels && channels > 0 && frames > 0 && newFrames > 0);
  475. float** const oldBuffers = buffers;
  476. const uint32_t oldFrames = frames;
  477. channels = newChannels;
  478. frames = newFrames;
  479. if (channels > 0 && frames > 0)
  480. {
  481. buffers = new float*[channels];
  482. for (uint32_t i=0; i < channels; ++i)
  483. {
  484. buffers[i] = new float[frames];
  485. if (retrieveOldBuffer)
  486. {
  487. if (oldFrames > frames)
  488. {
  489. const uint32_t diff = oldFrames - frames;
  490. carla_copyFloats(buffers[i], oldBuffers[i] + diff, frames);
  491. }
  492. else
  493. {
  494. const uint32_t diff = frames - oldFrames;
  495. carla_zeroFloats(buffers[i], diff);
  496. carla_copyFloats(buffers[i] + diff, oldBuffers[i], oldFrames);
  497. }
  498. }
  499. else
  500. {
  501. carla_zeroFloats(buffers[i], frames);
  502. }
  503. }
  504. }
  505. else
  506. {
  507. buffers = nullptr;
  508. }
  509. // delete old buffer
  510. if (oldBuffers != nullptr)
  511. {
  512. for (uint32_t i=0; i < channels; ++i)
  513. {
  514. CARLA_SAFE_ASSERT_CONTINUE(oldBuffers[i] != nullptr);
  515. delete[] oldBuffers[i];
  516. oldBuffers[i] = nullptr;
  517. }
  518. delete[] oldBuffers;
  519. }
  520. }
  521. #endif
  522. // -----------------------------------------------------------------------
  523. // ProtectedData::PostRtEvents
  524. CarlaPlugin::ProtectedData::PostRtEvents::PostRtEvents() noexcept
  525. : dataPool("CarlaPlugin::ProtectedData::PostRtEvents", 512, 512),
  526. data(dataPool),
  527. dataPendingRT(dataPool),
  528. dataMutex(),
  529. dataPendingMutex(),
  530. poolMutex() {}
  531. CarlaPlugin::ProtectedData::PostRtEvents::~PostRtEvents() noexcept
  532. {
  533. const CarlaMutexLocker cml1(dataMutex);
  534. const CarlaMutexLocker cml2(dataPendingMutex);
  535. const CarlaMutexLocker cml3(poolMutex);
  536. data.clear();
  537. dataPendingRT.clear();
  538. }
  539. void CarlaPlugin::ProtectedData::PostRtEvents::appendRT(const PluginPostRtEvent& e) noexcept
  540. {
  541. CARLA_SAFE_ASSERT_INT_RETURN(dataPendingMutex.tryLock(), e.type,);
  542. {
  543. const CarlaMutexLocker cml(poolMutex);
  544. dataPendingRT.append(e);
  545. }
  546. dataPendingMutex.unlock();
  547. }
  548. void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept
  549. {
  550. const CarlaMutexTryLocker cmtl(dataPendingMutex);
  551. if (cmtl.wasLocked() && dataPendingRT.isNotEmpty() && dataMutex.tryLock())
  552. {
  553. {
  554. const CarlaMutexLocker cml(poolMutex);
  555. dataPendingRT.moveTo(data, true);
  556. }
  557. dataMutex.unlock();
  558. }
  559. }
  560. // -----------------------------------------------------------------------
  561. // ProtectedData::PostUiEvents
  562. CarlaPlugin::ProtectedData::PostUiEvents::PostUiEvents() noexcept
  563. : mutex(),
  564. data() {}
  565. CarlaPlugin::ProtectedData::PostUiEvents::~PostUiEvents() noexcept
  566. {
  567. clear();
  568. }
  569. void CarlaPlugin::ProtectedData::PostUiEvents::append(const PluginPostRtEvent& e) noexcept
  570. {
  571. mutex.lock();
  572. data.append(e);
  573. mutex.unlock();
  574. }
  575. void CarlaPlugin::ProtectedData::PostUiEvents::clear() noexcept
  576. {
  577. mutex.lock();
  578. data.clear();
  579. mutex.unlock();
  580. }
  581. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  582. // -----------------------------------------------------------------------
  583. // ProtectedData::PostProc
  584. CarlaPlugin::ProtectedData::PostProc::PostProc() noexcept
  585. : dryWet(1.0f),
  586. volume(1.0f),
  587. balanceLeft(-1.0f),
  588. balanceRight(1.0f),
  589. panning(0.0f),
  590. extraBuffer(nullptr) {}
  591. #endif
  592. // -----------------------------------------------------------------------
  593. CarlaPlugin::ProtectedData::ProtectedData(CarlaEngine* const eng, const uint idx) noexcept
  594. : engine(eng),
  595. client(nullptr),
  596. id(idx),
  597. hints(0x0),
  598. options(0x0),
  599. nodeId(0),
  600. active(false),
  601. enabled(false),
  602. needsReset(false),
  603. engineBridged(eng->getType() == kEngineTypeBridge),
  604. enginePlugin(eng->getType() == kEngineTypePlugin),
  605. lib(nullptr),
  606. uiLib(nullptr),
  607. ctrlChannel(0),
  608. extraHints(0x0),
  609. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  610. midiLearnParameterIndex(-1),
  611. transientTryCounter(0),
  612. transientFirstTry(true),
  613. #endif
  614. name(nullptr),
  615. filename(nullptr),
  616. iconName(nullptr),
  617. audioIn(),
  618. audioOut(),
  619. cvIn(),
  620. cvOut(),
  621. event(),
  622. param(),
  623. prog(),
  624. midiprog(),
  625. custom(),
  626. masterMutex(),
  627. singleMutex(),
  628. stateSave(),
  629. uiTitle(),
  630. extNotes(),
  631. latency(),
  632. postRtEvents(),
  633. postUiEvents()
  634. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  635. , postProc()
  636. #endif
  637. {}
  638. CarlaPlugin::ProtectedData::~ProtectedData() noexcept
  639. {
  640. CARLA_SAFE_ASSERT(! (active && needsReset));
  641. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  642. CARLA_SAFE_ASSERT(transientTryCounter == 0);
  643. #endif
  644. {
  645. // mutex MUST have been locked before
  646. const bool lockMaster(masterMutex.tryLock());
  647. const bool lockSingle(singleMutex.tryLock());
  648. CARLA_SAFE_ASSERT(! lockMaster);
  649. CARLA_SAFE_ASSERT(! lockSingle);
  650. }
  651. if (client != nullptr)
  652. {
  653. if (client->isActive())
  654. {
  655. // must not happen
  656. carla_safe_assert("client->isActive()", __FILE__, __LINE__);
  657. client->deactivate(true);
  658. }
  659. clearBuffers();
  660. delete client;
  661. client = nullptr;
  662. }
  663. if (name != nullptr)
  664. {
  665. delete[] name;
  666. name = nullptr;
  667. }
  668. if (filename != nullptr)
  669. {
  670. delete[] filename;
  671. filename = nullptr;
  672. }
  673. if (iconName != nullptr)
  674. {
  675. delete[] iconName;
  676. iconName = nullptr;
  677. }
  678. for (LinkedList<CustomData>::Itenerator it = custom.begin2(); it.valid(); it.next())
  679. {
  680. CustomData& customData(it.getValue(kCustomDataFallbackNC));
  681. //CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  682. if (customData.type != nullptr)
  683. {
  684. delete[] customData.type;
  685. customData.type = nullptr;
  686. }
  687. else
  688. carla_safe_assert("customData.type != nullptr", __FILE__, __LINE__);
  689. if (customData.key != nullptr)
  690. {
  691. delete[] customData.key;
  692. customData.key = nullptr;
  693. }
  694. else
  695. carla_safe_assert("customData.key != nullptr", __FILE__, __LINE__);
  696. if (customData.value != nullptr)
  697. {
  698. delete[] customData.value;
  699. customData.value = nullptr;
  700. }
  701. else
  702. carla_safe_assert("customData.value != nullptr", __FILE__, __LINE__);
  703. }
  704. prog.clear();
  705. midiprog.clear();
  706. custom.clear();
  707. // MUST have been locked before
  708. masterMutex.unlock();
  709. singleMutex.unlock();
  710. CARLA_SAFE_ASSERT(uiLib == nullptr);
  711. if (lib != nullptr)
  712. libClose();
  713. }
  714. // -----------------------------------------------------------------------
  715. // Buffer functions
  716. void CarlaPlugin::ProtectedData::clearBuffers() noexcept
  717. {
  718. audioIn.clear();
  719. audioOut.clear();
  720. cvIn.clear();
  721. cvOut.clear();
  722. param.clear();
  723. event.clear();
  724. #ifndef BUILD_BRIDGE
  725. latency.clearBuffers();
  726. #endif
  727. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  728. if (postProc.extraBuffer != nullptr)
  729. {
  730. delete[] postProc.extraBuffer;
  731. postProc.extraBuffer = nullptr;
  732. }
  733. #endif
  734. }
  735. // -----------------------------------------------------------------------
  736. // Post-poned events
  737. void CarlaPlugin::ProtectedData::postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept
  738. {
  739. CARLA_SAFE_ASSERT_RETURN(rtEvent.type != kPluginPostRtEventNull,);
  740. postRtEvents.appendRT(rtEvent);
  741. }
  742. void CarlaPlugin::ProtectedData::postponeParameterChangeRtEvent(const bool sendCallbackLater,
  743. const int32_t index,
  744. const float value) noexcept
  745. {
  746. PluginPostRtEvent rtEvent = { kPluginPostRtEventParameterChange, sendCallbackLater, {} };
  747. rtEvent.parameter.index = index;
  748. rtEvent.parameter.value = value;
  749. postRtEvents.appendRT(rtEvent);
  750. }
  751. void CarlaPlugin::ProtectedData::postponeProgramChangeRtEvent(const bool sendCallbackLater,
  752. const uint32_t index) noexcept
  753. {
  754. PluginPostRtEvent rtEvent = { kPluginPostRtEventProgramChange, sendCallbackLater, {} };
  755. rtEvent.program.index = index;
  756. postRtEvents.appendRT(rtEvent);
  757. }
  758. void CarlaPlugin::ProtectedData::postponeMidiProgramChangeRtEvent(const bool sendCallbackLater,
  759. const uint32_t index) noexcept
  760. {
  761. PluginPostRtEvent rtEvent = { kPluginPostRtEventMidiProgramChange, sendCallbackLater, {} };
  762. rtEvent.program.index = index;
  763. postRtEvents.appendRT(rtEvent);
  764. }
  765. void CarlaPlugin::ProtectedData::postponeNoteOnRtEvent(const bool sendCallbackLater,
  766. const uint8_t channel,
  767. const uint8_t note,
  768. const uint8_t velocity) noexcept
  769. {
  770. PluginPostRtEvent rtEvent = { kPluginPostRtEventNoteOn, sendCallbackLater, {} };
  771. rtEvent.note.channel = channel;
  772. rtEvent.note.note = note;
  773. rtEvent.note.velocity = velocity;
  774. postRtEvents.appendRT(rtEvent);
  775. }
  776. void CarlaPlugin::ProtectedData::postponeNoteOffRtEvent(const bool sendCallbackLater,
  777. const uint8_t channel,
  778. const uint8_t note) noexcept
  779. {
  780. PluginPostRtEvent rtEvent = { kPluginPostRtEventNoteOff, sendCallbackLater, {} };
  781. rtEvent.note.channel = channel;
  782. rtEvent.note.note = note;
  783. postRtEvents.appendRT(rtEvent);
  784. }
  785. void CarlaPlugin::ProtectedData::postponeMidiLearnRtEvent(const bool sendCallbackLater,
  786. const uint32_t parameter,
  787. const uint8_t cc,
  788. const uint8_t channel) noexcept
  789. {
  790. PluginPostRtEvent rtEvent = { kPluginPostRtEventMidiLearn, sendCallbackLater, {} };
  791. rtEvent.midiLearn.parameter = parameter;
  792. rtEvent.midiLearn.cc = cc;
  793. rtEvent.midiLearn.channel = channel;
  794. postRtEvents.appendRT(rtEvent);
  795. }
  796. // -----------------------------------------------------------------------
  797. // Library functions
  798. static LibCounter sLibCounter;
  799. const char* CarlaPlugin::ProtectedData::libError(const char* const fname) noexcept
  800. {
  801. return lib_error(fname);
  802. }
  803. bool CarlaPlugin::ProtectedData::libOpen(const char* const fname) noexcept
  804. {
  805. lib = sLibCounter.open(fname);
  806. return (lib != nullptr);
  807. }
  808. bool CarlaPlugin::ProtectedData::libClose() noexcept
  809. {
  810. const bool ret = sLibCounter.close(lib);
  811. lib = nullptr;
  812. return ret;
  813. }
  814. void CarlaPlugin::ProtectedData::setCanDeleteLib(const bool canDelete) noexcept
  815. {
  816. sLibCounter.setCanDelete(lib, canDelete);
  817. }
  818. bool CarlaPlugin::ProtectedData::uiLibOpen(const char* const fname, const bool canDelete) noexcept
  819. {
  820. uiLib = sLibCounter.open(fname, canDelete);
  821. return (uiLib != nullptr);
  822. }
  823. bool CarlaPlugin::ProtectedData::uiLibClose() noexcept
  824. {
  825. const bool ret = sLibCounter.close(uiLib);
  826. uiLib = nullptr;
  827. return ret;
  828. }
  829. // -----------------------------------------------------------------------
  830. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  831. void CarlaPlugin::ProtectedData::tryTransient() noexcept
  832. {
  833. if (engine->getOptions().frontendWinId != 0)
  834. transientTryCounter = 1;
  835. }
  836. #endif
  837. void CarlaPlugin::ProtectedData::updateParameterValues(CarlaPlugin* const plugin,
  838. const bool sendCallback,
  839. const bool sendOsc,
  840. const bool useDefault) noexcept
  841. {
  842. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback || useDefault,);
  843. for (uint32_t i=0; i < param.count; ++i)
  844. {
  845. const float value(param.ranges[i].getFixedValue(plugin->getParameterValue(i)));
  846. if (useDefault)
  847. param.ranges[i].def = value;
  848. if (useDefault) {
  849. engine->callback(sendCallback, sendOsc,
  850. ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED,
  851. id,
  852. static_cast<int>(i),
  853. 0, 0,
  854. value,
  855. nullptr);
  856. }
  857. engine->callback(sendCallback, sendOsc,
  858. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  859. id,
  860. static_cast<int>(i),
  861. 0, 0,
  862. value,
  863. nullptr);
  864. }
  865. }
  866. void CarlaPlugin::ProtectedData::updateDefaultParameterValues(CarlaPlugin* const plugin) noexcept
  867. {
  868. for (uint32_t i=0; i < param.count; ++i)
  869. param.ranges[i].def = param.ranges[i].getFixedValue(plugin->getParameterValue(i));
  870. }
  871. // -----------------------------------------------------------------------
  872. CARLA_BACKEND_END_NAMESPACE