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.

CarlaPlugin.cpp 67KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135
  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 "CarlaBackendUtils.hpp"
  20. #include "CarlaMathUtils.hpp"
  21. #include "CarlaPluginUi.hpp"
  22. #include <ctime>
  23. #include <QtCore/QFile>
  24. #include <QtCore/QTextStream>
  25. #include <QtXml/QDomNode>
  26. CARLA_BACKEND_START_NAMESPACE
  27. // -------------------------------------------------------------------
  28. // Fallback data
  29. static const ParameterData kParameterDataNull = { PARAMETER_UNKNOWN, 0x0, PARAMETER_NULL, -1, -1, 0 };
  30. static const ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0.0001f, 0.1f };
  31. static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr };
  32. static const CustomData kCustomDataNull = { nullptr, nullptr, nullptr };
  33. static bool gIsLoadingProject = false;
  34. // -------------------------------------------------------------------
  35. // ParamSymbol struct, needed for CarlaPlugin::loadSaveState()
  36. struct ParamSymbol {
  37. int32_t index;
  38. const char* symbol;
  39. ParamSymbol(uint32_t i, const char* s)
  40. : index(static_cast<int32_t>(i)),
  41. symbol(carla_strdup(s)) {}
  42. ~ParamSymbol()
  43. {
  44. CARLA_SAFE_ASSERT_RETURN(symbol != nullptr,)
  45. delete[] symbol;
  46. symbol = nullptr;
  47. }
  48. #ifdef CARLA_PROPER_CPP11_SUPPORT
  49. ParamSymbol() = delete;
  50. CARLA_DECLARE_NON_COPY_STRUCT(ParamSymbol)
  51. #endif
  52. };
  53. // -----------------------------------------------------------------------
  54. void CarlaPluginProtectedData::tryTransient()
  55. {
  56. if (engine->getOptions().frontendWinId != 0)
  57. transientTryCounter = 1;
  58. }
  59. // -----------------------------------------------------------------------
  60. CarlaPlugin* CarlaPlugin::newFileGIG(const Initializer& init, const bool use16Outs)
  61. {
  62. carla_debug("CarlaPlugin::newFileGIG({%p, \"%s\", \"%s\", \"%s\"}, %s)", init.engine, init.filename, init.name, init.label, bool2str(use16Outs));
  63. #ifdef WANT_LINUXSAMPLER
  64. return newLinuxSampler(init, "GIG", use16Outs);
  65. #else
  66. init.engine->setLastError("GIG support not available");
  67. return nullptr;
  68. // unused
  69. (void)use16Outs;
  70. #endif
  71. }
  72. CarlaPlugin* CarlaPlugin::newFileSF2(const Initializer& init, const bool use16Outs)
  73. {
  74. carla_debug("CarlaPlugin::newFileSF2({%p, \"%s\", \"%s\", \"%s\"}, %s)", init.engine, init.filename, init.name, init.label, bool2str(use16Outs));
  75. #if defined(WANT_FLUIDSYNTH)
  76. return newFluidSynth(init, use16Outs);
  77. #elif defined(WANT_LINUXSAMPLER)
  78. return newLinuxSampler(init, "SF2", use16Outs);
  79. #else
  80. init.engine->setLastError("SF2 support not available");
  81. return nullptr;
  82. // unused
  83. (void)use16Outs;
  84. #endif
  85. }
  86. CarlaPlugin* CarlaPlugin::newFileSFZ(const Initializer& init)
  87. {
  88. carla_debug("CarlaPlugin::newFileSFZ({%p, \"%s\", \"%s\", \"%s\"})", init.engine, init.filename, init.name, init.label);
  89. #ifdef WANT_LINUXSAMPLER
  90. return newLinuxSampler(init, "SFZ", false);
  91. #else
  92. init.engine->setLastError("SFZ support not available");
  93. return nullptr;
  94. #endif
  95. }
  96. // -------------------------------------------------------------------
  97. // Constructor and destructor
  98. CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const unsigned int id)
  99. : pData(new CarlaPluginProtectedData(engine, id, this))
  100. {
  101. CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);
  102. CARLA_SAFE_ASSERT(id < engine->getMaxPluginNumber());
  103. carla_debug("CarlaPlugin::CarlaPlugin(%p, %i)", engine, id);
  104. switch (engine->getProccessMode())
  105. {
  106. case ENGINE_PROCESS_MODE_SINGLE_CLIENT:
  107. case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS:
  108. CARLA_SAFE_ASSERT(id < MAX_DEFAULT_PLUGINS);
  109. break;
  110. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  111. CARLA_SAFE_ASSERT(id < MAX_RACK_PLUGINS);
  112. break;
  113. case ENGINE_PROCESS_MODE_PATCHBAY:
  114. CARLA_SAFE_ASSERT(id < MAX_PATCHBAY_PLUGINS);
  115. break;
  116. case ENGINE_PROCESS_MODE_BRIDGE:
  117. CARLA_SAFE_ASSERT(id == 0);
  118. break;
  119. }
  120. }
  121. CarlaPlugin::~CarlaPlugin()
  122. {
  123. carla_debug("CarlaPlugin::~CarlaPlugin()");
  124. delete pData;
  125. }
  126. // -------------------------------------------------------------------
  127. // Information (base)
  128. unsigned int CarlaPlugin::getId() const noexcept
  129. {
  130. return pData->id;
  131. }
  132. unsigned int CarlaPlugin::getHints() const noexcept
  133. {
  134. return pData->hints;
  135. }
  136. unsigned int CarlaPlugin::getOptionsEnabled() const noexcept
  137. {
  138. return pData->options;
  139. }
  140. bool CarlaPlugin::isEnabled() const noexcept
  141. {
  142. return pData->enabled;
  143. }
  144. const char* CarlaPlugin::getName() const noexcept
  145. {
  146. return pData->name;
  147. }
  148. const char* CarlaPlugin::getFilename() const noexcept
  149. {
  150. return pData->filename;
  151. }
  152. const char* CarlaPlugin::getIconName() const noexcept
  153. {
  154. return pData->iconName;
  155. }
  156. PluginCategory CarlaPlugin::getCategory() const noexcept
  157. {
  158. PluginCategory category = PLUGIN_CATEGORY_NONE;
  159. try {
  160. category = getPluginCategoryFromName(pData->name);
  161. } catch(...) {}
  162. return category;
  163. }
  164. int64_t CarlaPlugin::getUniqueId() const noexcept
  165. {
  166. return 0;
  167. }
  168. uint32_t CarlaPlugin::getLatencyInFrames() const noexcept
  169. {
  170. return pData->latency;
  171. }
  172. // -------------------------------------------------------------------
  173. // Information (count)
  174. uint32_t CarlaPlugin::getAudioInCount() const noexcept
  175. {
  176. return pData->audioIn.count;
  177. }
  178. uint32_t CarlaPlugin::getAudioOutCount() const noexcept
  179. {
  180. return pData->audioOut.count;
  181. }
  182. uint32_t CarlaPlugin::getMidiInCount() const noexcept
  183. {
  184. return (pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_IN) ? 1 : 0;
  185. }
  186. uint32_t CarlaPlugin::getMidiOutCount() const noexcept
  187. {
  188. return (pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_OUT) ? 1 : 0;
  189. }
  190. uint32_t CarlaPlugin::getParameterCount() const noexcept
  191. {
  192. return pData->param.count;
  193. }
  194. uint32_t CarlaPlugin::getParameterScalePointCount(const uint32_t parameterId) const noexcept
  195. {
  196. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
  197. return 0;
  198. }
  199. uint32_t CarlaPlugin::getProgramCount() const noexcept
  200. {
  201. return pData->prog.count;
  202. }
  203. uint32_t CarlaPlugin::getMidiProgramCount() const noexcept
  204. {
  205. return pData->midiprog.count;
  206. }
  207. uint32_t CarlaPlugin::getCustomDataCount() const noexcept
  208. {
  209. return static_cast<uint32_t>(pData->custom.count());
  210. }
  211. // -------------------------------------------------------------------
  212. // Information (current data)
  213. int32_t CarlaPlugin::getCurrentProgram() const noexcept
  214. {
  215. return pData->prog.current;
  216. }
  217. int32_t CarlaPlugin::getCurrentMidiProgram() const noexcept
  218. {
  219. return pData->midiprog.current;
  220. }
  221. const ParameterData& CarlaPlugin::getParameterData(const uint32_t parameterId) const noexcept
  222. {
  223. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, kParameterDataNull);
  224. return pData->param.data[parameterId];
  225. }
  226. const ParameterRanges& CarlaPlugin::getParameterRanges(const uint32_t parameterId) const noexcept
  227. {
  228. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, kParameterRangesNull);
  229. return pData->param.ranges[parameterId];
  230. }
  231. bool CarlaPlugin::isParameterOutput(const uint32_t parameterId) const noexcept
  232. {
  233. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  234. return (pData->param.data[parameterId].type == PARAMETER_OUTPUT);
  235. }
  236. const MidiProgramData& CarlaPlugin::getMidiProgramData(const uint32_t index) const noexcept
  237. {
  238. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count, kMidiProgramDataNull);
  239. return pData->midiprog.data[index];
  240. }
  241. const CustomData& CarlaPlugin::getCustomData(const uint32_t index) const noexcept
  242. {
  243. CARLA_SAFE_ASSERT_RETURN(index < pData->custom.count(), kCustomDataNull);
  244. return pData->custom.getAt(index);
  245. }
  246. int32_t CarlaPlugin::getChunkData(void** const dataPtr) const noexcept
  247. {
  248. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  249. CARLA_SAFE_ASSERT(false); // this should never happen
  250. return 0;
  251. }
  252. // -------------------------------------------------------------------
  253. // Information (per-plugin data)
  254. unsigned int CarlaPlugin::getOptionsAvailable() const noexcept
  255. {
  256. CARLA_SAFE_ASSERT(false); // this should never happen
  257. return 0x0;
  258. }
  259. float CarlaPlugin::getParameterValue(const uint32_t parameterId) const noexcept
  260. {
  261. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), 0.0f);
  262. CARLA_SAFE_ASSERT(false); // this should never happen
  263. return 0.0f;
  264. }
  265. float CarlaPlugin::getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept
  266. {
  267. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), 0.0f);
  268. CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), 0.0f);
  269. CARLA_SAFE_ASSERT(false); // this should never happen
  270. return 0.0f;
  271. }
  272. void CarlaPlugin::getLabel(char* const strBuf) const noexcept
  273. {
  274. strBuf[0] = '\0';
  275. }
  276. void CarlaPlugin::getMaker(char* const strBuf) const noexcept
  277. {
  278. strBuf[0] = '\0';
  279. }
  280. void CarlaPlugin::getCopyright(char* const strBuf) const noexcept
  281. {
  282. strBuf[0] = '\0';
  283. }
  284. void CarlaPlugin::getRealName(char* const strBuf) const noexcept
  285. {
  286. strBuf[0] = '\0';
  287. }
  288. void CarlaPlugin::getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept
  289. {
  290. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(),);
  291. CARLA_SAFE_ASSERT(false); // this should never happen
  292. strBuf[0] = '\0';
  293. }
  294. void CarlaPlugin::getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept
  295. {
  296. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(),);
  297. strBuf[0] = '\0';
  298. }
  299. void CarlaPlugin::getParameterText(const uint32_t parameterId, char* const strBuf) const noexcept
  300. {
  301. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(),);
  302. CARLA_SAFE_ASSERT(false); // this should never happen
  303. strBuf[0] = '\0';
  304. }
  305. void CarlaPlugin::getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept
  306. {
  307. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(),);
  308. strBuf[0] = '\0';
  309. }
  310. void CarlaPlugin::getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept
  311. {
  312. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(),);
  313. CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId),);
  314. CARLA_SAFE_ASSERT(false); // this should never happen
  315. strBuf[0] = '\0';
  316. }
  317. float CarlaPlugin::getInternalParameterValue(const int32_t parameterId) const noexcept
  318. {
  319. CARLA_SAFE_ASSERT_RETURN(parameterId != PARAMETER_NULL && parameterId > PARAMETER_MAX, 0.0f);
  320. switch (parameterId)
  321. {
  322. case PARAMETER_ACTIVE:
  323. return pData->active;
  324. case PARAMETER_CTRL_CHANNEL:
  325. return pData->ctrlChannel;
  326. #ifndef BUILD_BRIDGE
  327. case PARAMETER_DRYWET:
  328. return pData->postProc.dryWet;
  329. case PARAMETER_VOLUME:
  330. return pData->postProc.volume;
  331. case PARAMETER_BALANCE_LEFT:
  332. return pData->postProc.balanceLeft;
  333. case PARAMETER_BALANCE_RIGHT:
  334. return pData->postProc.balanceRight;
  335. case PARAMETER_PANNING:
  336. return pData->postProc.panning;
  337. #endif
  338. };
  339. CARLA_SAFE_ASSERT_RETURN(parameterId >= 0, 0.0f);
  340. return getParameterValue(static_cast<uint32_t>(parameterId));
  341. }
  342. void CarlaPlugin::getProgramName(const uint32_t index, char* const strBuf) const noexcept
  343. {
  344. CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,);
  345. CARLA_SAFE_ASSERT_RETURN(pData->prog.names[index] != nullptr,);
  346. std::strncpy(strBuf, pData->prog.names[index], STR_MAX);
  347. }
  348. void CarlaPlugin::getMidiProgramName(const uint32_t index, char* const strBuf) const noexcept
  349. {
  350. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  351. CARLA_SAFE_ASSERT_RETURN(pData->midiprog.data[index].name != nullptr,);
  352. std::strncpy(strBuf, pData->midiprog.data[index].name, STR_MAX);
  353. }
  354. void CarlaPlugin::getParameterCountInfo(uint32_t& ins, uint32_t& outs) const noexcept
  355. {
  356. ins = 0;
  357. outs = 0;
  358. for (uint32_t i=0; i < pData->param.count; ++i)
  359. {
  360. if (pData->param.data[i].type == PARAMETER_INPUT)
  361. ++ins;
  362. else if (pData->param.data[i].type == PARAMETER_OUTPUT)
  363. ++outs;
  364. }
  365. }
  366. // -------------------------------------------------------------------
  367. // Set data (state)
  368. void CarlaPlugin::prepareForSave()
  369. {
  370. }
  371. void CarlaPlugin::resetParameters() noexcept
  372. {
  373. for (uint i=0; i < pData->param.count; ++i)
  374. {
  375. const ParameterData& paramData(pData->param.data[i]);
  376. const ParameterRanges& paramRanges(pData->param.ranges[i]);
  377. if (paramData.type != PARAMETER_INPUT)
  378. continue;
  379. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  380. continue;
  381. setParameterValue(i, paramRanges.def, true, true, true);
  382. }
  383. }
  384. void CarlaPlugin::randomizeParameters() noexcept
  385. {
  386. float value, random;
  387. char strBuf[STR_MAX+1];
  388. strBuf[STR_MAX] = '\0';
  389. std::srand(static_cast<uint>(std::time(nullptr)));
  390. for (uint i=0; i < pData->param.count; ++i)
  391. {
  392. const ParameterData& paramData(pData->param.data[i]);
  393. if (paramData.type != PARAMETER_INPUT)
  394. continue;
  395. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  396. continue;
  397. getParameterName(i, strBuf);
  398. if (std::strstr(strBuf, "olume") != nullptr)
  399. continue;
  400. if (std::strstr(strBuf, "Master") != nullptr)
  401. continue;
  402. const ParameterRanges& paramRanges(pData->param.ranges[i]);
  403. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  404. {
  405. random = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
  406. value = random > 0.5 ? paramRanges.max : paramRanges.min;
  407. }
  408. else
  409. {
  410. random = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
  411. value = random * (paramRanges.max - paramRanges.min) + paramRanges.min;
  412. if (paramData.hints & PARAMETER_IS_INTEGER)
  413. value = std::rint(value);
  414. }
  415. setParameterValue(i, value, true, true, true);
  416. }
  417. }
  418. const SaveState& CarlaPlugin::getSaveState()
  419. {
  420. pData->saveState.reset();
  421. prepareForSave();
  422. char strBuf[STR_MAX+1];
  423. // ---------------------------------------------------------------
  424. // Basic info
  425. getLabel(strBuf);
  426. pData->saveState.type = carla_strdup(getPluginTypeAsString(getType()));
  427. pData->saveState.name = carla_strdup(pData->name);
  428. pData->saveState.label = carla_strdup(strBuf);
  429. pData->saveState.binary = carla_strdup(pData->filename);
  430. pData->saveState.uniqueId = getUniqueId();
  431. // ---------------------------------------------------------------
  432. // Internals
  433. pData->saveState.active = pData->active;
  434. #ifndef BUILD_BRIDGE
  435. pData->saveState.dryWet = pData->postProc.dryWet;
  436. pData->saveState.volume = pData->postProc.volume;
  437. pData->saveState.balanceLeft = pData->postProc.balanceLeft;
  438. pData->saveState.balanceRight = pData->postProc.balanceRight;
  439. pData->saveState.panning = pData->postProc.panning;
  440. pData->saveState.ctrlChannel = pData->ctrlChannel;
  441. #endif
  442. // ---------------------------------------------------------------
  443. // Chunk
  444. if (pData->options & PLUGIN_OPTION_USE_CHUNKS)
  445. {
  446. void* data = nullptr;
  447. const int32_t dataSize(getChunkData(&data));
  448. if (data != nullptr && dataSize > 0)
  449. {
  450. pData->saveState.chunk = carla_strdup(QByteArray((char*)data, dataSize).toBase64().constData());
  451. // Don't save anything else if using chunks
  452. return pData->saveState;
  453. }
  454. }
  455. // ---------------------------------------------------------------
  456. // Current Program
  457. if (pData->prog.current >= 0 && getType() != PLUGIN_LV2)
  458. {
  459. pData->saveState.currentProgramIndex = pData->prog.current;
  460. pData->saveState.currentProgramName = carla_strdup(pData->prog.names[pData->prog.current]);
  461. }
  462. // ---------------------------------------------------------------
  463. // Current MIDI Program
  464. if (pData->midiprog.current >= 0 && getType() != PLUGIN_LV2)
  465. {
  466. const MidiProgramData& mpData(pData->midiprog.getCurrent());
  467. pData->saveState.currentMidiBank = static_cast<int32_t>(mpData.bank);
  468. pData->saveState.currentMidiProgram = static_cast<int32_t>(mpData.program);
  469. }
  470. // ---------------------------------------------------------------
  471. // Parameters
  472. const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
  473. for (uint32_t i=0; i < pData->param.count; ++i)
  474. {
  475. const ParameterData& paramData(pData->param.data[i]);
  476. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  477. continue;
  478. StateParameter* const stateParameter(new StateParameter());
  479. stateParameter->isInput = (paramData.type == PARAMETER_INPUT);
  480. stateParameter->index = paramData.index;
  481. stateParameter->midiCC = paramData.midiCC;
  482. stateParameter->midiChannel = paramData.midiChannel;
  483. getParameterName(i, strBuf);
  484. stateParameter->name = carla_strdup(strBuf);
  485. getParameterSymbol(i, strBuf);
  486. stateParameter->symbol = carla_strdup(strBuf);;
  487. stateParameter->value = getParameterValue(i);
  488. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  489. stateParameter->value /= sampleRate;
  490. pData->saveState.parameters.append(stateParameter);
  491. }
  492. // ---------------------------------------------------------------
  493. // Custom Data
  494. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next())
  495. {
  496. const CustomData& cData(it.getValue());
  497. StateCustomData* stateCustomData(new StateCustomData());
  498. stateCustomData->type = carla_strdup(cData.type);
  499. stateCustomData->key = carla_strdup(cData.key);
  500. stateCustomData->value = carla_strdup(cData.value);
  501. pData->saveState.customData.append(stateCustomData);
  502. }
  503. return pData->saveState;
  504. }
  505. void CarlaPlugin::loadSaveState(const SaveState& saveState)
  506. {
  507. char strBuf[STR_MAX+1];
  508. const bool usesMultiProgs(pData->extraHints & PLUGIN_EXTRA_HINT_USES_MULTI_PROGS);
  509. gIsLoadingProject = true;
  510. ScopedValueSetter<bool>(gIsLoadingProject, false);
  511. // ---------------------------------------------------------------
  512. // Part 1 - PRE-set custom data (only that which reload programs)
  513. for (LinkedList<StateCustomData*>::Itenerator it = saveState.customData.begin(); it.valid(); it.next())
  514. {
  515. const StateCustomData* const stateCustomData(it.getValue());
  516. const char* const key(stateCustomData->key);
  517. bool wantData = false;
  518. if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
  519. wantData = true;
  520. else if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
  521. wantData = true;
  522. if (wantData)
  523. setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true);
  524. }
  525. // ---------------------------------------------------------------
  526. // Part 2 - set program
  527. if (saveState.currentProgramIndex >= 0 && saveState.currentProgramName != nullptr)
  528. {
  529. int32_t programId = -1;
  530. // index < count
  531. if (saveState.currentProgramIndex < static_cast<int32_t>(pData->prog.count))
  532. {
  533. programId = saveState.currentProgramIndex;
  534. }
  535. // index not valid, try to find by name
  536. else
  537. {
  538. for (uint32_t i=0; i < pData->prog.count; ++i)
  539. {
  540. strBuf[0] = '\0';
  541. getProgramName(i, strBuf);
  542. if (strBuf[0] != '\0' && std::strcmp(saveState.currentProgramName, strBuf) == 0)
  543. {
  544. programId = static_cast<int32_t>(i);
  545. break;
  546. }
  547. }
  548. }
  549. // set program now, if valid
  550. if (programId >= 0)
  551. setProgram(programId, true, true, true);
  552. }
  553. // ---------------------------------------------------------------
  554. // Part 3 - set midi program
  555. if (saveState.currentMidiBank >= 0 && saveState.currentMidiProgram >= 0 && ! usesMultiProgs)
  556. setMidiProgramById(static_cast<uint32_t>(saveState.currentMidiBank), static_cast<uint32_t>(saveState.currentMidiProgram), true, true, true);
  557. // ---------------------------------------------------------------
  558. // Part 4a - get plugin parameter symbols
  559. LinkedList<ParamSymbol*> paramSymbols;
  560. if (getType() == PLUGIN_LADSPA || getType() == PLUGIN_LV2)
  561. {
  562. for (uint32_t i=0; i < pData->param.count; ++i)
  563. {
  564. strBuf[0] = '\0';
  565. getParameterSymbol(i, strBuf);
  566. if (strBuf[0] != '\0')
  567. {
  568. ParamSymbol* const paramSymbol(new ParamSymbol(i, strBuf));
  569. paramSymbols.append(paramSymbol);
  570. }
  571. }
  572. }
  573. // ---------------------------------------------------------------
  574. // Part 4b - set parameter values (carefully)
  575. const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
  576. for (LinkedList<StateParameter*>::Itenerator it = saveState.parameters.begin(); it.valid(); it.next())
  577. {
  578. StateParameter* const stateParameter(it.getValue());
  579. int32_t index = -1;
  580. if (getType() == PLUGIN_LADSPA)
  581. {
  582. // Try to set by symbol, otherwise use index
  583. if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
  584. {
  585. for (LinkedList<ParamSymbol*>::Itenerator it2 = paramSymbols.begin(); it2.valid(); it2.next())
  586. {
  587. ParamSymbol* const paramSymbol(it2.getValue());
  588. if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0)
  589. {
  590. index = paramSymbol->index;
  591. break;
  592. }
  593. }
  594. if (index == -1)
  595. index = stateParameter->index;
  596. }
  597. else
  598. index = stateParameter->index;
  599. }
  600. else if (getType() == PLUGIN_LV2)
  601. {
  602. // Symbol only
  603. if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
  604. {
  605. for (LinkedList<ParamSymbol*>::Itenerator it2 = paramSymbols.begin(); it2.valid(); it2.next())
  606. {
  607. ParamSymbol* const paramSymbol(it2.getValue());
  608. if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0)
  609. {
  610. index = paramSymbol->index;
  611. break;
  612. }
  613. }
  614. if (index == -1)
  615. carla_stderr("Failed to find LV2 parameter symbol '%s')", stateParameter->symbol);
  616. }
  617. else
  618. carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name);
  619. }
  620. else
  621. {
  622. // Index only
  623. index = stateParameter->index;
  624. }
  625. // Now set parameter
  626. if (index >= 0 && index < static_cast<int32_t>(pData->param.count))
  627. {
  628. //CARLA_SAFE_ASSERT(stateParameter->isInput == (pData
  629. if (stateParameter->isInput)
  630. {
  631. if (pData->param.data[index].hints & PARAMETER_USES_SAMPLERATE)
  632. stateParameter->value *= sampleRate;
  633. setParameterValue(static_cast<uint32_t>(index), stateParameter->value, true, true, true);
  634. }
  635. #ifndef BUILD_BRIDGE
  636. setParameterMidiCC(static_cast<uint32_t>(index), stateParameter->midiCC, true, true);
  637. setParameterMidiChannel(static_cast<uint32_t>(index), stateParameter->midiChannel, true, true);
  638. #endif
  639. }
  640. else
  641. carla_stderr("Could not set parameter data for '%s'", stateParameter->name);
  642. }
  643. // ---------------------------------------------------------------
  644. // Part 4c - clear
  645. for (LinkedList<ParamSymbol*>::Itenerator it = paramSymbols.begin(); it.valid(); it.next())
  646. {
  647. ParamSymbol* const paramSymbol(it.getValue());
  648. delete paramSymbol;
  649. }
  650. paramSymbols.clear();
  651. // ---------------------------------------------------------------
  652. // Part 5 - set custom data
  653. for (LinkedList<StateCustomData*>::Itenerator it = saveState.customData.begin(); it.valid(); it.next())
  654. {
  655. const StateCustomData* const stateCustomData(it.getValue());
  656. const char* const key(stateCustomData->key);
  657. if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
  658. continue;
  659. if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
  660. continue;
  661. setCustomData(stateCustomData->type, stateCustomData->key, stateCustomData->value, true);
  662. }
  663. // ---------------------------------------------------------------
  664. // Part 5x - set lv2 state
  665. if (getType() == PLUGIN_LV2 && pData->custom.count() > 0)
  666. setCustomData(CUSTOM_DATA_TYPE_STRING, "CarlaLoadLv2StateNow", "true", true);
  667. // ---------------------------------------------------------------
  668. // Part 6 - set chunk
  669. if (saveState.chunk != nullptr && (pData->options & PLUGIN_OPTION_USE_CHUNKS) != 0)
  670. setChunkData(saveState.chunk);
  671. // ---------------------------------------------------------------
  672. // Part 6 - set internal stuff
  673. #ifndef BUILD_BRIDGE
  674. setDryWet(saveState.dryWet, true, true);
  675. setVolume(saveState.volume, true, true);
  676. setBalanceLeft(saveState.balanceLeft, true, true);
  677. setBalanceRight(saveState.balanceRight, true, true);
  678. setPanning(saveState.panning, true, true);
  679. setCtrlChannel(saveState.ctrlChannel, true, true);
  680. #endif
  681. setActive(saveState.active, true, true);
  682. }
  683. bool CarlaPlugin::saveStateToFile(const char* const filename)
  684. {
  685. CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
  686. carla_debug("CarlaPlugin::saveStateToFile(\"%s\")", filename);
  687. QFile file(filename);
  688. if (! file.open(QIODevice::WriteOnly | QIODevice::Text))
  689. return false;
  690. QString content;
  691. fillXmlStringFromSaveState(content, getSaveState());
  692. QTextStream out(&file);
  693. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  694. out << "<!DOCTYPE CARLA-PRESET>\n";
  695. out << "<CARLA-PRESET VERSION='2.0'>\n";
  696. out << content;
  697. out << "</CARLA-PRESET>\n";
  698. file.close();
  699. return true;
  700. }
  701. bool CarlaPlugin::loadStateFromFile(const char* const filename)
  702. {
  703. CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
  704. carla_debug("CarlaPlugin::loadStateFromFile(\"%s\")", filename);
  705. QFile file(filename);
  706. if (! file.open(QIODevice::ReadOnly | QIODevice::Text))
  707. return false;
  708. QDomDocument xml;
  709. xml.setContent(file.readAll());
  710. file.close();
  711. QDomNode xmlNode(xml.documentElement());
  712. if (xmlNode.toElement().tagName().compare("carla-preset", Qt::CaseInsensitive) == 0)
  713. {
  714. pData->engine->setLastError("Not a valid Carla preset file");
  715. return false;
  716. }
  717. pData->saveState.reset();
  718. fillSaveStateFromXmlNode(pData->saveState, xmlNode);
  719. loadSaveState(pData->saveState);
  720. return true;
  721. }
  722. // -------------------------------------------------------------------
  723. // Set data (internal stuff)
  724. void CarlaPlugin::setId(const unsigned int newId) noexcept
  725. {
  726. pData->id = newId;
  727. }
  728. void CarlaPlugin::setName(const char* const newName)
  729. {
  730. CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0',);
  731. if (pData->name != nullptr)
  732. delete[] pData->name;
  733. pData->name = carla_strdup(newName);
  734. }
  735. void CarlaPlugin::setOption(const unsigned int option, const bool yesNo)
  736. {
  737. CARLA_SAFE_ASSERT_RETURN(getOptionsAvailable() & option,);
  738. if (yesNo)
  739. pData->options |= option;
  740. else
  741. pData->options &= ~option;
  742. pData->saveSetting(option, yesNo);
  743. }
  744. void CarlaPlugin::setEnabled(const bool yesNo) noexcept
  745. {
  746. if (pData->enabled == yesNo)
  747. return;
  748. pData->enabled = yesNo;
  749. pData->masterMutex.lock();
  750. pData->masterMutex.unlock();
  751. }
  752. // -------------------------------------------------------------------
  753. // Set data (internal stuff)
  754. void CarlaPlugin::setActive(const bool active, const bool sendOsc, const bool sendCallback) noexcept
  755. {
  756. #ifndef BUILD_BRIDGE
  757. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  758. #endif
  759. if (pData->active == active)
  760. return;
  761. {
  762. const ScopedSingleProcessLocker spl(this, true);
  763. if (active)
  764. activate();
  765. else
  766. deactivate();
  767. }
  768. pData->active = active;
  769. #ifndef BUILD_BRIDGE
  770. const float value(active ? 1.0f : 0.0f);
  771. if (sendOsc && pData->engine->isOscControlRegistered())
  772. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, value);
  773. if (sendCallback)
  774. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, value, nullptr);
  775. #else
  776. return;
  777. // unused
  778. (void)sendOsc;
  779. (void)sendCallback;
  780. #endif
  781. }
  782. #ifndef BUILD_BRIDGE
  783. void CarlaPlugin::setDryWet(const float value, const bool sendOsc, const bool sendCallback) noexcept
  784. {
  785. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f);
  786. const float fixedValue(carla_fixValue<float>(0.0f, 1.0f, value));
  787. if (pData->postProc.dryWet == fixedValue)
  788. return;
  789. pData->postProc.dryWet = fixedValue;
  790. if (sendOsc && pData->engine->isOscControlRegistered())
  791. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_DRYWET, fixedValue);
  792. if (sendCallback)
  793. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_DRYWET, 0, fixedValue, nullptr);
  794. }
  795. void CarlaPlugin::setVolume(const float value, const bool sendOsc, const bool sendCallback) noexcept
  796. {
  797. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.27f);
  798. const float fixedValue(carla_fixValue<float>(0.0f, 1.27f, value));
  799. if (pData->postProc.volume == fixedValue)
  800. return;
  801. pData->postProc.volume = fixedValue;
  802. if (sendOsc && pData->engine->isOscControlRegistered())
  803. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_VOLUME, fixedValue);
  804. if (sendCallback)
  805. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_VOLUME, 0, fixedValue, nullptr);
  806. }
  807. void CarlaPlugin::setBalanceLeft(const float value, const bool sendOsc, const bool sendCallback) noexcept
  808. {
  809. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  810. const float fixedValue(carla_fixValue<float>(-1.0f, 1.0f, value));
  811. if (pData->postProc.balanceLeft == fixedValue)
  812. return;
  813. pData->postProc.balanceLeft = fixedValue;
  814. if (sendOsc && pData->engine->isOscControlRegistered())
  815. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_BALANCE_LEFT, fixedValue);
  816. if (sendCallback)
  817. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_BALANCE_LEFT, 0, fixedValue, nullptr);
  818. }
  819. void CarlaPlugin::setBalanceRight(const float value, const bool sendOsc, const bool sendCallback) noexcept
  820. {
  821. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  822. const float fixedValue(carla_fixValue<float>(-1.0f, 1.0f, value));
  823. if (pData->postProc.balanceRight == fixedValue)
  824. return;
  825. pData->postProc.balanceRight = fixedValue;
  826. if (sendOsc && pData->engine->isOscControlRegistered())
  827. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_BALANCE_RIGHT, fixedValue);
  828. if (sendCallback)
  829. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_BALANCE_RIGHT, 0, fixedValue, nullptr);
  830. }
  831. void CarlaPlugin::setPanning(const float value, const bool sendOsc, const bool sendCallback) noexcept
  832. {
  833. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  834. const float fixedValue(carla_fixValue<float>(-1.0f, 1.0f, value));
  835. if (pData->postProc.panning == fixedValue)
  836. return;
  837. pData->postProc.panning = fixedValue;
  838. if (sendOsc && pData->engine->isOscControlRegistered())
  839. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_PANNING, fixedValue);
  840. if (sendCallback)
  841. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_PANNING, 0, fixedValue, nullptr);
  842. }
  843. #endif
  844. void CarlaPlugin::setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept
  845. {
  846. #ifndef BUILD_BRIDGE
  847. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  848. #endif
  849. CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,);
  850. if (pData->ctrlChannel == channel)
  851. return;
  852. pData->ctrlChannel = channel;
  853. #ifndef BUILD_BRIDGE
  854. const float ctrlf(channel);
  855. if (sendOsc && pData->engine->isOscControlRegistered())
  856. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_CTRL_CHANNEL, ctrlf);
  857. if (sendCallback)
  858. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_CTRL_CHANNEL, 0, ctrlf, nullptr);
  859. if (pData->hints & PLUGIN_IS_BRIDGE)
  860. osc_send_control(pData->osc.data, PARAMETER_CTRL_CHANNEL, ctrlf);
  861. #else
  862. return;
  863. // unused
  864. (void)sendOsc;
  865. (void)sendCallback;
  866. #endif
  867. }
  868. // -------------------------------------------------------------------
  869. // Set data (plugin-specific stuff)
  870. void CarlaPlugin::setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  871. {
  872. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  873. #ifdef BUILD_BRIDGE
  874. if (! gIsLoadingProject)
  875. {
  876. CARLA_ASSERT(! sendGui); // this should never happen
  877. }
  878. #endif
  879. #ifndef BUILD_BRIDGE
  880. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  881. uiParameterChange(parameterId, value);
  882. if (sendOsc && pData->engine->isOscControlRegistered())
  883. pData->engine->oscSend_control_set_parameter_value(pData->id, static_cast<int32_t>(parameterId), value);
  884. #endif
  885. if (sendCallback)
  886. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast<int>(parameterId), 0, value, nullptr);
  887. #ifdef BUILD_BRIDGE
  888. return;
  889. // unused
  890. (void)sendGui;
  891. (void)sendOsc;
  892. #endif
  893. }
  894. void CarlaPlugin::setParameterValueByRealIndex(const int32_t rindex, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  895. {
  896. CARLA_SAFE_ASSERT_RETURN(rindex > PARAMETER_MAX && rindex != PARAMETER_NULL,);
  897. switch (rindex)
  898. {
  899. case PARAMETER_ACTIVE:
  900. return setActive((value > 0.0f), sendOsc, sendCallback);
  901. case PARAMETER_CTRL_CHANNEL:
  902. return setCtrlChannel(int8_t(value), sendOsc, sendCallback);
  903. #ifndef BUILD_BRIDGE
  904. case PARAMETER_DRYWET:
  905. return setDryWet(value, sendOsc, sendCallback);
  906. case PARAMETER_VOLUME:
  907. return setVolume(value, sendOsc, sendCallback);
  908. case PARAMETER_BALANCE_LEFT:
  909. return setBalanceLeft(value, sendOsc, sendCallback);
  910. case PARAMETER_BALANCE_RIGHT:
  911. return setBalanceRight(value, sendOsc, sendCallback);
  912. case PARAMETER_PANNING:
  913. return setPanning(value, sendOsc, sendCallback);
  914. #endif
  915. }
  916. for (uint32_t i=0; i < pData->param.count; ++i)
  917. {
  918. if (pData->param.data[i].rindex == rindex)
  919. {
  920. if (getParameterValue(i) != value)
  921. setParameterValue(i, value, sendGui, sendOsc, sendCallback);
  922. break;
  923. }
  924. }
  925. }
  926. void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept
  927. {
  928. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  929. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  930. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  931. pData->param.data[parameterId].midiChannel = channel;
  932. #ifndef BUILD_BRIDGE
  933. if (sendOsc && pData->engine->isOscControlRegistered())
  934. pData->engine->oscSend_control_set_parameter_midi_channel(pData->id, parameterId, channel);
  935. if (sendCallback)
  936. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED, pData->id, static_cast<int>(parameterId), channel, 0.0f, nullptr);
  937. if (pData->hints & PLUGIN_IS_BRIDGE)
  938. {} // TODO
  939. #else
  940. return;
  941. // unused
  942. (void)sendOsc;
  943. (void)sendCallback;
  944. #endif
  945. }
  946. void CarlaPlugin::setParameterMidiCC(const uint32_t parameterId, int16_t cc, const bool sendOsc, const bool sendCallback) noexcept
  947. {
  948. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  949. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  950. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc <= 0x5F,);
  951. pData->param.data[parameterId].midiCC = cc;
  952. #ifndef BUILD_BRIDGE
  953. if (sendOsc && pData->engine->isOscControlRegistered())
  954. pData->engine->oscSend_control_set_parameter_midi_cc(pData->id, parameterId, cc);
  955. if (sendCallback)
  956. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_MIDI_CC_CHANGED, pData->id, static_cast<int>(parameterId), cc, 0.0f, nullptr);
  957. if (pData->hints & PLUGIN_IS_BRIDGE)
  958. {} // TODO
  959. #else
  960. return;
  961. // unused
  962. (void)sendOsc;
  963. (void)sendCallback;
  964. #endif
  965. }
  966. void CarlaPlugin::setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui)
  967. {
  968. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  969. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  970. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  971. #ifdef BUILD_BRIDGE
  972. if (! gIsLoadingProject) {
  973. CARLA_SAFE_ASSERT_RETURN(! sendGui,); // this should never happen
  974. }
  975. #else
  976. // unused
  977. (void)sendGui;
  978. #endif
  979. bool saveData = true;
  980. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0)
  981. {
  982. // Ignore some keys
  983. if (std::strncmp(key, "OSC:", 4) == 0 || std::strncmp(key, "CarlaAlternateFile", 18) == 0 || std::strcmp(key, "guiVisible") == 0)
  984. saveData = false;
  985. //else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVE_NOW) == 0 || std::strcmp(key, CARLA_BRIDGE_MSG_SET_CHUNK) == 0 || std::strcmp(key, CARLA_BRIDGE_MSG_SET_CUSTOM) == 0)
  986. // saveData = false;
  987. }
  988. if (! saveData)
  989. return;
  990. // Check if we already have this key
  991. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next())
  992. {
  993. CustomData& cData(it.getValue());
  994. CARLA_SAFE_ASSERT_CONTINUE(cData.type != nullptr && cData.type[0] != '\0');
  995. CARLA_SAFE_ASSERT_CONTINUE(cData.key != nullptr && cData.key[0] != '\0');
  996. CARLA_SAFE_ASSERT_CONTINUE(cData.value != nullptr);
  997. if (std::strcmp(cData.key, key) == 0)
  998. {
  999. if (cData.value != nullptr)
  1000. delete[] cData.value;
  1001. cData.value = carla_strdup(value);
  1002. return;
  1003. }
  1004. }
  1005. // Otherwise store it
  1006. CustomData newData;
  1007. newData.type = carla_strdup(type);
  1008. newData.key = carla_strdup(key);
  1009. newData.value = carla_strdup(value);
  1010. pData->custom.append(newData);
  1011. }
  1012. void CarlaPlugin::setChunkData(const char* const stringData)
  1013. {
  1014. CARLA_SAFE_ASSERT_RETURN(stringData != nullptr && stringData[0] != '\0',);
  1015. CARLA_SAFE_ASSERT(false); // this should never happen
  1016. }
  1017. void CarlaPlugin::setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  1018. {
  1019. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  1020. #ifdef BUILD_BRIDGE
  1021. if (! gIsLoadingProject) {
  1022. CARLA_ASSERT(! sendGui); // this should never happen
  1023. }
  1024. #endif
  1025. pData->prog.current = index;
  1026. #ifndef BUILD_BRIDGE
  1027. const bool reallySendOsc(sendOsc && pData->engine->isOscControlRegistered());
  1028. if (reallySendOsc)
  1029. pData->engine->oscSend_control_set_current_program(pData->id, index);
  1030. #endif
  1031. if (sendCallback)
  1032. pData->engine->callback(ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr);
  1033. // Change default parameter values
  1034. if (index >= 0)
  1035. {
  1036. #ifndef BUILD_BRIDGE
  1037. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1038. uiProgramChange(static_cast<uint32_t>(index));
  1039. #endif
  1040. if (getType() == PLUGIN_FILE_CSD || getType() == PLUGIN_FILE_GIG || getType() == PLUGIN_FILE_SF2 || getType() == PLUGIN_FILE_SFZ)
  1041. return;
  1042. for (uint32_t i=0; i < pData->param.count; ++i)
  1043. {
  1044. const float value(pData->param.ranges[i].getFixedValue(getParameterValue(i)));
  1045. pData->param.ranges[i].def = value;
  1046. #ifndef BUILD_BRIDGE
  1047. if (reallySendOsc)
  1048. {
  1049. pData->engine->oscSend_control_set_parameter_value(pData->id, static_cast<int32_t>(i), value);
  1050. pData->engine->oscSend_control_set_default_value(pData->id, i, value);
  1051. }
  1052. #endif
  1053. if (sendCallback)
  1054. {
  1055. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast<int>(i), 0, value, nullptr);
  1056. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, pData->id, static_cast<int>(i), 0, value, nullptr);
  1057. }
  1058. }
  1059. }
  1060. #ifdef BUILD_BRIDGE
  1061. return;
  1062. // unused
  1063. (void)sendGui;
  1064. (void)sendOsc;
  1065. #endif
  1066. }
  1067. void CarlaPlugin::setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  1068. {
  1069. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  1070. #ifdef BUILD_BRIDGE
  1071. if (! gIsLoadingProject) {
  1072. CARLA_ASSERT(! sendGui); // this should never happen
  1073. }
  1074. #endif
  1075. pData->midiprog.current = index;
  1076. #ifndef BUILD_BRIDGE
  1077. const bool reallySendOsc(sendOsc && pData->engine->isOscControlRegistered());
  1078. if (reallySendOsc)
  1079. pData->engine->oscSend_control_set_current_midi_program(pData->id, index);
  1080. #endif
  1081. if (sendCallback)
  1082. pData->engine->callback(ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr);
  1083. if (index >= 0)
  1084. {
  1085. #ifndef BUILD_BRIDGE
  1086. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1087. uiMidiProgramChange(static_cast<uint32_t>(index));
  1088. #endif
  1089. if (getType() == PLUGIN_FILE_CSD || getType() == PLUGIN_FILE_GIG || getType() == PLUGIN_FILE_SF2 || getType() == PLUGIN_FILE_SFZ)
  1090. return;
  1091. for (uint32_t i=0; i < pData->param.count; ++i)
  1092. {
  1093. const float value(pData->param.ranges[i].getFixedValue(getParameterValue(i)));
  1094. pData->param.ranges[i].def = value;
  1095. #ifndef BUILD_BRIDGE
  1096. if (reallySendOsc)
  1097. {
  1098. pData->engine->oscSend_control_set_parameter_value(pData->id, static_cast<int32_t>(i), value);
  1099. pData->engine->oscSend_control_set_default_value(pData->id, i, value);
  1100. }
  1101. #endif
  1102. if (sendCallback)
  1103. {
  1104. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast<int>(i), 0, value, nullptr);
  1105. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, pData->id, static_cast<int>(i), 0, value, nullptr);
  1106. }
  1107. }
  1108. }
  1109. #ifdef BUILD_BRIDGE
  1110. return;
  1111. // unused
  1112. (void)sendGui;
  1113. (void)sendOsc;
  1114. #endif
  1115. }
  1116. void CarlaPlugin::setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  1117. {
  1118. for (uint32_t i=0; i < pData->midiprog.count; ++i)
  1119. {
  1120. if (pData->midiprog.data[i].bank == bank && pData->midiprog.data[i].program == program)
  1121. return setMidiProgram(static_cast<int32_t>(i), sendGui, sendOsc, sendCallback);
  1122. }
  1123. }
  1124. // -------------------------------------------------------------------
  1125. // Set ui stuff
  1126. void CarlaPlugin::idle()
  1127. {
  1128. if (! pData->enabled)
  1129. return;
  1130. if (pData->hints & PLUGIN_NEEDS_SINGLE_THREAD)
  1131. {
  1132. // Process postponed events
  1133. postRtEventsRun();
  1134. // Update parameter outputs
  1135. for (uint32_t i=0; i < pData->param.count; ++i)
  1136. {
  1137. if (pData->param.data[i].type == PARAMETER_OUTPUT)
  1138. uiParameterChange(i, getParameterValue(i));
  1139. }
  1140. }
  1141. if (pData->transientTryCounter == 0)
  1142. return;
  1143. if (++pData->transientTryCounter % 10 != 0)
  1144. return;
  1145. if (pData->transientTryCounter >= 200)
  1146. return;
  1147. carla_stdout("Trying to get window...");
  1148. QString uiTitle(QString("%1 (GUI)").arg(pData->name));
  1149. if (CarlaPluginUi::tryTransientWinIdMatch(pData->osc.data.target != nullptr ? pData->osc.thread.getPid() : 0, uiTitle.toUtf8().constData(), pData->engine->getOptions().frontendWinId))
  1150. pData->transientTryCounter = 0;
  1151. }
  1152. void CarlaPlugin::showCustomUI(const bool yesNo)
  1153. {
  1154. CARLA_SAFE_ASSERT(false);
  1155. return;
  1156. // unused
  1157. (void)yesNo;
  1158. }
  1159. // -------------------------------------------------------------------
  1160. // Plugin state
  1161. void CarlaPlugin::reloadPrograms(const bool)
  1162. {
  1163. }
  1164. // -------------------------------------------------------------------
  1165. // Plugin processing
  1166. void CarlaPlugin::activate() noexcept
  1167. {
  1168. CARLA_SAFE_ASSERT(! pData->active);
  1169. }
  1170. void CarlaPlugin::deactivate() noexcept
  1171. {
  1172. CARLA_SAFE_ASSERT(pData->active);
  1173. }
  1174. void CarlaPlugin::bufferSizeChanged(const uint32_t)
  1175. {
  1176. }
  1177. void CarlaPlugin::sampleRateChanged(const double)
  1178. {
  1179. }
  1180. void CarlaPlugin::offlineModeChanged(const bool)
  1181. {
  1182. }
  1183. bool CarlaPlugin::tryLock(const bool forcedOffline) noexcept
  1184. {
  1185. if (forcedOffline)
  1186. {
  1187. pData->masterMutex.lock();
  1188. return true;
  1189. }
  1190. return pData->masterMutex.tryLock();
  1191. }
  1192. void CarlaPlugin::unlock() noexcept
  1193. {
  1194. pData->masterMutex.unlock();
  1195. }
  1196. // -------------------------------------------------------------------
  1197. // Plugin buffers
  1198. void CarlaPlugin::initBuffers()
  1199. {
  1200. pData->audioIn.initBuffers();
  1201. pData->audioOut.initBuffers();
  1202. pData->event.initBuffers();
  1203. }
  1204. void CarlaPlugin::clearBuffers()
  1205. {
  1206. pData->clearBuffers();
  1207. }
  1208. // -------------------------------------------------------------------
  1209. // OSC stuff
  1210. void CarlaPlugin::registerToOscClient() noexcept
  1211. {
  1212. #ifdef BUILD_BRIDGE
  1213. if (! pData->engine->isOscBridgeRegistered())
  1214. #else
  1215. if (! pData->engine->isOscControlRegistered())
  1216. #endif
  1217. return;
  1218. #ifndef BUILD_BRIDGE
  1219. pData->engine->oscSend_control_add_plugin_start(pData->id, pData->name);
  1220. #endif
  1221. // Base data
  1222. {
  1223. // TODO - clear buf
  1224. char bufName[STR_MAX+1] = { '\0' };
  1225. char bufLabel[STR_MAX+1] = { '\0' };
  1226. char bufMaker[STR_MAX+1] = { '\0' };
  1227. char bufCopyright[STR_MAX+1] = { '\0' };
  1228. getRealName(bufName);
  1229. getLabel(bufLabel);
  1230. getMaker(bufMaker);
  1231. getCopyright(bufCopyright);
  1232. #ifdef BUILD_BRIDGE
  1233. pData->engine->oscSend_bridge_plugin_info1(getCategory(), pData->hints, getUniqueId());
  1234. pData->engine->oscSend_bridge_plugin_info2(bufName, bufLabel, bufMaker, bufCopyright);
  1235. #else
  1236. pData->engine->oscSend_control_set_plugin_info1(pData->id, getType(), getCategory(), pData->hints, getUniqueId());
  1237. pData->engine->oscSend_control_set_plugin_info2(pData->id, bufName, bufLabel, bufMaker, bufCopyright);
  1238. #endif
  1239. }
  1240. // Base count
  1241. {
  1242. uint32_t paramIns, paramOuts;
  1243. getParameterCountInfo(paramIns, paramOuts);
  1244. #ifdef BUILD_BRIDGE
  1245. pData->engine->oscSend_bridge_audio_count(getAudioInCount(), getAudioOutCount());
  1246. pData->engine->oscSend_bridge_midi_count(getMidiInCount(), getMidiOutCount());
  1247. pData->engine->oscSend_bridge_parameter_count(paramIns, paramOuts);
  1248. #else
  1249. pData->engine->oscSend_control_set_audio_count(pData->id, getAudioInCount(), getAudioOutCount());
  1250. pData->engine->oscSend_control_set_midi_count(pData->id, getMidiInCount(), getMidiOutCount());
  1251. pData->engine->oscSend_control_set_parameter_count(pData->id, paramIns, paramOuts);
  1252. #endif
  1253. }
  1254. // Plugin Parameters
  1255. if (pData->param.count > 0 && pData->param.count < pData->engine->getOptions().maxParameters)
  1256. {
  1257. char bufName[STR_MAX+1], bufUnit[STR_MAX+1];
  1258. for (uint32_t i=0; i < pData->param.count; ++i)
  1259. {
  1260. carla_fill<char>(bufName, STR_MAX, '\0');
  1261. carla_fill<char>(bufUnit, STR_MAX, '\0');
  1262. getParameterName(i, bufName);
  1263. getParameterUnit(i, bufUnit);
  1264. const ParameterData& paramData(pData->param.data[i]);
  1265. const ParameterRanges& paramRanges(pData->param.ranges[i]);
  1266. #ifdef BUILD_BRIDGE
  1267. pData->engine->oscSend_bridge_parameter_data(i, paramData.rindex, paramData.type, paramData.hints, bufName, bufUnit);
  1268. pData->engine->oscSend_bridge_parameter_ranges1(i, paramRanges.def, paramRanges.min, paramRanges.max);
  1269. pData->engine->oscSend_bridge_parameter_ranges2(i, paramRanges.step, paramRanges.stepSmall, paramRanges.stepLarge);
  1270. pData->engine->oscSend_bridge_parameter_value(i, getParameterValue(i));
  1271. pData->engine->oscSend_bridge_parameter_midi_cc(i, paramData.midiCC);
  1272. pData->engine->oscSend_bridge_parameter_midi_channel(i, paramData.midiChannel);
  1273. #else
  1274. pData->engine->oscSend_control_set_parameter_data(pData->id, i, paramData.type, paramData.hints, bufName, bufUnit);
  1275. pData->engine->oscSend_control_set_parameter_ranges1(pData->id, i, paramRanges.def, paramRanges.min, paramRanges.max);
  1276. pData->engine->oscSend_control_set_parameter_ranges2(pData->id, i, paramRanges.step, paramRanges.stepSmall, paramRanges.stepLarge);
  1277. pData->engine->oscSend_control_set_parameter_value(pData->id, static_cast<int32_t>(i), getParameterValue(i));
  1278. pData->engine->oscSend_control_set_parameter_midi_cc(pData->id, i, paramData.midiCC);
  1279. pData->engine->oscSend_control_set_parameter_midi_channel(pData->id, i, paramData.midiChannel);
  1280. #endif
  1281. }
  1282. }
  1283. // Programs
  1284. if (pData->prog.count > 0)
  1285. {
  1286. #ifdef BUILD_BRIDGE
  1287. pData->engine->oscSend_bridge_program_count(pData->prog.count);
  1288. for (uint32_t i=0; i < pData->prog.count; ++i)
  1289. pData->engine->oscSend_bridge_program_name(i, pData->prog.names[i]);
  1290. pData->engine->oscSend_bridge_current_program(pData->prog.current);
  1291. #else
  1292. pData->engine->oscSend_control_set_program_count(pData->id, pData->prog.count);
  1293. for (uint32_t i=0; i < pData->prog.count; ++i)
  1294. pData->engine->oscSend_control_set_program_name(pData->id, i, pData->prog.names[i]);
  1295. pData->engine->oscSend_control_set_current_program(pData->id, pData->prog.current);
  1296. #endif
  1297. }
  1298. // MIDI Programs
  1299. if (pData->midiprog.count > 0)
  1300. {
  1301. #ifdef BUILD_BRIDGE
  1302. pData->engine->oscSend_bridge_midi_program_count(pData->midiprog.count);
  1303. for (uint32_t i=0; i < pData->midiprog.count; ++i)
  1304. {
  1305. const MidiProgramData& mpData(pData->midiprog.data[i]);
  1306. pData->engine->oscSend_bridge_midi_program_data(i, mpData.bank, mpData.program, mpData.name);
  1307. }
  1308. pData->engine->oscSend_bridge_current_midi_program(pData->midiprog.current);
  1309. #else
  1310. pData->engine->oscSend_control_set_midi_program_count(pData->id, pData->midiprog.count);
  1311. for (uint32_t i=0; i < pData->midiprog.count; ++i)
  1312. {
  1313. const MidiProgramData& mpData(pData->midiprog.data[i]);
  1314. pData->engine->oscSend_control_set_midi_program_data(pData->id, i, mpData.bank, mpData.program, mpData.name);
  1315. }
  1316. pData->engine->oscSend_control_set_current_midi_program(pData->id, pData->midiprog.current);
  1317. #endif
  1318. }
  1319. #ifndef BUILD_BRIDGE
  1320. pData->engine->oscSend_control_add_plugin_end(pData->id);
  1321. // Internal Parameters
  1322. {
  1323. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_DRYWET, pData->postProc.dryWet);
  1324. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_VOLUME, pData->postProc.volume);
  1325. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_BALANCE_LEFT, pData->postProc.balanceLeft);
  1326. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_BALANCE_RIGHT, pData->postProc.balanceRight);
  1327. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_PANNING, pData->postProc.panning);
  1328. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_CTRL_CHANNEL, pData->ctrlChannel);
  1329. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, pData->active ? 1.0f : 0.0f);
  1330. }
  1331. #endif
  1332. }
  1333. void CarlaPlugin::updateOscData(const lo_address& source, const char* const url)
  1334. {
  1335. // FIXME - remove debug prints later
  1336. carla_stdout("CarlaPlugin::updateOscData(%p, \"%s\")", source, url);
  1337. pData->osc.data.free();
  1338. const int proto = lo_address_get_protocol(source);
  1339. {
  1340. const char* host = lo_address_get_hostname(source);
  1341. const char* port = lo_address_get_port(source);
  1342. pData->osc.data.source = lo_address_new_with_proto(proto, host, port);
  1343. carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port);
  1344. }
  1345. {
  1346. char* host = lo_url_get_hostname(url);
  1347. char* port = lo_url_get_port(url);
  1348. pData->osc.data.path = carla_strdup_free(lo_url_get_path(url));
  1349. pData->osc.data.target = lo_address_new_with_proto(proto, host, port);
  1350. carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, pData->osc.data.path);
  1351. std::free(host);
  1352. std::free(port);
  1353. }
  1354. #ifndef BUILD_BRIDGE
  1355. if (pData->hints & PLUGIN_IS_BRIDGE)
  1356. {
  1357. carla_stdout("CarlaPlugin::updateOscData() - done");
  1358. return;
  1359. }
  1360. #endif
  1361. osc_send_sample_rate(pData->osc.data, static_cast<float>(pData->engine->getSampleRate()));
  1362. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next())
  1363. {
  1364. const CustomData& cData(it.getValue());
  1365. CARLA_SAFE_ASSERT_CONTINUE(cData.type != nullptr && cData.type[0] != '\0');
  1366. CARLA_SAFE_ASSERT_CONTINUE(cData.key != nullptr && cData.key[0] != '\0');
  1367. CARLA_SAFE_ASSERT_CONTINUE(cData.value != nullptr);
  1368. if (std::strcmp(cData.type, CUSTOM_DATA_TYPE_STRING) == 0)
  1369. osc_send_configure(pData->osc.data, cData.key, cData.value);
  1370. }
  1371. if (pData->prog.current >= 0)
  1372. osc_send_program(pData->osc.data, static_cast<uint32_t>(pData->prog.current));
  1373. if (pData->midiprog.current >= 0)
  1374. {
  1375. const MidiProgramData& curMidiProg(pData->midiprog.getCurrent());
  1376. if (getType() == PLUGIN_DSSI)
  1377. osc_send_program(pData->osc.data, curMidiProg.bank, curMidiProg.program);
  1378. else
  1379. osc_send_midi_program(pData->osc.data, curMidiProg.bank, curMidiProg.program);
  1380. }
  1381. for (uint32_t i=0; i < pData->param.count; ++i)
  1382. osc_send_control(pData->osc.data, pData->param.data[i].rindex, getParameterValue(i));
  1383. if ((pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0 && pData->engine->getOptions().frontendWinId != 0)
  1384. pData->transientTryCounter = 1;
  1385. carla_stdout("CarlaPlugin::updateOscData() - done");
  1386. }
  1387. // void CarlaPlugin::freeOscData()
  1388. // {
  1389. // pData->osc.data.free();
  1390. // }
  1391. bool CarlaPlugin::waitForOscGuiShow()
  1392. {
  1393. carla_stdout("CarlaPlugin::waitForOscGuiShow()");
  1394. uint i=0, oscUiTimeout = pData->engine->getOptions().uiBridgesTimeout;
  1395. // wait for UI 'update' call
  1396. for (; i < oscUiTimeout/100; ++i)
  1397. {
  1398. if (pData->osc.data.target != nullptr)
  1399. {
  1400. carla_stdout("CarlaPlugin::waitForOscGuiShow() - got response, asking UI to show itself now");
  1401. osc_send_show(pData->osc.data);
  1402. return true;
  1403. }
  1404. if (pData->osc.thread.isThreadRunning())
  1405. carla_msleep(100);
  1406. else
  1407. return false;
  1408. }
  1409. carla_stdout("CarlaPlugin::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", oscUiTimeout);
  1410. return false;
  1411. }
  1412. // -------------------------------------------------------------------
  1413. // MIDI events
  1414. #ifndef BUILD_BRIDGE
  1415. void CarlaPlugin::sendMidiSingleNote(const uint8_t channel, const uint8_t note, const uint8_t velo, const bool sendGui, const bool sendOsc, const bool sendCallback)
  1416. {
  1417. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1418. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1419. CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,);
  1420. if (! pData->active)
  1421. return;
  1422. ExternalMidiNote extNote;
  1423. extNote.channel = static_cast<int8_t>(channel);
  1424. extNote.note = note;
  1425. extNote.velo = velo;
  1426. pData->extNotes.append(extNote);
  1427. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1428. {
  1429. if (velo > 0)
  1430. uiNoteOn(channel, note, velo);
  1431. else
  1432. uiNoteOff(channel, note);
  1433. }
  1434. if (sendOsc && pData->engine->isOscControlRegistered())
  1435. {
  1436. if (velo > 0)
  1437. pData->engine->oscSend_control_note_on(pData->id, channel, note, velo);
  1438. else
  1439. pData->engine->oscSend_control_note_off(pData->id, channel, note);
  1440. }
  1441. if (sendCallback)
  1442. pData->engine->callback((velo > 0) ? ENGINE_CALLBACK_NOTE_ON : ENGINE_CALLBACK_NOTE_OFF, pData->id, channel, note, velo, nullptr);
  1443. }
  1444. #endif
  1445. void CarlaPlugin::sendMidiAllNotesOffToCallback()
  1446. {
  1447. if (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)
  1448. return;
  1449. PluginPostRtEvent postEvent;
  1450. postEvent.type = kPluginPostRtEventNoteOff;
  1451. postEvent.value1 = pData->ctrlChannel;
  1452. postEvent.value2 = 0;
  1453. postEvent.value3 = 0.0f;
  1454. for (int32_t i=0; i < MAX_MIDI_NOTE; ++i)
  1455. {
  1456. postEvent.value2 = i;
  1457. pData->postRtEvents.appendRT(postEvent);
  1458. }
  1459. }
  1460. // -------------------------------------------------------------------
  1461. // Post-poned events
  1462. void CarlaPlugin::postRtEventsRun()
  1463. {
  1464. const CarlaMutexLocker sl(pData->postRtEvents.mutex);
  1465. #ifndef BUILD_BRIDGE
  1466. const bool sendOsc(pData->engine->isOscControlRegistered());
  1467. #endif
  1468. while (! pData->postRtEvents.data.isEmpty())
  1469. {
  1470. const PluginPostRtEvent& event(pData->postRtEvents.data.getFirst(true));
  1471. switch (event.type)
  1472. {
  1473. case kPluginPostRtEventNull:
  1474. break;
  1475. case kPluginPostRtEventDebug:
  1476. #ifndef BUILD_BRIDGE
  1477. pData->engine->callback(ENGINE_CALLBACK_DEBUG, pData->id, event.value1, event.value2, event.value3, nullptr);
  1478. #endif
  1479. break;
  1480. case kPluginPostRtEventParameterChange:
  1481. // Update UI
  1482. if (event.value1 >= 0 && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1483. uiParameterChange(static_cast<uint32_t>(event.value1), event.value3);
  1484. #ifndef BUILD_BRIDGE
  1485. if (event.value2 != 1)
  1486. {
  1487. // Update OSC control client
  1488. if (sendOsc)
  1489. pData->engine->oscSend_control_set_parameter_value(pData->id, event.value1, event.value3);
  1490. // Update Host
  1491. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, event.value1, 0, event.value3, nullptr);
  1492. }
  1493. #endif
  1494. break;
  1495. case kPluginPostRtEventProgramChange:
  1496. // Update UI
  1497. if (event.value1 >= 0 && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1498. uiProgramChange(static_cast<uint32_t>(event.value1));
  1499. #ifndef BUILD_BRIDGE
  1500. // Update OSC control client
  1501. if (sendOsc)
  1502. pData->engine->oscSend_control_set_current_program(pData->id, event.value1);
  1503. // Update Host
  1504. pData->engine->callback(ENGINE_CALLBACK_PROGRAM_CHANGED, pData->id, event.value1, 0, 0.0f, nullptr);
  1505. // Update param values
  1506. for (uint32_t j=0; j < pData->param.count; ++j)
  1507. {
  1508. const float paramValue(getParameterValue(j));
  1509. if (sendOsc)
  1510. {
  1511. pData->engine->oscSend_control_set_parameter_value(pData->id, static_cast<int32_t>(j), paramValue);
  1512. pData->engine->oscSend_control_set_default_value(pData->id, j, pData->param.ranges[j].def);
  1513. }
  1514. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast<int>(j), 0, paramValue, nullptr);
  1515. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, pData->id, static_cast<int>(j), 0, pData->param.ranges[j].def, nullptr);
  1516. }
  1517. #endif
  1518. break;
  1519. case kPluginPostRtEventMidiProgramChange:
  1520. // Update UI
  1521. if (event.value1 >= 0 && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1522. uiMidiProgramChange(static_cast<uint32_t>(event.value1));
  1523. #ifndef BUILD_BRIDGE
  1524. // Update OSC control client
  1525. if (sendOsc)
  1526. pData->engine->oscSend_control_set_current_midi_program(pData->id, event.value1);
  1527. // Update Host
  1528. pData->engine->callback(ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, event.value1, 0, 0.0f, nullptr);
  1529. // Update param values
  1530. for (uint32_t j=0; j < pData->param.count; ++j)
  1531. {
  1532. const float paramValue(getParameterValue(j));
  1533. if (sendOsc)
  1534. {
  1535. pData->engine->oscSend_control_set_parameter_value(pData->id, static_cast<int32_t>(j), paramValue);
  1536. pData->engine->oscSend_control_set_default_value(pData->id, j, pData->param.ranges[j].def);
  1537. }
  1538. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, static_cast<int>(j), 0, paramValue, nullptr);
  1539. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED, pData->id, static_cast<int>(j), 0, pData->param.ranges[j].def, nullptr);
  1540. }
  1541. #endif
  1542. break;
  1543. case kPluginPostRtEventNoteOn:
  1544. {
  1545. CARLA_SAFE_ASSERT_BREAK(event.value1 >= 0 && event.value1 < MAX_MIDI_CHANNELS);
  1546. CARLA_SAFE_ASSERT_BREAK(event.value2 >= 0 && event.value2 < MAX_MIDI_NOTE);
  1547. CARLA_SAFE_ASSERT_BREAK(event.value3 >= 0 && event.value3 < MAX_MIDI_VALUE);
  1548. const uint8_t channel = static_cast<uint8_t>(event.value1);
  1549. const uint8_t note = static_cast<uint8_t>(event.value2);
  1550. const uint8_t velocity = uint8_t(event.value3);
  1551. // Update UI
  1552. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  1553. uiNoteOn(channel, note, velocity);
  1554. #ifndef BUILD_BRIDGE
  1555. // Update OSC control client
  1556. if (sendOsc)
  1557. pData->engine->oscSend_control_note_on(pData->id, channel, note, velocity);
  1558. // Update Host
  1559. pData->engine->callback(ENGINE_CALLBACK_NOTE_ON, pData->id, event.value1, event.value2, event.value3, nullptr);
  1560. #endif
  1561. break;
  1562. }
  1563. case kPluginPostRtEventNoteOff:
  1564. {
  1565. CARLA_SAFE_ASSERT_BREAK(event.value1 >= 0 && event.value1 < MAX_MIDI_CHANNELS);
  1566. CARLA_SAFE_ASSERT_BREAK(event.value2 >= 0 && event.value2 < MAX_MIDI_NOTE);
  1567. const uint8_t channel = static_cast<uint8_t>(event.value1);
  1568. const uint8_t note = static_cast<uint8_t>(event.value2);
  1569. // Update UI
  1570. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  1571. uiNoteOff(channel, note);
  1572. #ifndef BUILD_BRIDGE
  1573. // Update OSC control client
  1574. if (sendOsc)
  1575. pData->engine->oscSend_control_note_off(pData->id, channel, note);
  1576. // Update Host
  1577. pData->engine->callback(ENGINE_CALLBACK_NOTE_OFF, pData->id, event.value1, event.value2, 0.0f, nullptr);
  1578. #endif
  1579. break;
  1580. }
  1581. }
  1582. }
  1583. }
  1584. // -------------------------------------------------------------------
  1585. // Post-poned UI Stuff
  1586. void CarlaPlugin::uiParameterChange(const uint32_t index, const float value) noexcept
  1587. {
  1588. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  1589. return;
  1590. // unused
  1591. (void)value;
  1592. }
  1593. void CarlaPlugin::uiProgramChange(const uint32_t index) noexcept
  1594. {
  1595. CARLA_SAFE_ASSERT_RETURN(index < getProgramCount(),);
  1596. }
  1597. void CarlaPlugin::uiMidiProgramChange(const uint32_t index) noexcept
  1598. {
  1599. CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(),);
  1600. }
  1601. void CarlaPlugin::uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept
  1602. {
  1603. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1604. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1605. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1606. }
  1607. void CarlaPlugin::uiNoteOff(const uint8_t channel, const uint8_t note) noexcept
  1608. {
  1609. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1610. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1611. }
  1612. bool CarlaPlugin::canRunInRack() const noexcept
  1613. {
  1614. return (pData->extraHints & PLUGIN_EXTRA_HINT_CAN_RUN_RACK) != 0;
  1615. }
  1616. CarlaEngine* CarlaPlugin::getEngine() const noexcept
  1617. {
  1618. return pData->engine;
  1619. }
  1620. CarlaEngineClient* CarlaPlugin::getEngineClient() const noexcept
  1621. {
  1622. return pData->client;
  1623. }
  1624. CarlaEngineAudioPort* CarlaPlugin::getAudioInPort(const uint32_t index) const noexcept
  1625. {
  1626. return pData->audioIn.ports[index].port;
  1627. }
  1628. CarlaEngineAudioPort* CarlaPlugin::getAudioOutPort(const uint32_t index) const noexcept
  1629. {
  1630. return pData->audioOut.ports[index].port;
  1631. }
  1632. // -------------------------------------------------------------------
  1633. // Scoped Disabler
  1634. CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin* const plugin) noexcept
  1635. : fPlugin(plugin)
  1636. {
  1637. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  1638. CARLA_SAFE_ASSERT_RETURN(plugin->pData != nullptr,);
  1639. CARLA_SAFE_ASSERT_RETURN(plugin->pData->client != nullptr,);
  1640. carla_debug("CarlaPlugin::ScopedDisabler(%p)", plugin);
  1641. plugin->pData->masterMutex.lock();
  1642. if (plugin->pData->enabled)
  1643. plugin->pData->enabled = false;
  1644. if (plugin->pData->client->isActive())
  1645. plugin->pData->client->deactivate();
  1646. }
  1647. CarlaPlugin::ScopedDisabler::~ScopedDisabler() noexcept
  1648. {
  1649. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  1650. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,);
  1651. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData->client != nullptr,);
  1652. carla_debug("CarlaPlugin::~ScopedDisabler()");
  1653. fPlugin->pData->enabled = true;
  1654. fPlugin->pData->client->activate();
  1655. fPlugin->pData->masterMutex.unlock();
  1656. }
  1657. // -------------------------------------------------------------------
  1658. // Scoped Process Locker
  1659. CarlaPlugin::ScopedSingleProcessLocker::ScopedSingleProcessLocker(CarlaPlugin* const plugin, const bool block) noexcept
  1660. : fPlugin(plugin),
  1661. fBlock(block)
  1662. {
  1663. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  1664. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,);
  1665. carla_debug("CarlaPlugin::ScopedSingleProcessLocker(%p, %s)", plugin, bool2str(block));
  1666. if (! fBlock)
  1667. return;
  1668. plugin->pData->singleMutex.lock();
  1669. }
  1670. CarlaPlugin::ScopedSingleProcessLocker::~ScopedSingleProcessLocker() noexcept
  1671. {
  1672. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  1673. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,);
  1674. carla_debug("CarlaPlugin::~ScopedSingleProcessLocker()");
  1675. if (! fBlock)
  1676. return;
  1677. #ifndef BUILD_BRIDGE
  1678. if (fPlugin->pData->singleMutex.wasTryLockCalled())
  1679. fPlugin->pData->needsReset = true;
  1680. #endif
  1681. fPlugin->pData->singleMutex.unlock();
  1682. }
  1683. // -------------------------------------------------------------------
  1684. CARLA_BACKEND_END_NAMESPACE