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

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
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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 years ago
10 years ago
11 years ago
11 years ago
9 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
10 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
10 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
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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625
  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 "CarlaBackendUtils.hpp"
  20. #include "CarlaBase64Utils.hpp"
  21. #include "CarlaMathUtils.hpp"
  22. #include "CarlaPluginUI.hpp"
  23. #include "CarlaScopeUtils.hpp"
  24. #include "CarlaStringList.hpp"
  25. #include <ctime>
  26. #include "water/files/File.h"
  27. #include "water/streams/MemoryOutputStream.h"
  28. #include "water/xml/XmlDocument.h"
  29. #include "water/xml/XmlElement.h"
  30. using water::CharPointer_UTF8;
  31. using water::File;
  32. using water::MemoryOutputStream;
  33. using water::Result;
  34. using water::String;
  35. using water::XmlDocument;
  36. using water::XmlElement;
  37. CARLA_BACKEND_START_NAMESPACE
  38. // -------------------------------------------------------------------
  39. // Fallback data
  40. static const ParameterData kParameterDataNull = { PARAMETER_UNKNOWN, 0x0, PARAMETER_NULL, -1, 0, CONTROL_INDEX_NONE, 0.0f, 1.0f };
  41. static const ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0.0001f, 0.1f };
  42. static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr };
  43. static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
  44. static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr };
  45. static const PluginPostRtEvent kPluginPostRtEventFallback = { kPluginPostRtEventNull, false, 0, 0, 0, 0.0f };
  46. // -------------------------------------------------------------------
  47. // ParamSymbol struct, needed for CarlaPlugin::loadStateSave()
  48. struct ParamSymbol {
  49. int32_t index;
  50. const char* symbol;
  51. ParamSymbol(const uint32_t i, const char* const s)
  52. : index(static_cast<int32_t>(i)),
  53. symbol(carla_strdup(s)) {}
  54. ~ParamSymbol() noexcept
  55. {
  56. CARLA_SAFE_ASSERT_RETURN(symbol != nullptr,)
  57. delete[] symbol;
  58. symbol = nullptr;
  59. }
  60. #ifdef CARLA_PROPER_CPP11_SUPPORT
  61. ParamSymbol() = delete;
  62. CARLA_DECLARE_NON_COPY_STRUCT(ParamSymbol)
  63. #endif
  64. };
  65. // -------------------------------------------------------------------
  66. // Constructor and destructor
  67. CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const uint id)
  68. : pData(new ProtectedData(engine, id))
  69. {
  70. CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);
  71. CARLA_SAFE_ASSERT(id < engine->getMaxPluginNumber());
  72. carla_debug("CarlaPlugin::CarlaPlugin(%p, %i)", engine, id);
  73. switch (engine->getProccessMode())
  74. {
  75. case ENGINE_PROCESS_MODE_SINGLE_CLIENT:
  76. case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS:
  77. CARLA_SAFE_ASSERT(id < MAX_DEFAULT_PLUGINS);
  78. break;
  79. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  80. CARLA_SAFE_ASSERT(id < MAX_RACK_PLUGINS);
  81. break;
  82. case ENGINE_PROCESS_MODE_PATCHBAY:
  83. CARLA_SAFE_ASSERT(id < MAX_PATCHBAY_PLUGINS);
  84. break;
  85. case ENGINE_PROCESS_MODE_BRIDGE:
  86. CARLA_SAFE_ASSERT(id == 0);
  87. break;
  88. }
  89. }
  90. CarlaPlugin::~CarlaPlugin()
  91. {
  92. carla_debug("CarlaPlugin::~CarlaPlugin()");
  93. delete pData;
  94. }
  95. // -------------------------------------------------------------------
  96. // Information (base)
  97. uint CarlaPlugin::getId() const noexcept
  98. {
  99. return pData->id;
  100. }
  101. uint CarlaPlugin::getHints() const noexcept
  102. {
  103. return pData->hints;
  104. }
  105. uint CarlaPlugin::getOptionsEnabled() const noexcept
  106. {
  107. return pData->options;
  108. }
  109. bool CarlaPlugin::isEnabled() const noexcept
  110. {
  111. return pData->enabled;
  112. }
  113. const char* CarlaPlugin::getName() const noexcept
  114. {
  115. return pData->name;
  116. }
  117. const char* CarlaPlugin::getFilename() const noexcept
  118. {
  119. return pData->filename;
  120. }
  121. const char* CarlaPlugin::getIconName() const noexcept
  122. {
  123. return pData->iconName;
  124. }
  125. PluginCategory CarlaPlugin::getCategory() const noexcept
  126. {
  127. return getPluginCategoryFromName(pData->name);
  128. }
  129. int64_t CarlaPlugin::getUniqueId() const noexcept
  130. {
  131. return 0;
  132. }
  133. uint32_t CarlaPlugin::getLatencyInFrames() const noexcept
  134. {
  135. return 0;
  136. }
  137. // -------------------------------------------------------------------
  138. // Information (count)
  139. uint32_t CarlaPlugin::getAudioInCount() const noexcept
  140. {
  141. return pData->audioIn.count;
  142. }
  143. uint32_t CarlaPlugin::getAudioOutCount() const noexcept
  144. {
  145. return pData->audioOut.count;
  146. }
  147. uint32_t CarlaPlugin::getCVInCount() const noexcept
  148. {
  149. return pData->cvIn.count;
  150. }
  151. uint32_t CarlaPlugin::getCVOutCount() const noexcept
  152. {
  153. return pData->cvOut.count;
  154. }
  155. uint32_t CarlaPlugin::getMidiInCount() const noexcept
  156. {
  157. return (pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_IN) ? 1 : 0;
  158. }
  159. uint32_t CarlaPlugin::getMidiOutCount() const noexcept
  160. {
  161. return (pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_OUT) ? 1 : 0;
  162. }
  163. uint32_t CarlaPlugin::getParameterCount() const noexcept
  164. {
  165. return pData->param.count;
  166. }
  167. uint32_t CarlaPlugin::getParameterScalePointCount(const uint32_t parameterId) const noexcept
  168. {
  169. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
  170. return 0;
  171. }
  172. uint32_t CarlaPlugin::getProgramCount() const noexcept
  173. {
  174. return pData->prog.count;
  175. }
  176. uint32_t CarlaPlugin::getMidiProgramCount() const noexcept
  177. {
  178. return pData->midiprog.count;
  179. }
  180. uint32_t CarlaPlugin::getCustomDataCount() const noexcept
  181. {
  182. return static_cast<uint32_t>(pData->custom.count());
  183. }
  184. // -------------------------------------------------------------------
  185. // Information (current data)
  186. int32_t CarlaPlugin::getCurrentProgram() const noexcept
  187. {
  188. return pData->prog.current;
  189. }
  190. int32_t CarlaPlugin::getCurrentMidiProgram() const noexcept
  191. {
  192. return pData->midiprog.current;
  193. }
  194. const ParameterData& CarlaPlugin::getParameterData(const uint32_t parameterId) const noexcept
  195. {
  196. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, kParameterDataNull);
  197. return pData->param.data[parameterId];
  198. }
  199. const ParameterRanges& CarlaPlugin::getParameterRanges(const uint32_t parameterId) const noexcept
  200. {
  201. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, kParameterRangesNull);
  202. return pData->param.ranges[parameterId];
  203. }
  204. bool CarlaPlugin::isParameterOutput(const uint32_t parameterId) const noexcept
  205. {
  206. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  207. return (pData->param.data[parameterId].type == PARAMETER_OUTPUT);
  208. }
  209. const MidiProgramData& CarlaPlugin::getMidiProgramData(const uint32_t index) const noexcept
  210. {
  211. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count, kMidiProgramDataNull);
  212. return pData->midiprog.data[index];
  213. }
  214. const CustomData& CarlaPlugin::getCustomData(const uint32_t index) const noexcept
  215. {
  216. return pData->custom.getAt(index, kCustomDataFallback);
  217. }
  218. std::size_t CarlaPlugin::getChunkData(void** const dataPtr) noexcept
  219. {
  220. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  221. CARLA_SAFE_ASSERT(false); // this should never happen
  222. return 0;
  223. }
  224. // -------------------------------------------------------------------
  225. // Information (per-plugin data)
  226. uint CarlaPlugin::getOptionsAvailable() const noexcept
  227. {
  228. CARLA_SAFE_ASSERT(false); // this should never happen
  229. return 0x0;
  230. }
  231. float CarlaPlugin::getParameterValue(const uint32_t parameterId) const noexcept
  232. {
  233. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), 0.0f);
  234. CARLA_SAFE_ASSERT(false); // this should never happen
  235. return 0.0f;
  236. }
  237. float CarlaPlugin::getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept
  238. {
  239. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), 0.0f);
  240. CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), 0.0f);
  241. CARLA_SAFE_ASSERT(false); // this should never happen
  242. return 0.0f;
  243. }
  244. bool CarlaPlugin::getLabel(char* const strBuf) const noexcept
  245. {
  246. strBuf[0] = '\0';
  247. return false;
  248. }
  249. bool CarlaPlugin::getMaker(char* const strBuf) const noexcept
  250. {
  251. strBuf[0] = '\0';
  252. return false;
  253. }
  254. bool CarlaPlugin::getCopyright(char* const strBuf) const noexcept
  255. {
  256. strBuf[0] = '\0';
  257. return false;
  258. }
  259. bool CarlaPlugin::getRealName(char* const strBuf) const noexcept
  260. {
  261. strBuf[0] = '\0';
  262. return false;
  263. }
  264. bool CarlaPlugin::getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept
  265. {
  266. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  267. CARLA_SAFE_ASSERT(false); // this should never happen
  268. strBuf[0] = '\0';
  269. return false;
  270. }
  271. bool CarlaPlugin::getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept
  272. {
  273. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  274. strBuf[0] = '\0';
  275. return false;
  276. }
  277. bool CarlaPlugin::getParameterText(const uint32_t parameterId, char* const strBuf) noexcept
  278. {
  279. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  280. CARLA_SAFE_ASSERT(false); // this should never happen
  281. strBuf[0] = '\0';
  282. return false;
  283. }
  284. bool CarlaPlugin::getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept
  285. {
  286. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  287. strBuf[0] = '\0';
  288. return false;
  289. }
  290. bool CarlaPlugin::getParameterComment(const uint32_t parameterId, char* const strBuf) const noexcept
  291. {
  292. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  293. strBuf[0] = '\0';
  294. return false;
  295. }
  296. bool CarlaPlugin::getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept
  297. {
  298. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  299. strBuf[0] = '\0';
  300. return false;
  301. }
  302. bool CarlaPlugin::getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept
  303. {
  304. CARLA_SAFE_ASSERT_RETURN(parameterId < getParameterCount(), false);
  305. CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), false);
  306. CARLA_SAFE_ASSERT(false); // this should never happen
  307. strBuf[0] = '\0';
  308. return false;
  309. }
  310. float CarlaPlugin::getInternalParameterValue(const int32_t parameterId) const noexcept
  311. {
  312. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  313. CARLA_SAFE_ASSERT_RETURN(parameterId != PARAMETER_NULL && parameterId > PARAMETER_MAX, 0.0f);
  314. switch (parameterId)
  315. {
  316. case PARAMETER_ACTIVE:
  317. return pData->active;
  318. case PARAMETER_CTRL_CHANNEL:
  319. return pData->ctrlChannel;
  320. case PARAMETER_DRYWET:
  321. return pData->postProc.dryWet;
  322. case PARAMETER_VOLUME:
  323. return pData->postProc.volume;
  324. case PARAMETER_BALANCE_LEFT:
  325. return pData->postProc.balanceLeft;
  326. case PARAMETER_BALANCE_RIGHT:
  327. return pData->postProc.balanceRight;
  328. case PARAMETER_PANNING:
  329. return pData->postProc.panning;
  330. };
  331. #endif
  332. CARLA_SAFE_ASSERT_RETURN(parameterId >= 0, 0.0f);
  333. return getParameterValue(static_cast<uint32_t>(parameterId));
  334. }
  335. bool CarlaPlugin::getProgramName(const uint32_t index, char* const strBuf) const noexcept
  336. {
  337. CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count, false);
  338. CARLA_SAFE_ASSERT_RETURN(pData->prog.names[index] != nullptr, false);
  339. std::strncpy(strBuf, pData->prog.names[index], STR_MAX);
  340. return true;
  341. }
  342. bool CarlaPlugin::getMidiProgramName(const uint32_t index, char* const strBuf) const noexcept
  343. {
  344. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count, false);
  345. CARLA_SAFE_ASSERT_RETURN(pData->midiprog.data[index].name != nullptr, false);
  346. std::strncpy(strBuf, pData->midiprog.data[index].name, STR_MAX);
  347. return true;
  348. }
  349. void CarlaPlugin::getParameterCountInfo(uint32_t& ins, uint32_t& outs) const noexcept
  350. {
  351. ins = 0;
  352. outs = 0;
  353. for (uint32_t i=0; i < pData->param.count; ++i)
  354. {
  355. if (pData->param.data[i].type == PARAMETER_INPUT)
  356. ++ins;
  357. else if (pData->param.data[i].type == PARAMETER_OUTPUT)
  358. ++outs;
  359. }
  360. }
  361. // -------------------------------------------------------------------
  362. // Set data (state)
  363. void CarlaPlugin::prepareForSave()
  364. {
  365. }
  366. void CarlaPlugin::resetParameters() noexcept
  367. {
  368. for (uint i=0; i < pData->param.count; ++i)
  369. {
  370. const ParameterData& paramData(pData->param.data[i]);
  371. const ParameterRanges& paramRanges(pData->param.ranges[i]);
  372. if (paramData.type != PARAMETER_INPUT)
  373. continue;
  374. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  375. continue;
  376. setParameterValue(i, paramRanges.def, true, true, true);
  377. }
  378. }
  379. void CarlaPlugin::randomizeParameters() noexcept
  380. {
  381. float value, random;
  382. char strBuf[STR_MAX+1];
  383. strBuf[STR_MAX] = '\0';
  384. std::srand(static_cast<uint>(std::time(nullptr)));
  385. for (uint i=0; i < pData->param.count; ++i)
  386. {
  387. const ParameterData& paramData(pData->param.data[i]);
  388. if (paramData.type != PARAMETER_INPUT)
  389. continue;
  390. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  391. continue;
  392. if (! getParameterName(i, strBuf))
  393. strBuf[0] = '\0';
  394. if (std::strstr(strBuf, "olume") != nullptr)
  395. continue;
  396. if (std::strstr(strBuf, "Master") != nullptr)
  397. continue;
  398. const ParameterRanges& paramRanges(pData->param.ranges[i]);
  399. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  400. {
  401. random = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
  402. value = random > 0.5f ? paramRanges.max : paramRanges.min;
  403. }
  404. else
  405. {
  406. random = static_cast<float>(std::rand()) / static_cast<float>(RAND_MAX);
  407. value = random * (paramRanges.max - paramRanges.min) + paramRanges.min;
  408. if (paramData.hints & PARAMETER_IS_INTEGER)
  409. value = std::rint(value);
  410. }
  411. setParameterValue(i, value, true, true, true);
  412. }
  413. }
  414. const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)
  415. {
  416. if (callPrepareForSave)
  417. prepareForSave();
  418. pData->stateSave.clear();
  419. const PluginType pluginType(getType());
  420. char strBuf[STR_MAX+1];
  421. carla_zeroChars(strBuf, STR_MAX+1);
  422. // ---------------------------------------------------------------
  423. // Basic info
  424. if (! getLabel(strBuf))
  425. strBuf[0] = '\0';
  426. pData->stateSave.type = carla_strdup(getPluginTypeAsString(pluginType));
  427. pData->stateSave.name = carla_strdup(pData->name);
  428. pData->stateSave.label = carla_strdup(strBuf);
  429. pData->stateSave.uniqueId = getUniqueId();
  430. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  431. pData->stateSave.options = pData->options;
  432. #endif
  433. if (pData->filename != nullptr)
  434. pData->stateSave.binary = carla_strdup(pData->filename);
  435. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  436. // ---------------------------------------------------------------
  437. // Internals
  438. pData->stateSave.active = pData->active;
  439. pData->stateSave.dryWet = pData->postProc.dryWet;
  440. pData->stateSave.volume = pData->postProc.volume;
  441. pData->stateSave.balanceLeft = pData->postProc.balanceLeft;
  442. pData->stateSave.balanceRight = pData->postProc.balanceRight;
  443. pData->stateSave.panning = pData->postProc.panning;
  444. pData->stateSave.ctrlChannel = pData->ctrlChannel;
  445. #endif
  446. bool usingChunk = false;
  447. // ---------------------------------------------------------------
  448. // Chunk
  449. if (pData->options & PLUGIN_OPTION_USE_CHUNKS)
  450. {
  451. void* data = nullptr;
  452. const std::size_t dataSize(getChunkData(&data));
  453. if (data != nullptr && dataSize > 0)
  454. {
  455. pData->stateSave.chunk = CarlaString::asBase64(data, dataSize).dup();
  456. if (pluginType != PLUGIN_INTERNAL)
  457. usingChunk = true;
  458. }
  459. }
  460. // ---------------------------------------------------------------
  461. // Current Program
  462. if (pData->prog.current >= 0 && pluginType != PLUGIN_LV2)
  463. {
  464. pData->stateSave.currentProgramIndex = pData->prog.current;
  465. pData->stateSave.currentProgramName = carla_strdup(pData->prog.names[pData->prog.current]);
  466. }
  467. // ---------------------------------------------------------------
  468. // Current MIDI Program
  469. if (pData->midiprog.current >= 0 && pluginType != PLUGIN_LV2 && pluginType != PLUGIN_SF2)
  470. {
  471. const MidiProgramData& mpData(pData->midiprog.getCurrent());
  472. pData->stateSave.currentMidiBank = static_cast<int32_t>(mpData.bank);
  473. pData->stateSave.currentMidiProgram = static_cast<int32_t>(mpData.program);
  474. }
  475. // ---------------------------------------------------------------
  476. // Parameters
  477. const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
  478. for (uint32_t i=0; i < pData->param.count; ++i)
  479. {
  480. const ParameterData& paramData(pData->param.data[i]);
  481. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  482. continue;
  483. const bool dummy = paramData.type != PARAMETER_INPUT || usingChunk;
  484. if (dummy && paramData.mappedControlIndex <= CONTROL_INDEX_NONE)
  485. continue;
  486. CarlaStateSave::Parameter* const stateParameter(new CarlaStateSave::Parameter());
  487. stateParameter->dummy = dummy;
  488. stateParameter->index = paramData.index;
  489. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  490. stateParameter->mappedControlIndex = paramData.mappedControlIndex;
  491. stateParameter->midiChannel = paramData.midiChannel;
  492. if (paramData.hints & PARAMETER_MAPPED_RANGES_SET)
  493. {
  494. stateParameter->mappedMinimum = paramData.mappedMinimum;
  495. stateParameter->mappedMaximum = paramData.mappedMaximum;
  496. stateParameter->mappedRangeValid = true;
  497. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  498. {
  499. stateParameter->mappedMinimum /= sampleRate;
  500. stateParameter->mappedMaximum /= sampleRate;
  501. }
  502. }
  503. #endif
  504. if (! getParameterName(i, strBuf))
  505. strBuf[0] = '\0';
  506. stateParameter->name = carla_strdup(strBuf);
  507. if (! getParameterSymbol(i, strBuf))
  508. strBuf[0] = '\0';
  509. stateParameter->symbol = carla_strdup(strBuf);;
  510. if (! dummy)
  511. {
  512. stateParameter->value = getParameterValue(i);
  513. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  514. stateParameter->value /= sampleRate;
  515. }
  516. pData->stateSave.parameters.append(stateParameter);
  517. }
  518. // ---------------------------------------------------------------
  519. // Custom Data
  520. if (pData->hints & PLUGIN_IS_BRIDGE)
  521. waitForBridgeSaveSignal();
  522. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
  523. {
  524. const CustomData& cData(it.getValue(kCustomDataFallback));
  525. CARLA_SAFE_ASSERT_CONTINUE(cData.isValid());
  526. CarlaStateSave::CustomData* stateCustomData(new CarlaStateSave::CustomData());
  527. stateCustomData->type = carla_strdup(cData.type);
  528. stateCustomData->key = carla_strdup(cData.key);
  529. stateCustomData->value = carla_strdup(cData.value);
  530. pData->stateSave.customData.append(stateCustomData);
  531. }
  532. return pData->stateSave;
  533. }
  534. void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
  535. {
  536. const bool usesMultiProgs(pData->hints & PLUGIN_USES_MULTI_PROGS);
  537. const PluginType pluginType(getType());
  538. char strBuf[STR_MAX+1];
  539. carla_zeroChars(strBuf, STR_MAX+1);
  540. // ---------------------------------------------------------------
  541. // Part 1 - PRE-set custom data (only those which reload programs)
  542. for (CarlaStateSave::CustomDataItenerator it = stateSave.customData.begin2(); it.valid(); it.next())
  543. {
  544. const CarlaStateSave::CustomData* const stateCustomData(it.getValue(nullptr));
  545. CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr);
  546. CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid());
  547. const char* const key(stateCustomData->key);
  548. /**/ if (pluginType == PLUGIN_DSSI && (std::strcmp (key, "reloadprograms") == 0 ||
  549. std::strcmp (key, "load" ) == 0 ||
  550. std::strncmp(key, "patches", 7) == 0 ))
  551. pass();
  552. else if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
  553. pass();
  554. else
  555. continue;
  556. setCustomData(stateCustomData->type, key, stateCustomData->value, true);
  557. }
  558. // ---------------------------------------------------------------
  559. // Part 2 - set program
  560. if (stateSave.currentProgramIndex >= 0 && stateSave.currentProgramName != nullptr)
  561. {
  562. int32_t programId = -1;
  563. // index < count
  564. if (stateSave.currentProgramIndex < static_cast<int32_t>(pData->prog.count))
  565. {
  566. programId = stateSave.currentProgramIndex;
  567. }
  568. // index not valid, try to find by name
  569. else
  570. {
  571. for (uint32_t i=0; i < pData->prog.count; ++i)
  572. {
  573. if (getProgramName(i, strBuf) && std::strcmp(stateSave.currentProgramName, strBuf) == 0)
  574. {
  575. programId = static_cast<int32_t>(i);
  576. break;
  577. }
  578. }
  579. }
  580. // set program now, if valid
  581. if (programId >= 0)
  582. setProgram(programId, true, true, true);
  583. }
  584. // ---------------------------------------------------------------
  585. // Part 3 - set midi program
  586. if (stateSave.currentMidiBank >= 0 && stateSave.currentMidiProgram >= 0 && ! usesMultiProgs)
  587. setMidiProgramById(static_cast<uint32_t>(stateSave.currentMidiBank), static_cast<uint32_t>(stateSave.currentMidiProgram), true, true, true);
  588. // ---------------------------------------------------------------
  589. // Part 4a - get plugin parameter symbols
  590. LinkedList<ParamSymbol*> paramSymbols;
  591. if (pluginType == PLUGIN_LADSPA || pluginType == PLUGIN_LV2)
  592. {
  593. for (uint32_t i=0; i < pData->param.count; ++i)
  594. {
  595. if (getParameterSymbol(i, strBuf))
  596. {
  597. ParamSymbol* const paramSymbol(new ParamSymbol(i, strBuf));
  598. paramSymbols.append(paramSymbol);
  599. }
  600. }
  601. }
  602. // ---------------------------------------------------------------
  603. // Part 4b - set parameter values (carefully)
  604. const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
  605. for (CarlaStateSave::ParameterItenerator it = stateSave.parameters.begin2(); it.valid(); it.next())
  606. {
  607. CarlaStateSave::Parameter* const stateParameter(it.getValue(nullptr));
  608. CARLA_SAFE_ASSERT_CONTINUE(stateParameter != nullptr);
  609. int32_t index = -1;
  610. if (pluginType == PLUGIN_LADSPA)
  611. {
  612. // Try to set by symbol, otherwise use index
  613. if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
  614. {
  615. for (LinkedList<ParamSymbol*>::Itenerator it2 = paramSymbols.begin2(); it2.valid(); it2.next())
  616. {
  617. ParamSymbol* const paramSymbol(it2.getValue(nullptr));
  618. CARLA_SAFE_ASSERT_CONTINUE(paramSymbol != nullptr);
  619. CARLA_SAFE_ASSERT_CONTINUE(paramSymbol->symbol != nullptr);
  620. if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0)
  621. {
  622. index = paramSymbol->index;
  623. break;
  624. }
  625. }
  626. if (index == -1)
  627. index = stateParameter->index;
  628. }
  629. else
  630. {
  631. index = stateParameter->index;
  632. }
  633. }
  634. else if (pluginType == PLUGIN_LV2)
  635. {
  636. // Symbol only
  637. if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
  638. {
  639. for (LinkedList<ParamSymbol*>::Itenerator it2 = paramSymbols.begin2(); it2.valid(); it2.next())
  640. {
  641. ParamSymbol* const paramSymbol(it2.getValue(nullptr));
  642. CARLA_SAFE_ASSERT_CONTINUE(paramSymbol != nullptr);
  643. CARLA_SAFE_ASSERT_CONTINUE(paramSymbol->symbol != nullptr);
  644. if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0)
  645. {
  646. index = paramSymbol->index;
  647. break;
  648. }
  649. }
  650. if (index == -1)
  651. carla_stderr("Failed to find LV2 parameter symbol '%s' for '%s'",
  652. stateParameter->symbol, pData->name);
  653. }
  654. else
  655. {
  656. carla_stderr("LV2 Plugin parameter '%s' has no symbol", stateParameter->name);
  657. }
  658. }
  659. else
  660. {
  661. // Index only
  662. index = stateParameter->index;
  663. }
  664. // Now set parameter
  665. if (index >= 0 && index < static_cast<int32_t>(pData->param.count))
  666. {
  667. //CARLA_SAFE_ASSERT(stateParameter->isInput == (pData
  668. if (! stateParameter->dummy)
  669. {
  670. if (pData->param.data[index].hints & PARAMETER_USES_SAMPLERATE)
  671. stateParameter->value *= sampleRate;
  672. setParameterValue(static_cast<uint32_t>(index), stateParameter->value, true, true, true);
  673. }
  674. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  675. if (stateParameter->mappedRangeValid)
  676. {
  677. if (pData->param.data[index].hints & PARAMETER_USES_SAMPLERATE)
  678. {
  679. stateParameter->mappedMinimum *= sampleRate;
  680. stateParameter->mappedMaximum *= sampleRate;
  681. }
  682. setParameterMappedRange(static_cast<uint32_t>(index),
  683. stateParameter->mappedMinimum,
  684. stateParameter->mappedMaximum, true, true);
  685. }
  686. setParameterMappedControlIndex(static_cast<uint32_t>(index), stateParameter->mappedControlIndex, true, true);
  687. setParameterMidiChannel(static_cast<uint32_t>(index), stateParameter->midiChannel, true, true);
  688. #endif
  689. }
  690. else
  691. carla_stderr("Could not set parameter '%s' value for '%s'",
  692. stateParameter->name, pData->name);
  693. }
  694. // ---------------------------------------------------------------
  695. // Part 4c - clear
  696. for (LinkedList<ParamSymbol*>::Itenerator it = paramSymbols.begin2(); it.valid(); it.next())
  697. {
  698. ParamSymbol* const paramSymbol(it.getValue(nullptr));
  699. delete paramSymbol;
  700. }
  701. paramSymbols.clear();
  702. // ---------------------------------------------------------------
  703. // Part 5 - set custom data
  704. for (CarlaStateSave::CustomDataItenerator it = stateSave.customData.begin2(); it.valid(); it.next())
  705. {
  706. const CarlaStateSave::CustomData* const stateCustomData(it.getValue(nullptr));
  707. CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr);
  708. CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid());
  709. const char* const key(stateCustomData->key);
  710. if (pluginType == PLUGIN_DSSI && (std::strcmp (key, "reloadprograms") == 0 ||
  711. std::strcmp (key, "load" ) == 0 ||
  712. std::strncmp(key, "patches", 7) == 0 ))
  713. continue;
  714. if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
  715. continue;
  716. setCustomData(stateCustomData->type, key, stateCustomData->value, true);
  717. }
  718. // ---------------------------------------------------------------
  719. // Part 5x - set lv2 state
  720. if (pluginType == PLUGIN_LV2)
  721. {
  722. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
  723. {
  724. const CustomData& customData(it.getValue(kCustomDataFallback));
  725. CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  726. if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
  727. continue;
  728. restoreLV2State();
  729. break;
  730. }
  731. }
  732. // ---------------------------------------------------------------
  733. // Part 6 - set chunk
  734. if (stateSave.chunk != nullptr && (pData->options & PLUGIN_OPTION_USE_CHUNKS) != 0)
  735. {
  736. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(stateSave.chunk));
  737. #ifdef CARLA_PROPER_CPP11_SUPPORT
  738. setChunkData(chunk.data(), chunk.size());
  739. #else
  740. setChunkData(&chunk.front(), chunk.size());
  741. #endif
  742. }
  743. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  744. // ---------------------------------------------------------------
  745. // Part 6 - set internal stuff
  746. const uint availOptions(getOptionsAvailable());
  747. for (uint i=0; i<10; ++i) // FIXME - get this value somehow...
  748. {
  749. const uint option(1u << i);
  750. if (availOptions & option)
  751. setOption(option, (stateSave.options & option) != 0, true);
  752. }
  753. setDryWet(stateSave.dryWet, true, true);
  754. setVolume(stateSave.volume, true, true);
  755. setBalanceLeft(stateSave.balanceLeft, true, true);
  756. setBalanceRight(stateSave.balanceRight, true, true);
  757. setPanning(stateSave.panning, true, true);
  758. setCtrlChannel(stateSave.ctrlChannel, true, true);
  759. setActive(stateSave.active, true, true);
  760. if (! pData->engine->isLoadingProject())
  761. pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0f, nullptr);
  762. #endif
  763. }
  764. bool CarlaPlugin::saveStateToFile(const char* const filename)
  765. {
  766. CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
  767. carla_debug("CarlaPlugin::saveStateToFile(\"%s\")", filename);
  768. MemoryOutputStream out, streamState;
  769. getStateSave().dumpToMemoryStream(streamState);
  770. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  771. out << "<!DOCTYPE CARLA-PRESET>\n";
  772. out << "<CARLA-PRESET VERSION='2.0'>\n";
  773. out << streamState;
  774. out << "</CARLA-PRESET>\n";
  775. const String jfilename = String(CharPointer_UTF8(filename));
  776. File file(jfilename);
  777. if (file.replaceWithData(out.getData(), out.getDataSize()))
  778. return true;
  779. pData->engine->setLastError("Failed to write file");
  780. return false;
  781. }
  782. bool CarlaPlugin::loadStateFromFile(const char* const filename)
  783. {
  784. // TODO set errors
  785. CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
  786. carla_debug("CarlaPlugin::loadStateFromFile(\"%s\")", filename);
  787. const String jfilename = String(CharPointer_UTF8(filename));
  788. File file(jfilename);
  789. CARLA_SAFE_ASSERT_RETURN(file.existsAsFile(), false);
  790. XmlDocument xml(file);
  791. CarlaScopedPointer<XmlElement> xmlElement(xml.getDocumentElement(true));
  792. CARLA_SAFE_ASSERT_RETURN(xmlElement != nullptr, false);
  793. CARLA_SAFE_ASSERT_RETURN(xmlElement->getTagName().equalsIgnoreCase("carla-preset"), false);
  794. // completely load file
  795. xmlElement = xml.getDocumentElement(false);
  796. CARLA_SAFE_ASSERT_RETURN(xmlElement != nullptr, false);
  797. if (pData->stateSave.fillFromXmlElement(xmlElement))
  798. {
  799. loadStateSave(pData->stateSave);
  800. return true;
  801. }
  802. return false;
  803. }
  804. bool CarlaPlugin::exportAsLV2(const char* const lv2path)
  805. {
  806. CARLA_SAFE_ASSERT_RETURN(lv2path != nullptr && lv2path[0] != '\0', false);
  807. carla_debug("CarlaPlugin::exportAsLV2(\"%s\")", lv2path);
  808. CarlaString bundlepath(lv2path);
  809. if (! bundlepath.endsWith(".lv2"))
  810. bundlepath += ".lv2";
  811. const File bundlefolder(bundlepath.buffer());
  812. if (bundlefolder.existsAsFile())
  813. {
  814. pData->engine->setLastError("Requested filename already exists as file, use a folder instead");
  815. return false;
  816. }
  817. if (! bundlefolder.exists())
  818. {
  819. const Result res(bundlefolder.createDirectory());
  820. if (res.failed())
  821. {
  822. pData->engine->setLastError(res.getErrorMessage().toRawUTF8());
  823. return false;
  824. }
  825. }
  826. CarlaString symbol(pData->name);
  827. symbol.toBasic();
  828. {
  829. const CarlaString pluginFilename(bundlepath + CARLA_OS_SEP_STR + symbol + ".xml");
  830. if (! saveStateToFile(pluginFilename))
  831. return false;
  832. }
  833. {
  834. MemoryOutputStream manifestStream;
  835. manifestStream << "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
  836. manifestStream << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  837. manifestStream << "@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n";
  838. manifestStream << "\n";
  839. manifestStream << "<" << symbol.buffer() << ".ttl>\n";
  840. manifestStream << " a lv2:Plugin ;\n";
  841. manifestStream << " lv2:binary <" << symbol.buffer() << CARLA_LIB_EXT "> ;\n";
  842. manifestStream << " rdfs:seeAlso <" << symbol.buffer() << ".ttl> .\n";
  843. manifestStream << "\n";
  844. manifestStream << "<ext-ui>\n";
  845. manifestStream << " a <http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget> ;\n";
  846. manifestStream << " ui:binary <" << symbol.buffer() << CARLA_LIB_EXT "> ;\n";
  847. manifestStream << " lv2:extensionData <http://lv2plug.in/ns/extensions/ui#idleInterface> ,\n";
  848. manifestStream << " <http://lv2plug.in/ns/extensions/ui#showInterface> ;\n";
  849. manifestStream << " lv2:requiredFeature <http://lv2plug.in/ns/ext/instance-access> .\n";
  850. manifestStream << "\n";
  851. const CarlaString manifestFilename(bundlepath + CARLA_OS_SEP_STR "manifest.ttl");
  852. const File manifestFile(manifestFilename.buffer());
  853. if (! manifestFile.replaceWithData(manifestStream.getData(), manifestStream.getDataSize()))
  854. {
  855. pData->engine->setLastError("Failed to write manifest.ttl file");
  856. return false;
  857. }
  858. }
  859. {
  860. MemoryOutputStream mainStream;
  861. mainStream << "@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n";
  862. mainStream << "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
  863. mainStream << "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
  864. mainStream << "@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n";
  865. mainStream << "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
  866. mainStream << "@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n";
  867. mainStream << "\n";
  868. mainStream << "<>\n";
  869. mainStream << " a lv2:Plugin ;\n";
  870. mainStream << "\n";
  871. mainStream << " lv2:requiredFeature <http://lv2plug.in/ns/ext/buf-size#boundedBlockLength> ,\n";
  872. mainStream << " <http://lv2plug.in/ns/ext/options#options> ,\n";
  873. mainStream << " <http://lv2plug.in/ns/ext/urid#map> ;\n";
  874. mainStream << "\n";
  875. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  876. {
  877. mainStream << " ui:ui <ext-ui> ;\n";
  878. mainStream << "\n";
  879. }
  880. const uint32_t midiIns = getMidiInCount();
  881. const uint32_t midiOuts = getMidiOutCount();
  882. int portIndex = 0;
  883. if (midiIns > 0)
  884. {
  885. mainStream << " lv2:port [\n";
  886. mainStream << " a lv2:InputPort, atom:AtomPort ;\n";
  887. mainStream << " lv2:index 0 ;\n";
  888. mainStream << " lv2:symbol \"clv2_events_in\" ;\n";
  889. mainStream << " lv2:name \"Events Input\" ;\n";
  890. mainStream << " atom:bufferType atom:Sequence ;\n";
  891. mainStream << " atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ,\n";
  892. mainStream << " <http://lv2plug.in/ns/ext/time#Position> ;\n";
  893. mainStream << " ] ;\n";
  894. ++portIndex;
  895. for (uint32_t i=1; i<midiIns; ++i)
  896. {
  897. const String portIndexNum(portIndex++);
  898. const String portIndexLabel(portIndex);
  899. mainStream << " lv2:port [\n";
  900. mainStream << " a lv2:InputPort, atom:AtomPort ;\n";
  901. mainStream << " lv2:index " << portIndexNum << " ;\n";
  902. mainStream << " lv2:symbol \"clv2_midi_in_" << portIndexLabel << "\" ;\n";
  903. mainStream << " lv2:name \"MIDI Input " << portIndexLabel << "\" ;\n";
  904. mainStream << " ] ;\n";
  905. }
  906. }
  907. else
  908. {
  909. mainStream << " lv2:port [\n";
  910. mainStream << " a lv2:InputPort, atom:AtomPort ;\n";
  911. mainStream << " lv2:index 0 ;\n";
  912. mainStream << " lv2:symbol \"clv2_time_info\" ;\n";
  913. mainStream << " lv2:name \"Time Info\" ;\n";
  914. mainStream << " atom:bufferType atom:Sequence ;\n";
  915. mainStream << " atom:supports <http://lv2plug.in/ns/ext/time#Position> ;\n";
  916. mainStream << " ] ;\n";
  917. ++portIndex;
  918. }
  919. for (uint32_t i=0; i<midiOuts; ++i)
  920. {
  921. const String portIndexNum(portIndex++);
  922. const String portIndexLabel(portIndex);
  923. mainStream << " lv2:port [\n";
  924. mainStream << " a lv2:InputPort, atom:AtomPort ;\n";
  925. mainStream << " lv2:index " << portIndexNum << " ;\n";
  926. mainStream << " lv2:symbol \"clv2_midi_out_" << portIndexLabel << "\" ;\n";
  927. mainStream << " lv2:name \"MIDI Output " << portIndexLabel << "\" ;\n";
  928. mainStream << " atom:bufferType atom:Sequence ;\n";
  929. mainStream << " atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n";
  930. mainStream << " ] ;\n";
  931. }
  932. mainStream << " lv2:port [\n";
  933. mainStream << " a lv2:InputPort, lv2:ControlPort ;\n";
  934. mainStream << " lv2:index " << String(portIndex++) << " ;\n";
  935. mainStream << " lv2:name \"freewheel\" ;\n";
  936. mainStream << " lv2:symbol \"clv2_freewheel\" ;\n";
  937. mainStream << " lv2:default 0 ;\n";
  938. mainStream << " lv2:minimum 0 ;\n";
  939. mainStream << " lv2:maximum 1 ;\n";
  940. mainStream << " lv2:designation lv2:freeWheeling ;\n";
  941. mainStream << " lv2:portProperty lv2:toggled , lv2:integer ;\n";
  942. mainStream << " lv2:portProperty <http://lv2plug.in/ns/ext/port-props#notOnGUI> ;\n";
  943. mainStream << " ] ;\n";
  944. for (uint32_t i=0; i<pData->audioIn.count; ++i)
  945. {
  946. const String portIndexNum(portIndex++);
  947. const String portIndexLabel(i+1);
  948. mainStream << " lv2:port [\n";
  949. mainStream << " a lv2:InputPort, lv2:AudioPort ;\n";
  950. mainStream << " lv2:index " << portIndexNum << " ;\n";
  951. mainStream << " lv2:symbol \"clv2_audio_in_" << portIndexLabel << "\" ;\n";
  952. mainStream << " lv2:name \"Audio Input " << portIndexLabel << "\" ;\n";
  953. mainStream << " ] ;\n";
  954. }
  955. for (uint32_t i=0; i<pData->audioOut.count; ++i)
  956. {
  957. const String portIndexNum(portIndex++);
  958. const String portIndexLabel(i+1);
  959. mainStream << " lv2:port [\n";
  960. mainStream << " a lv2:OutputPort, lv2:AudioPort ;\n";
  961. mainStream << " lv2:index " << portIndexNum << " ;\n";
  962. mainStream << " lv2:symbol \"clv2_audio_out_" << portIndexLabel << "\" ;\n";
  963. mainStream << " lv2:name \"Audio Output " << portIndexLabel << "\" ;\n";
  964. mainStream << " ] ;\n";
  965. }
  966. CarlaStringList uniqueSymbolNames;
  967. char strBufName[STR_MAX+1];
  968. char strBufSymbol[STR_MAX+1];
  969. carla_zeroChars(strBufName, STR_MAX+1);
  970. carla_zeroChars(strBufSymbol, STR_MAX+1);
  971. for (uint32_t i=0; i<pData->param.count; ++i)
  972. {
  973. const ParameterData& paramData(pData->param.data[i]);
  974. const ParameterRanges& paramRanges(pData->param.ranges[i]);
  975. const String portIndexNum(portIndex++);
  976. mainStream << " lv2:port [\n";
  977. if (paramData.type == PARAMETER_INPUT)
  978. mainStream << " a lv2:InputPort, lv2:ControlPort ;\n";
  979. else
  980. mainStream << " a lv2:OutputPort, lv2:ControlPort ;\n";
  981. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  982. mainStream << " lv2:portProperty lv2:toggled ;\n";
  983. if (paramData.hints & PARAMETER_IS_INTEGER)
  984. mainStream << " lv2:portProperty lv2:integer ;\n";
  985. // TODO logarithmic, enabled (not on gui), automable, samplerate, scalepoints
  986. if (! getParameterName(i, strBufName))
  987. strBufName[0] = '\0';
  988. if (! getParameterSymbol(i, strBufSymbol))
  989. strBufSymbol[0] = '\0';
  990. if (strBufSymbol[0] == '\0')
  991. {
  992. CarlaString s(strBufName);
  993. s.toBasic();
  994. std::memcpy(strBufSymbol, s.buffer(), s.length()+1);
  995. if (strBufSymbol[0] >= '0' && strBufSymbol[0] <= '9')
  996. {
  997. const size_t len(std::strlen(strBufSymbol));
  998. std::memmove(strBufSymbol+1, strBufSymbol, len);
  999. strBufSymbol[0] = '_';
  1000. strBufSymbol[len+1] = '\0';
  1001. }
  1002. }
  1003. if (uniqueSymbolNames.contains(strBufSymbol))
  1004. std::snprintf(strBufSymbol, STR_MAX, "clv2_param_%d", i+1);
  1005. mainStream << " lv2:index " << portIndexNum << " ;\n";
  1006. mainStream << " lv2:symbol \"" << strBufSymbol << "\" ;\n";
  1007. mainStream << " lv2:name \"\"\"" << strBufName << "\"\"\" ;\n";
  1008. mainStream << " lv2:default " << String(paramRanges.def) << " ;\n";
  1009. mainStream << " lv2:minimum " << String(paramRanges.min) << " ;\n";
  1010. mainStream << " lv2:maximum " << String(paramRanges.max) << " ;\n";
  1011. // TODO midiCC, midiChannel
  1012. mainStream << " ] ;\n";
  1013. }
  1014. char strBuf[STR_MAX+1];
  1015. carla_zeroChars(strBuf, STR_MAX+1);
  1016. if (! getMaker(strBuf))
  1017. strBuf[0] = '\0';
  1018. mainStream << " rdfs:comment \"Plugin generated using Carla LV2 export.\" ;\n";
  1019. mainStream << " doap:name \"\"\"" << getName() << "\"\"\" ;\n";
  1020. mainStream << " doap:maintainer [ foaf:name \"\"\"" << strBuf << "\"\"\" ] .\n";
  1021. mainStream << "\n";
  1022. const CarlaString mainFilename(bundlepath + CARLA_OS_SEP_STR + symbol + ".ttl");
  1023. const File mainFile(mainFilename.buffer());
  1024. if (! mainFile.replaceWithData(mainStream.getData(), mainStream.getDataSize()))
  1025. {
  1026. pData->engine->setLastError("Failed to write main plugin ttl file");
  1027. return false;
  1028. }
  1029. }
  1030. const CarlaString binaryFilename(bundlepath + CARLA_OS_SEP_STR + symbol + CARLA_LIB_EXT);
  1031. const File binaryFileSource(File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("carla-bridge-lv2" CARLA_LIB_EXT));
  1032. const File binaryFileTarget(binaryFilename.buffer());
  1033. const EngineOptions& opts(pData->engine->getOptions());
  1034. const CarlaString binFolderTarget(bundlepath + CARLA_OS_SEP_STR + "bin");
  1035. const CarlaString resFolderTarget(bundlepath + CARLA_OS_SEP_STR + "res");
  1036. if (! binaryFileSource.copyFileTo(binaryFileTarget))
  1037. {
  1038. pData->engine->setLastError("Failed to copy plugin binary");
  1039. return false;
  1040. }
  1041. #ifdef CARLA_OS_WIN
  1042. File(opts.resourceDir).copyDirectoryTo(File(resFolderTarget.buffer()));
  1043. // Copying all the binaries is pointless, just go through the expected needed bits
  1044. const File binFolder1(opts.binaryDir);
  1045. const File binFolder2(binFolderTarget.buffer());
  1046. binFolder2.createDirectory();
  1047. static const char* files[] = {
  1048. "carla-bridge-native.exe",
  1049. "carla-bridge-win32.exe",
  1050. "carla-discovery-win32.exe",
  1051. "carla-discovery-win64.exe",
  1052. "libcarla_utils.dll"
  1053. };
  1054. for (int i=0; i<5; ++i)
  1055. binFolder1.getChildFile(files[i]).copyFileTo(binFolder2.getChildFile(files[i]));;
  1056. #else
  1057. File(opts.binaryDir).createSymbolicLink(File(binFolderTarget.buffer()), true);
  1058. File(opts.resourceDir).createSymbolicLink(File(resFolderTarget.buffer()), true);
  1059. #endif
  1060. return true;
  1061. }
  1062. // -------------------------------------------------------------------
  1063. // Set data (internal stuff)
  1064. void CarlaPlugin::setId(const uint newId) noexcept
  1065. {
  1066. pData->id = newId;
  1067. }
  1068. void CarlaPlugin::setName(const char* const newName)
  1069. {
  1070. CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0',);
  1071. if (pData->name != nullptr)
  1072. delete[] pData->name;
  1073. pData->name = carla_strdup(newName);
  1074. }
  1075. void CarlaPlugin::setOption(const uint option, const bool yesNo, const bool sendCallback)
  1076. {
  1077. CARLA_SAFE_ASSERT_UINT2_RETURN(getOptionsAvailable() & option, getOptionsAvailable(), option,);
  1078. if (yesNo)
  1079. pData->options |= option;
  1080. else
  1081. pData->options &= ~option;
  1082. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1083. if (sendCallback)
  1084. pData->engine->callback(true, true,
  1085. ENGINE_CALLBACK_OPTION_CHANGED,
  1086. pData->id,
  1087. static_cast<int>(option),
  1088. yesNo ? 1 : 0,
  1089. 0, 0.0f, nullptr);
  1090. #else
  1091. // unused
  1092. return; (void)sendCallback;
  1093. #endif
  1094. }
  1095. void CarlaPlugin::setEnabled(const bool yesNo) noexcept
  1096. {
  1097. if (pData->enabled == yesNo)
  1098. return;
  1099. pData->masterMutex.lock();
  1100. pData->enabled = yesNo;
  1101. if (yesNo && ! pData->client->isActive())
  1102. pData->client->activate();
  1103. pData->masterMutex.unlock();
  1104. }
  1105. void CarlaPlugin::setActive(const bool active, const bool sendOsc, const bool sendCallback) noexcept
  1106. {
  1107. if (pData->engineBridged) {
  1108. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1109. } else if (pData->enginePlugin) {
  1110. // nothing here
  1111. } else {
  1112. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1113. }
  1114. if (pData->active == active)
  1115. return;
  1116. {
  1117. const ScopedSingleProcessLocker spl(this, true);
  1118. if (active)
  1119. activate();
  1120. else
  1121. deactivate();
  1122. }
  1123. pData->active = active;
  1124. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1125. const float value = active ? 1.0f : 0.0f;
  1126. pData->engine->callback(sendCallback, sendOsc,
  1127. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1128. pData->id,
  1129. PARAMETER_ACTIVE,
  1130. 0, 0,
  1131. value,
  1132. nullptr);
  1133. #endif
  1134. }
  1135. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1136. void CarlaPlugin::setDryWet(const float value, const bool sendOsc, const bool sendCallback) noexcept
  1137. {
  1138. if (pData->engineBridged) {
  1139. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1140. } else {
  1141. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1142. }
  1143. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f);
  1144. const float fixedValue(carla_fixedValue<float>(0.0f, 1.0f, value));
  1145. if (carla_isEqual(pData->postProc.dryWet, fixedValue))
  1146. return;
  1147. pData->postProc.dryWet = fixedValue;
  1148. pData->engine->callback(sendCallback, sendOsc,
  1149. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1150. pData->id,
  1151. PARAMETER_DRYWET,
  1152. 0, 0,
  1153. fixedValue,
  1154. nullptr);
  1155. }
  1156. void CarlaPlugin::setVolume(const float value, const bool sendOsc, const bool sendCallback) noexcept
  1157. {
  1158. if (pData->engineBridged) {
  1159. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1160. } else {
  1161. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1162. }
  1163. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.27f);
  1164. const float fixedValue(carla_fixedValue<float>(0.0f, 1.27f, value));
  1165. if (carla_isEqual(pData->postProc.volume, fixedValue))
  1166. return;
  1167. pData->postProc.volume = fixedValue;
  1168. pData->engine->callback(sendCallback, sendOsc,
  1169. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1170. pData->id,
  1171. PARAMETER_VOLUME,
  1172. 0, 0,
  1173. fixedValue,
  1174. nullptr);
  1175. }
  1176. void CarlaPlugin::setBalanceLeft(const float value, const bool sendOsc, const bool sendCallback) noexcept
  1177. {
  1178. if (pData->engineBridged) {
  1179. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1180. } else {
  1181. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1182. }
  1183. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  1184. const float fixedValue(carla_fixedValue<float>(-1.0f, 1.0f, value));
  1185. if (carla_isEqual(pData->postProc.balanceLeft, fixedValue))
  1186. return;
  1187. pData->postProc.balanceLeft = fixedValue;
  1188. pData->engine->callback(sendCallback, sendOsc,
  1189. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1190. pData->id,
  1191. PARAMETER_BALANCE_LEFT,
  1192. 0, 0,
  1193. fixedValue,
  1194. nullptr);
  1195. }
  1196. void CarlaPlugin::setBalanceRight(const float value, const bool sendOsc, const bool sendCallback) noexcept
  1197. {
  1198. if (pData->engineBridged) {
  1199. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1200. } else {
  1201. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1202. }
  1203. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  1204. const float fixedValue(carla_fixedValue<float>(-1.0f, 1.0f, value));
  1205. if (carla_isEqual(pData->postProc.balanceRight, fixedValue))
  1206. return;
  1207. pData->postProc.balanceRight = fixedValue;
  1208. pData->engine->callback(sendCallback, sendOsc,
  1209. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1210. pData->id,
  1211. PARAMETER_BALANCE_RIGHT,
  1212. 0, 0,
  1213. fixedValue,
  1214. nullptr);
  1215. }
  1216. void CarlaPlugin::setPanning(const float value, const bool sendOsc, const bool sendCallback) noexcept
  1217. {
  1218. if (pData->engineBridged) {
  1219. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1220. } else {
  1221. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1222. }
  1223. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  1224. const float fixedValue(carla_fixedValue<float>(-1.0f, 1.0f, value));
  1225. if (carla_isEqual(pData->postProc.panning, fixedValue))
  1226. return;
  1227. pData->postProc.panning = fixedValue;
  1228. pData->engine->callback(sendCallback, sendOsc,
  1229. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1230. pData->id,
  1231. PARAMETER_PANNING,
  1232. 0, 0,
  1233. fixedValue,
  1234. nullptr);
  1235. }
  1236. void CarlaPlugin::setDryWetRT(const float value, const bool sendCallbackLater) noexcept
  1237. {
  1238. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f);
  1239. const float fixedValue(carla_fixedValue<float>(0.0f, 1.0f, value));
  1240. if (carla_isEqual(pData->postProc.dryWet, fixedValue))
  1241. return;
  1242. pData->postProc.dryWet = fixedValue;
  1243. pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_DRYWET, 0, 0, fixedValue);
  1244. }
  1245. void CarlaPlugin::setVolumeRT(const float value, const bool sendCallbackLater) noexcept
  1246. {
  1247. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.27f);
  1248. const float fixedValue(carla_fixedValue<float>(0.0f, 1.27f, value));
  1249. if (carla_isEqual(pData->postProc.volume, fixedValue))
  1250. return;
  1251. pData->postProc.volume = fixedValue;
  1252. pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_VOLUME, 0, 0, fixedValue);
  1253. }
  1254. void CarlaPlugin::setBalanceLeftRT(const float value, const bool sendCallbackLater) noexcept
  1255. {
  1256. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  1257. const float fixedValue(carla_fixedValue<float>(-1.0f, 1.0f, value));
  1258. if (carla_isEqual(pData->postProc.balanceLeft, fixedValue))
  1259. return;
  1260. pData->postProc.balanceLeft = fixedValue;
  1261. pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_BALANCE_LEFT, 0, 0, fixedValue);
  1262. }
  1263. void CarlaPlugin::setBalanceRightRT(const float value, const bool sendCallbackLater) noexcept
  1264. {
  1265. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  1266. const float fixedValue(carla_fixedValue<float>(-1.0f, 1.0f, value));
  1267. if (carla_isEqual(pData->postProc.balanceRight, fixedValue))
  1268. return;
  1269. pData->postProc.balanceRight = fixedValue;
  1270. pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_BALANCE_RIGHT, 0, 0, fixedValue);
  1271. }
  1272. void CarlaPlugin::setPanningRT(const float value, const bool sendCallbackLater) noexcept
  1273. {
  1274. CARLA_SAFE_ASSERT(value >= -1.0f && value <= 1.0f);
  1275. const float fixedValue(carla_fixedValue<float>(-1.0f, 1.0f, value));
  1276. if (carla_isEqual(pData->postProc.panning, fixedValue))
  1277. return;
  1278. pData->postProc.panning = fixedValue;
  1279. pData->postponeRtEvent(kPluginPostRtEventParameterChange, sendCallbackLater, PARAMETER_PANNING, 0, 0, fixedValue);
  1280. }
  1281. #endif // ! BUILD_BRIDGE_ALTERNATIVE_ARCH
  1282. void CarlaPlugin::setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept
  1283. {
  1284. if (pData->engineBridged) {
  1285. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1286. } else {
  1287. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1288. }
  1289. CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,);
  1290. if (pData->ctrlChannel == channel)
  1291. return;
  1292. pData->ctrlChannel = channel;
  1293. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1294. const float channelf = static_cast<float>(channel);
  1295. pData->engine->callback(sendCallback, sendOsc,
  1296. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1297. pData->id,
  1298. PARAMETER_CTRL_CHANNEL,
  1299. 0, 0,
  1300. channelf, nullptr);
  1301. #endif
  1302. }
  1303. // -------------------------------------------------------------------
  1304. // Set data (plugin-specific stuff)
  1305. void CarlaPlugin::setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  1306. {
  1307. if (pData->engineBridged) {
  1308. // NOTE: some LV2 plugins feedback messages to UI on purpose
  1309. CARLA_SAFE_ASSERT_RETURN(getType() == PLUGIN_LV2 || !sendGui,);
  1310. } else if (pData->enginePlugin) {
  1311. // nothing here
  1312. } else {
  1313. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  1314. }
  1315. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  1316. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1317. uiParameterChange(parameterId, value);
  1318. pData->engine->callback(sendCallback, sendOsc,
  1319. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1320. pData->id,
  1321. static_cast<int>(parameterId),
  1322. 0, 0,
  1323. value,
  1324. nullptr);
  1325. }
  1326. void CarlaPlugin::setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept
  1327. {
  1328. pData->postponeRtEvent(kPluginPostRtEventParameterChange,
  1329. sendCallbackLater, static_cast<int32_t>(parameterId), 0, 0, value);
  1330. }
  1331. void CarlaPlugin::setParameterValueByRealIndex(const int32_t rindex, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  1332. {
  1333. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1334. CARLA_SAFE_ASSERT_RETURN(rindex > PARAMETER_MAX && rindex != PARAMETER_NULL,);
  1335. switch (rindex)
  1336. {
  1337. case PARAMETER_ACTIVE:
  1338. return setActive((value > 0.0f), sendOsc, sendCallback);
  1339. case PARAMETER_CTRL_CHANNEL:
  1340. return setCtrlChannel(int8_t(value), sendOsc, sendCallback);
  1341. case PARAMETER_DRYWET:
  1342. return setDryWet(value, sendOsc, sendCallback);
  1343. case PARAMETER_VOLUME:
  1344. return setVolume(value, sendOsc, sendCallback);
  1345. case PARAMETER_BALANCE_LEFT:
  1346. return setBalanceLeft(value, sendOsc, sendCallback);
  1347. case PARAMETER_BALANCE_RIGHT:
  1348. return setBalanceRight(value, sendOsc, sendCallback);
  1349. case PARAMETER_PANNING:
  1350. return setPanning(value, sendOsc, sendCallback);
  1351. }
  1352. #endif
  1353. CARLA_SAFE_ASSERT_RETURN(rindex >= 0,);
  1354. for (uint32_t i=0; i < pData->param.count; ++i)
  1355. {
  1356. if (pData->param.data[i].rindex == rindex)
  1357. {
  1358. //if (carla_isNotEqual(getParameterValue(i), value))
  1359. setParameterValue(i, value, sendGui, sendOsc, sendCallback);
  1360. break;
  1361. }
  1362. }
  1363. }
  1364. void CarlaPlugin::setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept
  1365. {
  1366. if (pData->engineBridged) {
  1367. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1368. } else {
  1369. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1370. }
  1371. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  1372. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1373. if (pData->param.data[parameterId].midiChannel == channel)
  1374. return;
  1375. pData->param.data[parameterId].midiChannel = channel;
  1376. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1377. pData->engine->callback(sendCallback, sendOsc,
  1378. ENGINE_CALLBACK_PARAMETER_MIDI_CHANNEL_CHANGED,
  1379. pData->id,
  1380. static_cast<int>(parameterId),
  1381. channel,
  1382. 0, 0.0f, nullptr);
  1383. #endif
  1384. }
  1385. void CarlaPlugin::setParameterMappedControlIndex(const uint32_t parameterId, const int16_t index, const bool sendOsc, const bool sendCallback) noexcept
  1386. {
  1387. if (pData->engineBridged) {
  1388. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1389. } else {
  1390. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1391. }
  1392. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  1393. CARLA_SAFE_ASSERT_RETURN(index >= CONTROL_INDEX_NONE && index <= CONTROL_INDEX_MAX_ALLOWED,);
  1394. ParameterData& paramData(pData->param.data[parameterId]);
  1395. if (paramData.mappedControlIndex == index)
  1396. return;
  1397. const ParameterRanges& paramRanges(pData->param.ranges[parameterId]);
  1398. if ((paramData.hints & PARAMETER_MAPPED_RANGES_SET) == 0x0)
  1399. setParameterMappedRange(parameterId, paramRanges.min, paramRanges.max, true, true);
  1400. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1401. char strBuf[STR_MAX+1];
  1402. carla_zeroChars(strBuf, STR_MAX+1);
  1403. if (! getParameterName(parameterId, strBuf))
  1404. std::snprintf(strBuf, STR_MAX, "Param %u", parameterId);
  1405. const uint portNameSize = pData->engine->getMaxPortNameSize();
  1406. if (portNameSize < STR_MAX)
  1407. strBuf[portNameSize] = '\0';
  1408. if (index == CONTROL_INDEX_CV)
  1409. {
  1410. CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,);
  1411. CARLA_SAFE_ASSERT_RETURN(paramData.type == PARAMETER_INPUT,);
  1412. CARLA_SAFE_ASSERT_RETURN(paramData.hints & PARAMETER_CAN_BE_CV_CONTROLLED,);
  1413. CarlaEngineCVPort* const cvPort =
  1414. (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, strBuf, true, parameterId);
  1415. cvPort->setRange(paramData.mappedMinimum, paramData.mappedMaximum);
  1416. pData->event.cvSourcePorts->addCVSource(cvPort, parameterId);
  1417. }
  1418. else if (paramData.mappedControlIndex == CONTROL_INDEX_CV)
  1419. {
  1420. CARLA_SAFE_ASSERT_RETURN(pData->event.cvSourcePorts != nullptr,);
  1421. CARLA_SAFE_ASSERT(pData->client->removePort(kEnginePortTypeCV, strBuf, true));
  1422. CARLA_SAFE_ASSERT(pData->event.cvSourcePorts->removeCVSource(parameterId));
  1423. }
  1424. else if (paramData.mappedControlIndex == CONTROL_INDEX_NONE)
  1425. {
  1426. // when doing MIDI CC mapping, ensure ranges are within bounds
  1427. if (paramData.mappedMinimum < paramRanges.min || paramData.mappedMaximum > paramRanges.max)
  1428. setParameterMappedRange(parameterId,
  1429. std::max(paramData.mappedMinimum, paramRanges.min),
  1430. std::min(paramData.mappedMaximum, paramRanges.max),
  1431. true, true);
  1432. }
  1433. #endif
  1434. paramData.mappedControlIndex = index;
  1435. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1436. pData->engine->callback(sendCallback, sendOsc,
  1437. ENGINE_CALLBACK_PARAMETER_MAPPED_CONTROL_INDEX_CHANGED,
  1438. pData->id,
  1439. static_cast<int>(parameterId),
  1440. index,
  1441. 0, 0.0f, nullptr);
  1442. #endif
  1443. }
  1444. void CarlaPlugin::setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept
  1445. {
  1446. if (pData->engineBridged) {
  1447. CARLA_SAFE_ASSERT_RETURN(!sendOsc && !sendCallback,);
  1448. } else {
  1449. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  1450. }
  1451. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  1452. ParameterData& paramData(pData->param.data[parameterId]);
  1453. if (carla_isEqual(paramData.mappedMinimum, minimum) &&
  1454. carla_isEqual(paramData.mappedMaximum, maximum) &&
  1455. (paramData.hints & PARAMETER_MAPPED_RANGES_SET) != 0x0)
  1456. return;
  1457. if (paramData.mappedControlIndex != CONTROL_INDEX_NONE && paramData.mappedControlIndex != CONTROL_INDEX_CV)
  1458. {
  1459. const ParameterRanges& paramRanges(pData->param.ranges[parameterId]);
  1460. CARLA_SAFE_ASSERT_RETURN(minimum >= paramRanges.min,);
  1461. CARLA_SAFE_ASSERT_RETURN(maximum <= paramRanges.max,);
  1462. }
  1463. paramData.hints |= PARAMETER_MAPPED_RANGES_SET;
  1464. paramData.mappedMinimum = minimum;
  1465. paramData.mappedMaximum = maximum;
  1466. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1467. if (pData->event.cvSourcePorts != nullptr && paramData.mappedControlIndex == CONTROL_INDEX_CV)
  1468. pData->event.cvSourcePorts->setCVSourceRange(parameterId, minimum, maximum);
  1469. char strBuf[STR_MAX+1];
  1470. carla_zeroChars(strBuf, STR_MAX+1);
  1471. std::snprintf(strBuf, STR_MAX, "%.12g:%.12g", static_cast<double>(minimum), static_cast<double>(maximum));
  1472. pData->engine->callback(sendCallback, sendOsc,
  1473. ENGINE_CALLBACK_PARAMETER_MAPPED_RANGE_CHANGED,
  1474. pData->id,
  1475. static_cast<int>(parameterId),
  1476. 0, 0, 0.0f,
  1477. strBuf);
  1478. #endif
  1479. }
  1480. void CarlaPlugin::setCustomData(const char* const type, const char* const key, const char* const value, const bool)
  1481. {
  1482. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  1483. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  1484. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  1485. // Ignore some keys
  1486. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0)
  1487. {
  1488. const PluginType ptype = getType();
  1489. if ((ptype == PLUGIN_INTERNAL && std::strncmp(key, "CarlaAlternateFile", 18) == 0) ||
  1490. (ptype == PLUGIN_DSSI && std::strcmp (key, "guiVisible") == 0) ||
  1491. (ptype == PLUGIN_LV2 && std::strncmp(key, "OSC:", 4) == 0))
  1492. return;
  1493. }
  1494. // Check if we already have this key
  1495. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
  1496. {
  1497. CustomData& customData(it.getValue(kCustomDataFallbackNC));
  1498. CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  1499. if (std::strcmp(customData.key, key) == 0)
  1500. {
  1501. if (customData.value != nullptr)
  1502. delete[] customData.value;
  1503. customData.value = carla_strdup(value);
  1504. return;
  1505. }
  1506. }
  1507. // Otherwise store it
  1508. CustomData customData;
  1509. customData.type = carla_strdup(type);
  1510. customData.key = carla_strdup(key);
  1511. customData.value = carla_strdup(value);
  1512. pData->custom.append(customData);
  1513. }
  1514. void CarlaPlugin::setChunkData(const void* const data, const std::size_t dataSize)
  1515. {
  1516. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  1517. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  1518. CARLA_SAFE_ASSERT(false); // this should never happen
  1519. }
  1520. void CarlaPlugin::setProgram(const int32_t index,
  1521. const bool sendGui, const bool sendOsc, const bool sendCallback, const bool) noexcept
  1522. {
  1523. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  1524. pData->prog.current = index;
  1525. pData->engine->callback(sendCallback, sendOsc,
  1526. ENGINE_CALLBACK_PROGRAM_CHANGED,
  1527. pData->id,
  1528. index,
  1529. 0, 0, 0.0f, nullptr);
  1530. // Change default parameter values
  1531. if (index >= 0)
  1532. {
  1533. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1534. uiProgramChange(static_cast<uint32_t>(index));
  1535. switch (getType())
  1536. {
  1537. case PLUGIN_SF2:
  1538. case PLUGIN_SFZ:
  1539. break;
  1540. default:
  1541. pData->updateParameterValues(this, sendCallback, sendOsc, true);
  1542. break;
  1543. }
  1544. }
  1545. }
  1546. void CarlaPlugin::setMidiProgram(const int32_t index,
  1547. const bool sendGui, const bool sendOsc, const bool sendCallback, const bool) noexcept
  1548. {
  1549. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  1550. pData->midiprog.current = index;
  1551. pData->engine->callback(sendCallback, sendOsc,
  1552. ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED,
  1553. pData->id,
  1554. index,
  1555. 0, 0, 0.0f, nullptr);
  1556. // Change default parameter values
  1557. if (index >= 0)
  1558. {
  1559. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1560. uiMidiProgramChange(static_cast<uint32_t>(index));
  1561. switch (getType())
  1562. {
  1563. case PLUGIN_SF2:
  1564. case PLUGIN_SFZ:
  1565. break;
  1566. default:
  1567. pData->updateParameterValues(this, sendCallback, sendOsc, true);
  1568. break;
  1569. }
  1570. }
  1571. }
  1572. void CarlaPlugin::setMidiProgramById(const uint32_t bank, const uint32_t program, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept
  1573. {
  1574. for (uint32_t i=0; i < pData->midiprog.count; ++i)
  1575. {
  1576. if (pData->midiprog.data[i].bank == bank && pData->midiprog.data[i].program == program)
  1577. return setMidiProgram(static_cast<int32_t>(i), sendGui, sendOsc, sendCallback);
  1578. }
  1579. }
  1580. void CarlaPlugin::setProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept
  1581. {
  1582. CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,);
  1583. const int32_t index = static_cast<int32_t>(uindex);
  1584. pData->prog.current = index;
  1585. // Change default parameter values
  1586. switch (getType())
  1587. {
  1588. case PLUGIN_SF2:
  1589. case PLUGIN_SFZ:
  1590. break;
  1591. default:
  1592. pData->updateDefaultParameterValues(this);
  1593. break;
  1594. }
  1595. pData->postponeRtEvent(kPluginPostRtEventProgramChange, sendCallbackLater, index, 0, 0, 0.0f);
  1596. }
  1597. void CarlaPlugin::setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept
  1598. {
  1599. CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
  1600. const int32_t index = static_cast<int32_t>(uindex);
  1601. pData->midiprog.current = index;
  1602. // Change default parameter values
  1603. switch (getType())
  1604. {
  1605. case PLUGIN_SF2:
  1606. case PLUGIN_SFZ:
  1607. break;
  1608. default:
  1609. pData->updateDefaultParameterValues(this);
  1610. break;
  1611. }
  1612. pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, sendCallbackLater, index, 0, 0, 0.0f);
  1613. }
  1614. // -------------------------------------------------------------------
  1615. // Plugin state
  1616. void CarlaPlugin::reloadPrograms(const bool)
  1617. {
  1618. }
  1619. // -------------------------------------------------------------------
  1620. // Plugin processing
  1621. void CarlaPlugin::activate() noexcept
  1622. {
  1623. CARLA_SAFE_ASSERT(! pData->active);
  1624. }
  1625. void CarlaPlugin::deactivate() noexcept
  1626. {
  1627. CARLA_SAFE_ASSERT(pData->active);
  1628. }
  1629. void CarlaPlugin::bufferSizeChanged(const uint32_t)
  1630. {
  1631. }
  1632. void CarlaPlugin::sampleRateChanged(const double)
  1633. {
  1634. }
  1635. void CarlaPlugin::offlineModeChanged(const bool)
  1636. {
  1637. }
  1638. // -------------------------------------------------------------------
  1639. // Misc
  1640. void CarlaPlugin::idle()
  1641. {
  1642. if (! pData->enabled)
  1643. return;
  1644. const bool hasUI(pData->hints & PLUGIN_HAS_CUSTOM_UI);
  1645. const bool needsUiMainThread(pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD);
  1646. const uint32_t latency(getLatencyInFrames());
  1647. if (pData->latency.frames != latency)
  1648. {
  1649. carla_stdout("latency changed to %i samples", latency);
  1650. const ScopedSingleProcessLocker sspl(this, true);
  1651. pData->client->setLatency(latency);
  1652. #ifndef BUILD_BRIDGE
  1653. pData->latency.recreateBuffers(pData->latency.channels, latency);
  1654. #else
  1655. pData->latency.frames = latency;
  1656. #endif
  1657. }
  1658. ProtectedData::PostRtEvents::Access rtEvents(pData->postRtEvents);
  1659. if (rtEvents.isEmpty())
  1660. return;
  1661. for (RtLinkedList<PluginPostRtEvent>::Itenerator it = rtEvents.getDataIterator(); it.valid(); it.next())
  1662. {
  1663. const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback));
  1664. CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull);
  1665. switch (event.type)
  1666. {
  1667. case kPluginPostRtEventNull: {
  1668. } break;
  1669. case kPluginPostRtEventDebug: {
  1670. pData->engine->callback(true, true,
  1671. ENGINE_CALLBACK_DEBUG, pData->id,
  1672. event.value1, event.value2, event.value3, event.valuef, nullptr);
  1673. } break;
  1674. case kPluginPostRtEventParameterChange: {
  1675. // Update UI
  1676. if (event.value1 >= 0 && hasUI)
  1677. {
  1678. if (needsUiMainThread)
  1679. pData->postUiEvents.append(event);
  1680. else
  1681. uiParameterChange(static_cast<uint32_t>(event.value1), event.valuef);
  1682. }
  1683. if (event.sendCallback)
  1684. {
  1685. // Update Host
  1686. pData->engine->callback(true, true,
  1687. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1688. pData->id,
  1689. event.value1,
  1690. 0, 0,
  1691. event.valuef,
  1692. nullptr);
  1693. }
  1694. } break;
  1695. case kPluginPostRtEventProgramChange: {
  1696. // Update UI
  1697. if (event.value1 >= 0 && hasUI)
  1698. {
  1699. if (needsUiMainThread)
  1700. pData->postUiEvents.append(event);
  1701. else
  1702. uiProgramChange(static_cast<uint32_t>(event.value1));
  1703. }
  1704. // Update param values
  1705. for (uint32_t j=0; j < pData->param.count; ++j)
  1706. {
  1707. const float paramDefault(pData->param.ranges[j].def);
  1708. const float paramValue(getParameterValue(j));
  1709. pData->engine->callback(true, true,
  1710. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1711. pData->id,
  1712. static_cast<int>(j),
  1713. 0, 0,
  1714. paramValue,
  1715. nullptr);
  1716. pData->engine->callback(true, true,
  1717. ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED,
  1718. pData->id,
  1719. static_cast<int>(j),
  1720. 0, 0,
  1721. paramDefault,
  1722. nullptr);
  1723. }
  1724. if (event.sendCallback)
  1725. {
  1726. // Update Host
  1727. pData->engine->callback(true, true,
  1728. ENGINE_CALLBACK_PROGRAM_CHANGED,
  1729. pData->id,
  1730. event.value1,
  1731. 0, 0, 0.0f, nullptr);
  1732. }
  1733. } break;
  1734. case kPluginPostRtEventMidiProgramChange: {
  1735. // Update UI
  1736. if (event.value1 >= 0 && hasUI)
  1737. {
  1738. if (needsUiMainThread)
  1739. pData->postUiEvents.append(event);
  1740. else
  1741. uiMidiProgramChange(static_cast<uint32_t>(event.value1));
  1742. }
  1743. // Update param values
  1744. for (uint32_t j=0; j < pData->param.count; ++j)
  1745. {
  1746. const float paramDefault(pData->param.ranges[j].def);
  1747. const float paramValue(getParameterValue(j));
  1748. pData->engine->callback(true, true,
  1749. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  1750. pData->id,
  1751. static_cast<int>(j),
  1752. 0, 0,
  1753. paramValue,
  1754. nullptr);
  1755. pData->engine->callback(true, true,
  1756. ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED,
  1757. pData->id,
  1758. static_cast<int>(j),
  1759. 0, 0,
  1760. paramDefault,
  1761. nullptr);
  1762. }
  1763. if (event.sendCallback)
  1764. {
  1765. // Update Host
  1766. pData->engine->callback(true, true,
  1767. ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED,
  1768. pData->id,
  1769. event.value1,
  1770. 0, 0, 0.0f, nullptr);
  1771. }
  1772. } break;
  1773. case kPluginPostRtEventNoteOn: {
  1774. CARLA_SAFE_ASSERT_BREAK(event.value1 >= 0 && event.value1 < MAX_MIDI_CHANNELS);
  1775. CARLA_SAFE_ASSERT_BREAK(event.value2 >= 0 && event.value2 < MAX_MIDI_NOTE);
  1776. CARLA_SAFE_ASSERT_BREAK(event.value3 >= 0 && event.value3 < MAX_MIDI_VALUE);
  1777. const uint8_t channel = static_cast<uint8_t>(event.value1);
  1778. const uint8_t note = static_cast<uint8_t>(event.value2);
  1779. const uint8_t velocity = static_cast<uint8_t>(event.value3);
  1780. // Update UI
  1781. if (hasUI)
  1782. {
  1783. if (needsUiMainThread)
  1784. pData->postUiEvents.append(event);
  1785. else
  1786. uiNoteOn(channel, note, velocity);
  1787. }
  1788. if (event.sendCallback)
  1789. {
  1790. // Update Host
  1791. pData->engine->callback(true, true,
  1792. ENGINE_CALLBACK_NOTE_ON,
  1793. pData->id,
  1794. event.value1,
  1795. event.value2,
  1796. event.value3,
  1797. 0.0f, nullptr);
  1798. }
  1799. } break;
  1800. case kPluginPostRtEventNoteOff: {
  1801. CARLA_SAFE_ASSERT_BREAK(event.value1 >= 0 && event.value1 < MAX_MIDI_CHANNELS);
  1802. CARLA_SAFE_ASSERT_BREAK(event.value2 >= 0 && event.value2 < MAX_MIDI_NOTE);
  1803. const uint8_t channel = static_cast<uint8_t>(event.value1);
  1804. const uint8_t note = static_cast<uint8_t>(event.value2);
  1805. // Update UI
  1806. if (hasUI)
  1807. {
  1808. if (needsUiMainThread)
  1809. pData->postUiEvents.append(event);
  1810. else
  1811. uiNoteOff(channel, note);
  1812. }
  1813. if (event.sendCallback)
  1814. {
  1815. // Update Host
  1816. pData->engine->callback(true, true,
  1817. ENGINE_CALLBACK_NOTE_OFF,
  1818. pData->id,
  1819. event.value1,
  1820. event.value2,
  1821. 0, 0.0f, nullptr);
  1822. }
  1823. } break;
  1824. }
  1825. }
  1826. }
  1827. bool CarlaPlugin::tryLock(const bool forcedOffline) noexcept
  1828. {
  1829. if (forcedOffline)
  1830. {
  1831. #ifndef STOAT_TEST_BUILD
  1832. pData->masterMutex.lock();
  1833. return true;
  1834. #endif
  1835. }
  1836. return pData->masterMutex.tryLock();
  1837. }
  1838. void CarlaPlugin::unlock() noexcept
  1839. {
  1840. pData->masterMutex.unlock();
  1841. }
  1842. // -------------------------------------------------------------------
  1843. // Plugin buffers
  1844. void CarlaPlugin::initBuffers() const noexcept
  1845. {
  1846. pData->audioIn.initBuffers();
  1847. pData->audioOut.initBuffers();
  1848. pData->cvIn.initBuffers();
  1849. pData->cvOut.initBuffers();
  1850. pData->event.initBuffers();
  1851. }
  1852. void CarlaPlugin::clearBuffers() noexcept
  1853. {
  1854. pData->clearBuffers();
  1855. }
  1856. // -------------------------------------------------------------------
  1857. // OSC stuff
  1858. // FIXME
  1859. void CarlaPlugin::handleOscMessage(const char* const, const int, const void* const, const char* const, const lo_message)
  1860. {
  1861. // do nothing
  1862. }
  1863. // -------------------------------------------------------------------
  1864. // MIDI events
  1865. void CarlaPlugin::sendMidiSingleNote(const uint8_t channel, const uint8_t note, const uint8_t velo, const bool sendGui, const bool sendOsc, const bool sendCallback)
  1866. {
  1867. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1868. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1869. CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,);
  1870. if (! pData->active)
  1871. return;
  1872. ExternalMidiNote extNote;
  1873. extNote.channel = static_cast<int8_t>(channel);
  1874. extNote.note = note;
  1875. extNote.velo = velo;
  1876. pData->extNotes.appendNonRT(extNote);
  1877. if (sendGui && (pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0)
  1878. {
  1879. if (velo > 0)
  1880. uiNoteOn(channel, note, velo);
  1881. else
  1882. uiNoteOff(channel, note);
  1883. }
  1884. pData->engine->callback(sendCallback, sendOsc,
  1885. (velo > 0) ? ENGINE_CALLBACK_NOTE_ON : ENGINE_CALLBACK_NOTE_OFF,
  1886. pData->id,
  1887. channel,
  1888. note,
  1889. velo,
  1890. 0.0f, nullptr);
  1891. }
  1892. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1893. void CarlaPlugin::postponeRtAllNotesOff()
  1894. {
  1895. if (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS)
  1896. return;
  1897. PluginPostRtEvent postEvent = {
  1898. kPluginPostRtEventNoteOff,
  1899. true,
  1900. pData->ctrlChannel,
  1901. 0, 0, 0.0f
  1902. };
  1903. for (int32_t i=0; i < MAX_MIDI_NOTE; ++i)
  1904. {
  1905. postEvent.value2 = i;
  1906. pData->postRtEvents.appendRT(postEvent);
  1907. }
  1908. }
  1909. #endif
  1910. // -------------------------------------------------------------------
  1911. // UI Stuff
  1912. void CarlaPlugin::showCustomUI(const bool yesNo)
  1913. {
  1914. if (yesNo) {
  1915. CARLA_SAFE_ASSERT(false);
  1916. }
  1917. }
  1918. void CarlaPlugin::uiIdle()
  1919. {
  1920. if (pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD)
  1921. {
  1922. // Update parameter outputs
  1923. for (uint32_t i=0; i < pData->param.count; ++i)
  1924. {
  1925. if (pData->param.data[i].type == PARAMETER_OUTPUT)
  1926. uiParameterChange(i, getParameterValue(i));
  1927. }
  1928. const CarlaMutexLocker sl(pData->postUiEvents.mutex);
  1929. for (LinkedList<PluginPostRtEvent>::Itenerator it = pData->postUiEvents.data.begin2(); it.valid(); it.next())
  1930. {
  1931. const PluginPostRtEvent& event(it.getValue(kPluginPostRtEventFallback));
  1932. CARLA_SAFE_ASSERT_CONTINUE(event.type != kPluginPostRtEventNull);
  1933. switch (event.type)
  1934. {
  1935. case kPluginPostRtEventNull:
  1936. case kPluginPostRtEventDebug:
  1937. break;
  1938. case kPluginPostRtEventParameterChange:
  1939. uiParameterChange(static_cast<uint32_t>(event.value1), event.valuef);
  1940. break;
  1941. case kPluginPostRtEventProgramChange:
  1942. uiProgramChange(static_cast<uint32_t>(event.value1));
  1943. break;
  1944. case kPluginPostRtEventMidiProgramChange:
  1945. uiMidiProgramChange(static_cast<uint32_t>(event.value1));
  1946. break;
  1947. case kPluginPostRtEventNoteOn:
  1948. uiNoteOn(static_cast<uint8_t>(event.value1),
  1949. static_cast<uint8_t>(event.value2),
  1950. static_cast<uint8_t>(event.value3));
  1951. break;
  1952. case kPluginPostRtEventNoteOff:
  1953. uiNoteOff(static_cast<uint8_t>(event.value1),
  1954. static_cast<uint8_t>(event.value2));
  1955. break;
  1956. }
  1957. }
  1958. pData->postUiEvents.data.clear();
  1959. }
  1960. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1961. if (pData->transientTryCounter == 0)
  1962. return;
  1963. if (++pData->transientTryCounter % 10 != 0)
  1964. return;
  1965. if (pData->transientTryCounter >= 200)
  1966. return;
  1967. carla_stdout("Trying to get window...");
  1968. CarlaString uiTitle(pData->name);
  1969. uiTitle += " (GUI)";
  1970. if (CarlaPluginUI::tryTransientWinIdMatch(getUiBridgeProcessId(), uiTitle,
  1971. pData->engine->getOptions().frontendWinId, pData->transientFirstTry))
  1972. {
  1973. pData->transientTryCounter = 0;
  1974. pData->transientFirstTry = false;
  1975. }
  1976. #endif
  1977. }
  1978. void CarlaPlugin::uiParameterChange(const uint32_t index, const float value) noexcept
  1979. {
  1980. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  1981. return;
  1982. // unused
  1983. (void)value;
  1984. }
  1985. void CarlaPlugin::uiProgramChange(const uint32_t index) noexcept
  1986. {
  1987. CARLA_SAFE_ASSERT_RETURN(index < getProgramCount(),);
  1988. }
  1989. void CarlaPlugin::uiMidiProgramChange(const uint32_t index) noexcept
  1990. {
  1991. CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(),);
  1992. }
  1993. void CarlaPlugin::uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept
  1994. {
  1995. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1996. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1997. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1998. }
  1999. void CarlaPlugin::uiNoteOff(const uint8_t channel, const uint8_t note) noexcept
  2000. {
  2001. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  2002. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  2003. }
  2004. CarlaEngine* CarlaPlugin::getEngine() const noexcept
  2005. {
  2006. return pData->engine;
  2007. }
  2008. CarlaEngineClient* CarlaPlugin::getEngineClient() const noexcept
  2009. {
  2010. return pData->client;
  2011. }
  2012. CarlaEngineAudioPort* CarlaPlugin::getAudioInPort(const uint32_t index) const noexcept
  2013. {
  2014. return pData->audioIn.ports[index].port;
  2015. }
  2016. CarlaEngineAudioPort* CarlaPlugin::getAudioOutPort(const uint32_t index) const noexcept
  2017. {
  2018. return pData->audioOut.ports[index].port;
  2019. }
  2020. CarlaEngineCVPort* CarlaPlugin::getCVInPort(const uint32_t index) const noexcept
  2021. {
  2022. return pData->cvIn.ports[index].port;
  2023. }
  2024. CarlaEngineCVPort* CarlaPlugin::getCVOutPort(const uint32_t index) const noexcept
  2025. {
  2026. return pData->cvOut.ports[index].port;
  2027. }
  2028. CarlaEngineEventPort* CarlaPlugin::getDefaultEventInPort() const noexcept
  2029. {
  2030. return pData->event.portIn;
  2031. }
  2032. CarlaEngineEventPort* CarlaPlugin::getDefaultEventOutPort() const noexcept
  2033. {
  2034. return pData->event.portOut;
  2035. }
  2036. void* CarlaPlugin::getNativeHandle() const noexcept
  2037. {
  2038. return nullptr;
  2039. }
  2040. const void* CarlaPlugin::getNativeDescriptor() const noexcept
  2041. {
  2042. return nullptr;
  2043. }
  2044. uintptr_t CarlaPlugin::getUiBridgeProcessId() const noexcept
  2045. {
  2046. return 0;
  2047. }
  2048. // -------------------------------------------------------------------
  2049. uint32_t CarlaPlugin::getPatchbayNodeId() const noexcept
  2050. {
  2051. return pData->nodeId;
  2052. }
  2053. void CarlaPlugin::setPatchbayNodeId(const uint32_t nodeId) noexcept
  2054. {
  2055. pData->nodeId = nodeId;
  2056. }
  2057. // -------------------------------------------------------------------
  2058. void CarlaPlugin::restoreLV2State() noexcept
  2059. {
  2060. carla_stderr2("Warning: restoreLV2State() called for non-implemented type");
  2061. }
  2062. void CarlaPlugin::waitForBridgeSaveSignal() noexcept
  2063. {
  2064. }
  2065. // -------------------------------------------------------------------
  2066. // Scoped Disabler
  2067. CarlaPlugin::ScopedDisabler::ScopedDisabler(CarlaPlugin* const plugin) noexcept
  2068. : fPlugin(plugin),
  2069. fWasEnabled(false)
  2070. {
  2071. CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,);
  2072. CARLA_SAFE_ASSERT_RETURN(plugin->pData != nullptr,);
  2073. CARLA_SAFE_ASSERT_RETURN(plugin->pData->client != nullptr,);
  2074. carla_debug("CarlaPlugin::ScopedDisabler(%p)", plugin);
  2075. plugin->pData->masterMutex.lock();
  2076. if (plugin->pData->enabled)
  2077. {
  2078. fWasEnabled = true;
  2079. plugin->pData->enabled = false;
  2080. if (plugin->pData->client->isActive())
  2081. plugin->pData->client->deactivate();
  2082. }
  2083. }
  2084. CarlaPlugin::ScopedDisabler::~ScopedDisabler() noexcept
  2085. {
  2086. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  2087. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,);
  2088. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData->client != nullptr,);
  2089. carla_debug("CarlaPlugin::~ScopedDisabler()");
  2090. if (fWasEnabled)
  2091. {
  2092. fPlugin->pData->enabled = true;
  2093. fPlugin->pData->client->activate();
  2094. }
  2095. fPlugin->pData->masterMutex.unlock();
  2096. }
  2097. // -------------------------------------------------------------------
  2098. // Scoped Process Locker
  2099. CarlaPlugin::ScopedSingleProcessLocker::ScopedSingleProcessLocker(CarlaPlugin* const plugin, const bool block) noexcept
  2100. : fPlugin(plugin),
  2101. fBlock(block)
  2102. {
  2103. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  2104. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,);
  2105. carla_debug("CarlaPlugin::ScopedSingleProcessLocker(%p, %s)", plugin, bool2str(block));
  2106. if (! fBlock)
  2107. return;
  2108. plugin->pData->singleMutex.lock();
  2109. }
  2110. CarlaPlugin::ScopedSingleProcessLocker::~ScopedSingleProcessLocker() noexcept
  2111. {
  2112. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  2113. CARLA_SAFE_ASSERT_RETURN(fPlugin->pData != nullptr,);
  2114. carla_debug("CarlaPlugin::~ScopedSingleProcessLocker()");
  2115. if (! fBlock)
  2116. return;
  2117. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2118. if (fPlugin->pData->singleMutex.wasTryLockCalled())
  2119. fPlugin->pData->needsReset = true;
  2120. #endif
  2121. fPlugin->pData->singleMutex.unlock();
  2122. }
  2123. // -------------------------------------------------------------------
  2124. CARLA_BACKEND_END_NAMESPACE