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.

DssiPlugin.cpp 82KB

11 years ago
11 years ago
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
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
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
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
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
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
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
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
10 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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311
  1. /*
  2. * Carla DSSI Plugin
  3. * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #include "CarlaEngine.hpp"
  19. #ifdef WANT_DSSI
  20. #include "CarlaDssiUtils.hpp"
  21. #include "CarlaBase64Utils.hpp"
  22. #include "CarlaMathUtils.hpp"
  23. CARLA_BACKEND_START_NAMESPACE
  24. // -----------------------------------------------------
  25. class DssiPlugin : public CarlaPlugin
  26. {
  27. public:
  28. DssiPlugin(CarlaEngine* const engine, const uint id) noexcept
  29. : CarlaPlugin(engine, id),
  30. fHandle(nullptr),
  31. fHandle2(nullptr),
  32. fDescriptor(nullptr),
  33. fDssiDescriptor(nullptr),
  34. fUsesCustomData(false),
  35. fUiFilename(nullptr),
  36. fAudioInBuffers(nullptr),
  37. fAudioOutBuffers(nullptr),
  38. fParamBuffers(nullptr),
  39. fLatencyChanged(false),
  40. fLatencyIndex(-1)
  41. {
  42. carla_debug("DssiPlugin::DssiPlugin(%p, %i)", engine, id);
  43. pData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI);
  44. }
  45. ~DssiPlugin() noexcept override
  46. {
  47. carla_debug("DssiPlugin::~DssiPlugin()");
  48. // close UI
  49. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  50. {
  51. showCustomUI(false);
  52. pData->osc.thread.stopThread(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
  53. }
  54. pData->singleMutex.lock();
  55. pData->masterMutex.lock();
  56. if (pData->client != nullptr && pData->client->isActive())
  57. pData->client->deactivate();
  58. if (pData->active)
  59. {
  60. deactivate();
  61. pData->active = false;
  62. }
  63. if (fDescriptor != nullptr)
  64. {
  65. if (pData->name != nullptr && fDssiDescriptor != nullptr && fDssiDescriptor->run_synth == nullptr && fDssiDescriptor->run_multiple_synths != nullptr)
  66. removeUniqueMultiSynth(fDescriptor->Label);
  67. if (fDescriptor->cleanup != nullptr)
  68. {
  69. if (fHandle != nullptr)
  70. {
  71. try {
  72. fDescriptor->cleanup(fHandle);
  73. } CARLA_SAFE_EXCEPTION("DSSI cleanup");
  74. }
  75. if (fHandle2 != nullptr)
  76. {
  77. try {
  78. fDescriptor->cleanup(fHandle2);
  79. } CARLA_SAFE_EXCEPTION("DSSI cleanup #2");
  80. }
  81. }
  82. fHandle = nullptr;
  83. fHandle2 = nullptr;
  84. fDescriptor = nullptr;
  85. fDssiDescriptor = nullptr;
  86. }
  87. if (fUiFilename != nullptr)
  88. {
  89. delete[] fUiFilename;
  90. fUiFilename = nullptr;
  91. }
  92. clearBuffers();
  93. }
  94. // -------------------------------------------------------------------
  95. // Information (base)
  96. PluginType getType() const noexcept override
  97. {
  98. return PLUGIN_DSSI;
  99. }
  100. PluginCategory getCategory() const noexcept override
  101. {
  102. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr, PLUGIN_CATEGORY_NONE);
  103. if (pData->audioIn.count == 0 && pData->audioOut.count > 0 && (fDssiDescriptor->run_synth != nullptr || fDssiDescriptor->run_multiple_synths != nullptr))
  104. return PLUGIN_CATEGORY_SYNTH;
  105. return CarlaPlugin::getCategory();
  106. }
  107. int64_t getUniqueId() const noexcept override
  108. {
  109. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0);
  110. return static_cast<int64_t>(fDescriptor->UniqueID);
  111. }
  112. // -------------------------------------------------------------------
  113. // Information (count)
  114. // nothing
  115. // -------------------------------------------------------------------
  116. // Information (current data)
  117. int32_t getChunkData(void** const dataPtr) const noexcept override
  118. {
  119. CARLA_SAFE_ASSERT_RETURN(fUsesCustomData, 0);
  120. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  121. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr, 0);
  122. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->get_custom_data != nullptr, 0);
  123. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0);
  124. CARLA_SAFE_ASSERT_RETURN(fHandle2 == nullptr, 0);
  125. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  126. *dataPtr = nullptr;
  127. int ret = 0;
  128. ulong dataSize = 0;
  129. try {
  130. ret = fDssiDescriptor->get_custom_data(fHandle, dataPtr, &dataSize);
  131. } CARLA_SAFE_EXCEPTION_RETURN("DssiPlugin::getChunkData", 0);
  132. return (ret != 0) ? static_cast<int32_t>(dataSize) : 0;
  133. }
  134. // -------------------------------------------------------------------
  135. // Information (per-plugin data)
  136. uint getOptionsAvailable() const noexcept override
  137. {
  138. #ifdef __USE_GNU
  139. const bool isDssiVst(strcasestr(pData->filename, "dssi-vst") != nullptr);
  140. #else
  141. const bool isDssiVst(std::strstr(pData->filename, "dssi-vst") != nullptr);
  142. #endif
  143. uint options = 0x0;
  144. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  145. if (! isDssiVst)
  146. {
  147. if (fLatencyIndex == -1)
  148. options |= PLUGIN_OPTION_FIXED_BUFFERS;
  149. if (pData->engine->getProccessMode() != ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  150. {
  151. if (pData->options & PLUGIN_OPTION_FORCE_STEREO)
  152. options |= PLUGIN_OPTION_FORCE_STEREO;
  153. else if (pData->audioIn.count <= 1 && pData->audioOut.count <= 1 && (pData->audioIn.count != 0 || pData->audioOut.count != 0))
  154. options |= PLUGIN_OPTION_FORCE_STEREO;
  155. }
  156. }
  157. if (fUsesCustomData)
  158. options |= PLUGIN_OPTION_USE_CHUNKS;
  159. if (fDssiDescriptor->run_synth != nullptr || fDssiDescriptor->run_multiple_synths != nullptr)
  160. {
  161. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  162. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  163. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  164. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  165. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  166. }
  167. return options;
  168. }
  169. float getParameterValue(const uint32_t parameterId) const noexcept override
  170. {
  171. CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f);
  172. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  173. return fParamBuffers[parameterId];
  174. }
  175. void getLabel(char* const strBuf) const noexcept override
  176. {
  177. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf));
  178. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Label != nullptr, nullStrBuf(strBuf));
  179. std::strncpy(strBuf, fDescriptor->Label, STR_MAX);
  180. }
  181. void getMaker(char* const strBuf) const noexcept override
  182. {
  183. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf));
  184. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Maker != nullptr, nullStrBuf(strBuf));
  185. std::strncpy(strBuf, fDescriptor->Maker, STR_MAX);
  186. }
  187. void getCopyright(char* const strBuf) const noexcept override
  188. {
  189. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf));
  190. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Copyright != nullptr, nullStrBuf(strBuf));
  191. std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX);
  192. }
  193. void getRealName(char* const strBuf) const noexcept override
  194. {
  195. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf));
  196. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Name != nullptr, nullStrBuf(strBuf));
  197. std::strncpy(strBuf, fDescriptor->Name, STR_MAX);
  198. }
  199. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  200. {
  201. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, nullStrBuf(strBuf));
  202. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf));
  203. const int32_t rindex(pData->param.data[parameterId].rindex);
  204. CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), nullStrBuf(strBuf));
  205. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, nullStrBuf(strBuf));
  206. if (getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, true))
  207. return;
  208. std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX);
  209. }
  210. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  211. {
  212. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf));
  213. const int32_t rindex(pData->param.data[parameterId].rindex);
  214. CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), nullStrBuf(strBuf));
  215. if (getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false))
  216. return;
  217. nullStrBuf(strBuf);
  218. }
  219. // -------------------------------------------------------------------
  220. // Set data (state)
  221. // nothing
  222. // -------------------------------------------------------------------
  223. // Set data (internal stuff)
  224. // nothing
  225. // -------------------------------------------------------------------
  226. // Set data (plugin-specific stuff)
  227. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  228. {
  229. CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
  230. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  231. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  232. fParamBuffers[parameterId] = fixedValue;
  233. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  234. }
  235. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  236. {
  237. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  238. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  239. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  240. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  241. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  242. carla_debug("DssiPlugin::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
  243. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
  244. return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
  245. if (fDssiDescriptor->configure != nullptr)
  246. {
  247. try {
  248. fDssiDescriptor->configure(fHandle, key, value);
  249. } catch(...) {}
  250. if (fHandle2 != nullptr)
  251. {
  252. try {
  253. fDssiDescriptor->configure(fHandle2, key, value);
  254. } catch(...) {}
  255. }
  256. }
  257. if (sendGui && pData->osc.data.target != nullptr)
  258. osc_send_configure(pData->osc.data, key, value);
  259. if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0)
  260. {
  261. const ScopedSingleProcessLocker spl(this, true);
  262. reloadPrograms(false);
  263. }
  264. CarlaPlugin::setCustomData(type, key, value, sendGui);
  265. }
  266. void setChunkData(const char* const stringData) override
  267. {
  268. CARLA_SAFE_ASSERT_RETURN(fUsesCustomData,);
  269. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  270. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  271. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->set_custom_data != nullptr,);
  272. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  273. CARLA_SAFE_ASSERT_RETURN(fHandle2 == nullptr,);
  274. CARLA_SAFE_ASSERT_RETURN(stringData != nullptr,);
  275. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(stringData));
  276. CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0,);
  277. {
  278. const ScopedSingleProcessLocker spl(this, true);
  279. try {
  280. fDssiDescriptor->set_custom_data(fHandle, chunk.data(), chunk.size());
  281. } CARLA_SAFE_EXCEPTION("DssiPlugin::setChunkData");
  282. }
  283. #ifdef BUILD_BRIDGE
  284. const bool sendOsc(false);
  285. #else
  286. const bool sendOsc(pData->engine->isOscControlRegistered());
  287. #endif
  288. pData->updateParameterValues(this, sendOsc, true, false);
  289. }
  290. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  291. {
  292. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  293. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
  294. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  295. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  296. if (index >= 0)
  297. {
  298. const uint32_t bank(pData->midiprog.data[index].bank);
  299. const uint32_t program(pData->midiprog.data[index].program);
  300. const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  301. try {
  302. fDssiDescriptor->select_program(fHandle, bank, program);
  303. } catch(...) {}
  304. if (fHandle2 != nullptr)
  305. {
  306. try {
  307. fDssiDescriptor->select_program(fHandle2, bank, program);
  308. } catch(...) {}
  309. }
  310. }
  311. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  312. }
  313. // -------------------------------------------------------------------
  314. // Set ui stuff
  315. void showCustomUI(const bool yesNo) override
  316. {
  317. if (yesNo)
  318. {
  319. pData->osc.data.free();
  320. pData->osc.thread.startThread();
  321. }
  322. else
  323. {
  324. pData->transientTryCounter = 0;
  325. if (pData->osc.data.target != nullptr)
  326. {
  327. osc_send_hide(pData->osc.data);
  328. osc_send_quit(pData->osc.data);
  329. pData->osc.data.free();
  330. }
  331. pData->osc.thread.stopThread(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
  332. }
  333. }
  334. void idle() override
  335. {
  336. if (fLatencyChanged && fLatencyIndex != -1)
  337. {
  338. fLatencyChanged = false;
  339. const int32_t latency(static_cast<int32_t>(fParamBuffers[fLatencyIndex]));
  340. if (latency >= 0)
  341. {
  342. const uint32_t ulatency(static_cast<uint32_t>(latency));
  343. if (pData->latency != ulatency)
  344. {
  345. carla_stdout("latency changed to %i", latency);
  346. const ScopedSingleProcessLocker sspl(this, true);
  347. pData->latency = ulatency;
  348. pData->client->setLatency(ulatency);
  349. #ifndef BUILD_BRIDGE
  350. pData->recreateLatencyBuffers();
  351. #endif
  352. }
  353. }
  354. else
  355. carla_safe_assert_int("latency >= 0", __FILE__, __LINE__, latency);
  356. }
  357. }
  358. // -------------------------------------------------------------------
  359. // Plugin state
  360. void reload() override
  361. {
  362. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  363. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  364. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  365. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  366. carla_debug("DssiPlugin::reload() - start");
  367. const EngineProcessMode processMode(pData->engine->getProccessMode());
  368. // Safely disable plugin for reload
  369. const ScopedDisabler sd(this);
  370. if (pData->active)
  371. deactivate();
  372. clearBuffers();
  373. const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
  374. const uint32_t portCount(getSafePortCount());
  375. uint32_t aIns, aOuts, mIns, params;
  376. aIns = aOuts = mIns = params = 0;
  377. bool forcedStereoIn, forcedStereoOut;
  378. forcedStereoIn = forcedStereoOut = false;
  379. bool needsCtrlIn, needsCtrlOut;
  380. needsCtrlIn = needsCtrlOut = false;
  381. for (uint32_t i=0; i < portCount; ++i)
  382. {
  383. const LADSPA_PortDescriptor portType(fDescriptor->PortDescriptors[i]);
  384. if (LADSPA_IS_PORT_AUDIO(portType))
  385. {
  386. if (LADSPA_IS_PORT_INPUT(portType))
  387. aIns += 1;
  388. else if (LADSPA_IS_PORT_OUTPUT(portType))
  389. aOuts += 1;
  390. }
  391. else if (LADSPA_IS_PORT_CONTROL(portType))
  392. params += 1;
  393. }
  394. if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1))
  395. {
  396. if (fHandle2 == nullptr)
  397. {
  398. try {
  399. fHandle2 = fDescriptor->instantiate(fDescriptor, static_cast<ulong>(sampleRate));
  400. } CARLA_SAFE_EXCEPTION("DSSI instantiate #2");
  401. }
  402. if (fHandle2 != nullptr)
  403. {
  404. if (aIns == 1)
  405. {
  406. aIns = 2;
  407. forcedStereoIn = true;
  408. }
  409. if (aOuts == 1)
  410. {
  411. aOuts = 2;
  412. forcedStereoOut = true;
  413. }
  414. }
  415. }
  416. if (fDssiDescriptor->run_synth != nullptr || fDssiDescriptor->run_multiple_synths != nullptr)
  417. {
  418. mIns = 1;
  419. needsCtrlIn = true;
  420. }
  421. if (aIns > 0)
  422. {
  423. pData->audioIn.createNew(aIns);
  424. fAudioInBuffers = new float*[aIns];
  425. for (uint32_t i=0; i < aIns; ++i)
  426. fAudioInBuffers[i] = nullptr;
  427. }
  428. if (aOuts > 0)
  429. {
  430. pData->audioOut.createNew(aOuts);
  431. fAudioOutBuffers = new float*[aOuts];
  432. needsCtrlIn = true;
  433. for (uint32_t i=0; i < aOuts; ++i)
  434. fAudioOutBuffers[i] = nullptr;
  435. }
  436. if (params > 0)
  437. {
  438. pData->param.createNew(params, true);
  439. fParamBuffers = new float[params];
  440. FloatVectorOperations::clear(fParamBuffers, static_cast<int>(params));
  441. }
  442. const uint portNameSize(pData->engine->getMaxPortNameSize());
  443. CarlaString portName;
  444. for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCtrl=0; i < portCount; ++i)
  445. {
  446. const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i];
  447. const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i];
  448. if (LADSPA_IS_PORT_AUDIO(portType))
  449. {
  450. portName.clear();
  451. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  452. {
  453. portName = pData->name;
  454. portName += ":";
  455. }
  456. if (fDescriptor->PortNames[i] != nullptr && fDescriptor->PortNames[i][0] != '\0')
  457. {
  458. portName += fDescriptor->PortNames[i];
  459. }
  460. else
  461. {
  462. if (LADSPA_IS_PORT_INPUT(portType))
  463. {
  464. if (aIns > 1)
  465. {
  466. portName += "audio-in_";
  467. portName += CarlaString(iAudioIn+1);
  468. }
  469. else
  470. portName += "audio-in";
  471. }
  472. else
  473. {
  474. if (aOuts > 1)
  475. {
  476. portName += "audio-out_";
  477. portName += CarlaString(iAudioOut+1);
  478. }
  479. else
  480. portName += "audio-out";
  481. }
  482. }
  483. portName.truncate(portNameSize);
  484. if (LADSPA_IS_PORT_INPUT(portType))
  485. {
  486. const uint32_t j = iAudioIn++;
  487. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  488. pData->audioIn.ports[j].rindex = i;
  489. if (forcedStereoIn)
  490. {
  491. portName += "_2";
  492. pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  493. pData->audioIn.ports[1].rindex = i;
  494. }
  495. }
  496. else if (LADSPA_IS_PORT_OUTPUT(portType))
  497. {
  498. const uint32_t j = iAudioOut++;
  499. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  500. pData->audioOut.ports[j].rindex = i;
  501. if (forcedStereoOut)
  502. {
  503. portName += "_2";
  504. pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  505. pData->audioOut.ports[1].rindex = i;
  506. }
  507. }
  508. else
  509. carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
  510. }
  511. else if (LADSPA_IS_PORT_CONTROL(portType))
  512. {
  513. const uint32_t j = iCtrl++;
  514. pData->param.data[j].index = static_cast<int32_t>(j);
  515. pData->param.data[j].rindex = static_cast<int32_t>(i);
  516. const char* const paramName(fDescriptor->PortNames[i] != nullptr ? fDescriptor->PortNames[i] : "unknown");
  517. float min, max, def, step, stepSmall, stepLarge;
  518. // min value
  519. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  520. min = portRangeHints.LowerBound;
  521. else
  522. min = 0.0f;
  523. // max value
  524. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  525. max = portRangeHints.UpperBound;
  526. else
  527. max = 1.0f;
  528. if (min > max)
  529. {
  530. carla_stderr2("WARNING - Broken plugin parameter '%s': min > max", paramName);
  531. min = max - 0.1f;
  532. }
  533. else if (min == max)
  534. {
  535. carla_stderr2("WARNING - Broken plugin parameter '%s': min == maxf", paramName);
  536. max = min + 0.1f;
  537. }
  538. // default value
  539. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  540. if (def < min)
  541. def = min;
  542. else if (def > max)
  543. def = max;
  544. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  545. {
  546. min *= sampleRate;
  547. max *= sampleRate;
  548. def *= sampleRate;
  549. pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  550. }
  551. if (LADSPA_IS_HINT_TOGGLED(portRangeHints.HintDescriptor))
  552. {
  553. step = max - min;
  554. stepSmall = step;
  555. stepLarge = step;
  556. pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  557. }
  558. else if (LADSPA_IS_HINT_INTEGER(portRangeHints.HintDescriptor))
  559. {
  560. step = 1.0f;
  561. stepSmall = 1.0f;
  562. stepLarge = 10.0f;
  563. pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  564. }
  565. else
  566. {
  567. const float range = max - min;
  568. step = range/100.0f;
  569. stepSmall = range/1000.0f;
  570. stepLarge = range/10.0f;
  571. }
  572. if (LADSPA_IS_PORT_INPUT(portType))
  573. {
  574. pData->param.data[j].type = PARAMETER_INPUT;
  575. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  576. pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  577. needsCtrlIn = true;
  578. // MIDI CC value
  579. if (fDssiDescriptor->get_midi_controller_for_port != nullptr)
  580. {
  581. int controller = fDssiDescriptor->get_midi_controller_for_port(fHandle, i);
  582. if (DSSI_CONTROLLER_IS_SET(controller) && DSSI_IS_CC(controller))
  583. {
  584. int16_t cc = DSSI_CC_NUMBER(controller);
  585. if (! MIDI_IS_CONTROL_BANK_SELECT(cc))
  586. pData->param.data[j].midiCC = cc;
  587. }
  588. }
  589. }
  590. else if (LADSPA_IS_PORT_OUTPUT(portType))
  591. {
  592. pData->param.data[j].type = PARAMETER_OUTPUT;
  593. if (std::strcmp(paramName, "latency") == 0 || std::strcmp(paramName, "_latency") == 0)
  594. {
  595. min = 0.0f;
  596. max = sampleRate;
  597. def = 0.0f;
  598. step = 1.0f;
  599. stepSmall = 1.0f;
  600. stepLarge = 1.0f;
  601. pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
  602. CARLA_SAFE_ASSERT(fLatencyIndex == -1);
  603. fLatencyIndex = static_cast<int32_t>(j);
  604. }
  605. else
  606. {
  607. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  608. pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  609. needsCtrlOut = true;
  610. }
  611. }
  612. else
  613. {
  614. carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
  615. }
  616. // extra parameter hints
  617. if (LADSPA_IS_HINT_LOGARITHMIC(portRangeHints.HintDescriptor))
  618. pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  619. pData->param.ranges[j].min = min;
  620. pData->param.ranges[j].max = max;
  621. pData->param.ranges[j].def = def;
  622. pData->param.ranges[j].step = step;
  623. pData->param.ranges[j].stepSmall = stepSmall;
  624. pData->param.ranges[j].stepLarge = stepLarge;
  625. // Start parameters in their default values
  626. fParamBuffers[j] = def;
  627. try {
  628. fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]);
  629. } CARLA_SAFE_EXCEPTION("DSSI connect_port parameter");
  630. if (fHandle2 != nullptr)
  631. {
  632. try {
  633. fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]);
  634. } CARLA_SAFE_EXCEPTION("DSSI connect_port parameter #2");
  635. }
  636. }
  637. else
  638. {
  639. // Not Audio or Control
  640. carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)");
  641. try {
  642. fDescriptor->connect_port(fHandle, i, nullptr);
  643. } CARLA_SAFE_EXCEPTION("DSSI connect_port null");
  644. if (fHandle2 != nullptr)
  645. {
  646. try {
  647. fDescriptor->connect_port(fHandle2, i, nullptr);
  648. } CARLA_SAFE_EXCEPTION("DSSI connect_port null #2");
  649. }
  650. }
  651. }
  652. if (needsCtrlIn)
  653. {
  654. portName.clear();
  655. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  656. {
  657. portName = pData->name;
  658. portName += ":";
  659. }
  660. portName += "events-in";
  661. portName.truncate(portNameSize);
  662. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  663. }
  664. if (needsCtrlOut)
  665. {
  666. portName.clear();
  667. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  668. {
  669. portName = pData->name;
  670. portName += ":";
  671. }
  672. portName += "events-out";
  673. portName.truncate(portNameSize);
  674. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  675. }
  676. if (forcedStereoIn || forcedStereoOut)
  677. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  678. else
  679. pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
  680. // plugin hints
  681. pData->hints = 0x0;
  682. if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties))
  683. pData->hints |= PLUGIN_IS_RTSAFE;
  684. if (fUiFilename != nullptr)
  685. pData->hints |= PLUGIN_HAS_CUSTOM_UI;
  686. #ifndef BUILD_BRIDGE
  687. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  688. pData->hints |= PLUGIN_CAN_DRYWET;
  689. if (aOuts > 0)
  690. pData->hints |= PLUGIN_CAN_VOLUME;
  691. if (aOuts >= 2 && aOuts % 2 == 0)
  692. pData->hints |= PLUGIN_CAN_BALANCE;
  693. #endif
  694. // extra plugin hints
  695. pData->extraHints = 0x0;
  696. if (mIns > 0)
  697. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  698. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0))
  699. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  700. // check latency
  701. if (fLatencyIndex >= 0)
  702. {
  703. // we need to pre-run the plugin so it can update its latency control-port
  704. float tmpIn [(aIns > 0) ? aIns : 1][2];
  705. float tmpOut[(aOuts > 0) ? aOuts : 1][2];
  706. for (uint32_t j=0; j < aIns; ++j)
  707. {
  708. tmpIn[j][0] = 0.0f;
  709. tmpIn[j][1] = 0.0f;
  710. try {
  711. fDescriptor->connect_port(fHandle, pData->audioIn.ports[j].rindex, tmpIn[j]);
  712. } CARLA_SAFE_EXCEPTION("DSSI connect_port latency input");
  713. }
  714. for (uint32_t j=0; j < aOuts; ++j)
  715. {
  716. tmpOut[j][0] = 0.0f;
  717. tmpOut[j][1] = 0.0f;
  718. try {
  719. fDescriptor->connect_port(fHandle, pData->audioOut.ports[j].rindex, tmpOut[j]);
  720. } CARLA_SAFE_EXCEPTION("DSSI connect_port latency output");
  721. }
  722. if (fDescriptor->activate != nullptr)
  723. {
  724. try {
  725. fDescriptor->activate(fHandle);
  726. } CARLA_SAFE_EXCEPTION("DSSI latency activate");
  727. }
  728. try {
  729. fDescriptor->run(fHandle, 2);
  730. } CARLA_SAFE_EXCEPTION("DSSI latency run");
  731. if (fDescriptor->deactivate != nullptr)
  732. {
  733. try {
  734. fDescriptor->deactivate(fHandle);
  735. } CARLA_SAFE_EXCEPTION("DSSI latency deactivate");
  736. }
  737. const int32_t latency(static_cast<int32_t>(fParamBuffers[fLatencyIndex]));
  738. if (latency >= 0)
  739. {
  740. const uint32_t ulatency(static_cast<uint32_t>(latency));
  741. if (pData->latency != ulatency)
  742. {
  743. carla_stdout("latency = %i", latency);
  744. pData->latency = ulatency;
  745. pData->client->setLatency(ulatency);
  746. #ifndef BUILD_BRIDGE
  747. pData->recreateLatencyBuffers();
  748. #endif
  749. }
  750. }
  751. else
  752. carla_safe_assert_int("latency >= 0", __FILE__, __LINE__, latency);
  753. fLatencyChanged = false;
  754. }
  755. bufferSizeChanged(pData->engine->getBufferSize());
  756. reloadPrograms(true);
  757. if (pData->active)
  758. activate();
  759. carla_debug("DssiPlugin::reload() - end");
  760. }
  761. void reloadPrograms(const bool doInit) override
  762. {
  763. carla_debug("DssiPlugin::reloadPrograms(%s)", bool2str(doInit));
  764. const uint32_t oldCount = pData->midiprog.count;
  765. const int32_t current = pData->midiprog.current;
  766. // Delete old programs
  767. pData->midiprog.clear();
  768. // Query new programs
  769. uint32_t newCount = 0;
  770. if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
  771. {
  772. for (; fDssiDescriptor->get_program(fHandle, newCount) != nullptr;)
  773. ++newCount;
  774. }
  775. if (newCount > 0)
  776. {
  777. pData->midiprog.createNew(newCount);
  778. // Update data
  779. for (uint32_t i=0; i < newCount; ++i)
  780. {
  781. const DSSI_Program_Descriptor* const pdesc(fDssiDescriptor->get_program(fHandle, i));
  782. CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr);
  783. CARLA_SAFE_ASSERT(pdesc->Name != nullptr);
  784. pData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
  785. pData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
  786. pData->midiprog.data[i].name = carla_strdup(pdesc->Name);
  787. }
  788. }
  789. #ifndef BUILD_BRIDGE
  790. // Update OSC Names
  791. if (pData->engine->isOscControlRegistered())
  792. {
  793. pData->engine->oscSend_control_set_midi_program_count(pData->id, newCount);
  794. for (uint32_t i=0; i < newCount; ++i)
  795. pData->engine->oscSend_control_set_midi_program_data(pData->id, i, pData->midiprog.data[i].bank, pData->midiprog.data[i].program, pData->midiprog.data[i].name);
  796. }
  797. #endif
  798. if (doInit)
  799. {
  800. if (newCount > 0)
  801. setMidiProgram(0, false, false, false);
  802. }
  803. else
  804. {
  805. // Check if current program is invalid
  806. bool programChanged = false;
  807. if (newCount == oldCount+1)
  808. {
  809. // one midi program added, probably created by user
  810. pData->midiprog.current = static_cast<int32_t>(oldCount);
  811. programChanged = true;
  812. }
  813. else if (current < 0 && newCount > 0)
  814. {
  815. // programs exist now, but not before
  816. pData->midiprog.current = 0;
  817. programChanged = true;
  818. }
  819. else if (current >= 0 && newCount == 0)
  820. {
  821. // programs existed before, but not anymore
  822. pData->midiprog.current = -1;
  823. programChanged = true;
  824. }
  825. else if (current >= static_cast<int32_t>(newCount))
  826. {
  827. // current midi program > count
  828. pData->midiprog.current = 0;
  829. programChanged = true;
  830. }
  831. else
  832. {
  833. // no change
  834. pData->midiprog.current = current;
  835. }
  836. if (programChanged)
  837. setMidiProgram(pData->midiprog.current, true, true, true);
  838. pData->engine->callback(ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0.0f, nullptr);
  839. }
  840. }
  841. // -------------------------------------------------------------------
  842. // Plugin processing
  843. void activate() noexcept override
  844. {
  845. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  846. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  847. if (fDescriptor->activate != nullptr)
  848. {
  849. try {
  850. fDescriptor->activate(fHandle);
  851. } CARLA_SAFE_EXCEPTION("DSSI activate");
  852. if (fHandle2 != nullptr)
  853. {
  854. try {
  855. fDescriptor->activate(fHandle2);
  856. } CARLA_SAFE_EXCEPTION("DSSI activate #2");
  857. }
  858. }
  859. }
  860. void deactivate() noexcept override
  861. {
  862. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  863. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  864. if (fDescriptor->deactivate != nullptr)
  865. {
  866. try {
  867. fDescriptor->deactivate(fHandle);
  868. } CARLA_SAFE_EXCEPTION("DSSI deactivate");
  869. if (fHandle2 != nullptr)
  870. {
  871. try {
  872. fDescriptor->deactivate(fHandle2);
  873. } CARLA_SAFE_EXCEPTION("DSSI deactivate #2");
  874. }
  875. }
  876. }
  877. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override
  878. {
  879. // --------------------------------------------------------------------------------------------------------
  880. // Check if active
  881. if (! pData->active)
  882. {
  883. // disable any output sound
  884. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  885. FloatVectorOperations::clear(outBuffer[i], static_cast<int>(frames));
  886. return;
  887. }
  888. ulong midiEventCount = 0;
  889. // --------------------------------------------------------------------------------------------------------
  890. // Check if needs reset
  891. if (pData->needsReset)
  892. {
  893. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  894. {
  895. midiEventCount = MAX_MIDI_CHANNELS*2;
  896. carla_zeroStruct<snd_seq_event_t>(fMidiEvents, midiEventCount);
  897. for (uchar i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i)
  898. {
  899. fMidiEvents[i].type = SND_SEQ_EVENT_CONTROLLER;
  900. fMidiEvents[i].data.control.channel = i;
  901. fMidiEvents[i].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
  902. fMidiEvents[k+i].type = SND_SEQ_EVENT_CONTROLLER;
  903. fMidiEvents[k+i].data.control.channel = i;
  904. fMidiEvents[k+i].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
  905. }
  906. }
  907. else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
  908. {
  909. midiEventCount = MAX_MIDI_NOTE;
  910. carla_zeroStruct<snd_seq_event_t>(fMidiEvents, midiEventCount);
  911. for (uchar i=0; i < MAX_MIDI_NOTE; ++i)
  912. {
  913. fMidiEvents[i].type = SND_SEQ_EVENT_NOTEOFF;
  914. fMidiEvents[i].data.note.channel = static_cast<uchar>(pData->ctrlChannel);
  915. fMidiEvents[i].data.note.note = i;
  916. }
  917. }
  918. #ifndef BUILD_BRIDGE
  919. if (pData->latency > 0)
  920. {
  921. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  922. FloatVectorOperations::clear(pData->latencyBuffers[i], static_cast<int>(pData->latency));
  923. }
  924. #endif
  925. pData->needsReset = false;
  926. }
  927. // --------------------------------------------------------------------------------------------------------
  928. // Event Input and Processing
  929. if (pData->event.portIn != nullptr)
  930. {
  931. // ----------------------------------------------------------------------------------------------------
  932. // MIDI Input (External)
  933. if (pData->extNotes.mutex.tryLock())
  934. {
  935. ExternalMidiNote note = { 0, 0, 0 };
  936. for (; midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();)
  937. {
  938. note = pData->extNotes.data.getFirst(note, true);
  939. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  940. snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]);
  941. carla_zeroStruct<snd_seq_event_t>(midiEvent);
  942. midiEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
  943. midiEvent.data.note.channel = static_cast<uchar>(note.channel);
  944. midiEvent.data.note.note = note.note;
  945. midiEvent.data.note.velocity = note.velo;
  946. }
  947. pData->extNotes.mutex.unlock();
  948. } // End of MIDI Input (External)
  949. // ----------------------------------------------------------------------------------------------------
  950. // Event Input (System)
  951. bool allNotesOffSent = false;
  952. const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
  953. uint32_t numEvents = pData->event.portIn->getEventCount();
  954. uint32_t startTime = 0;
  955. uint32_t timeOffset = 0;
  956. uint32_t nextBankId;
  957. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  958. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  959. else
  960. nextBankId = 0;
  961. for (uint32_t i=0; i < numEvents; ++i)
  962. {
  963. const EngineEvent& event(pData->event.portIn->getEvent(i));
  964. if (event.time >= frames)
  965. continue;
  966. CARLA_ASSERT_INT2(event.time >= timeOffset, event.time, timeOffset);
  967. if (isSampleAccurate && event.time > timeOffset)
  968. {
  969. if (processSingle(inBuffer, outBuffer, event.time - timeOffset, timeOffset, midiEventCount))
  970. {
  971. startTime = 0;
  972. timeOffset = event.time;
  973. midiEventCount = 0;
  974. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  975. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  976. else
  977. nextBankId = 0;
  978. }
  979. else
  980. startTime += timeOffset;
  981. }
  982. switch (event.type)
  983. {
  984. case kEngineEventTypeNull:
  985. break;
  986. case kEngineEventTypeControl: {
  987. const EngineControlEvent& ctrlEvent(event.ctrl);
  988. switch (ctrlEvent.type)
  989. {
  990. case kEngineControlEventTypeNull:
  991. break;
  992. case kEngineControlEventTypeParameter: {
  993. #ifndef BUILD_BRIDGE
  994. // Control backend stuff
  995. if (event.channel == pData->ctrlChannel)
  996. {
  997. float value;
  998. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  999. {
  1000. value = ctrlEvent.value;
  1001. setDryWet(value, false, false);
  1002. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  1003. break;
  1004. }
  1005. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  1006. {
  1007. value = ctrlEvent.value*127.0f/100.0f;
  1008. setVolume(value, false, false);
  1009. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  1010. break;
  1011. }
  1012. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  1013. {
  1014. float left, right;
  1015. value = ctrlEvent.value/0.5f - 1.0f;
  1016. if (value < 0.0f)
  1017. {
  1018. left = -1.0f;
  1019. right = (value*2.0f)+1.0f;
  1020. }
  1021. else if (value > 0.0f)
  1022. {
  1023. left = (value*2.0f)-1.0f;
  1024. right = 1.0f;
  1025. }
  1026. else
  1027. {
  1028. left = -1.0f;
  1029. right = 1.0f;
  1030. }
  1031. setBalanceLeft(left, false, false);
  1032. setBalanceRight(right, false, false);
  1033. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  1034. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  1035. break;
  1036. }
  1037. }
  1038. #endif
  1039. // Control plugin parameters
  1040. uint32_t k;
  1041. for (k=0; k < pData->param.count; ++k)
  1042. {
  1043. if (pData->param.data[k].midiChannel != event.channel)
  1044. continue;
  1045. if (pData->param.data[k].midiCC != ctrlEvent.param)
  1046. continue;
  1047. if (pData->param.data[k].type != PARAMETER_INPUT)
  1048. continue;
  1049. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  1050. continue;
  1051. float value;
  1052. if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  1053. {
  1054. value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;
  1055. }
  1056. else
  1057. {
  1058. value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value);
  1059. if (pData->param.data[k].hints & PARAMETER_IS_INTEGER)
  1060. value = std::rint(value);
  1061. }
  1062. setParameterValue(k, value, false, false, false);
  1063. pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  1064. break;
  1065. }
  1066. // check if event is already handled
  1067. if (k != pData->param.count)
  1068. break;
  1069. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F)
  1070. {
  1071. if (midiEventCount >= kPluginMaxMidiEvents)
  1072. continue;
  1073. snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]);
  1074. carla_zeroStruct<snd_seq_event_t>(midiEvent);
  1075. midiEvent.time.tick = isSampleAccurate ? startTime : event.time;
  1076. midiEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1077. midiEvent.data.control.channel = event.channel;
  1078. midiEvent.data.control.param = ctrlEvent.param;
  1079. midiEvent.data.control.value = int8_t(ctrlEvent.value*127.0f);
  1080. }
  1081. break;
  1082. } // case kEngineControlEventTypeParameter
  1083. case kEngineControlEventTypeMidiBank:
  1084. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1085. nextBankId = ctrlEvent.param;
  1086. break;
  1087. case kEngineControlEventTypeMidiProgram:
  1088. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1089. {
  1090. const uint32_t nextProgramId = ctrlEvent.param;
  1091. for (uint32_t k=0; k < pData->midiprog.count; ++k)
  1092. {
  1093. if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
  1094. {
  1095. const int32_t index(static_cast<int32_t>(k));
  1096. setMidiProgram(index, false, false, false);
  1097. pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, index, 0, 0.0f);
  1098. break;
  1099. }
  1100. }
  1101. }
  1102. break;
  1103. case kEngineControlEventTypeAllSoundOff:
  1104. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1105. {
  1106. if (midiEventCount >= kPluginMaxMidiEvents)
  1107. continue;
  1108. snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]);
  1109. carla_zeroStruct<snd_seq_event_t>(midiEvent);
  1110. midiEvent.time.tick = isSampleAccurate ? startTime : event.time;
  1111. midiEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1112. midiEvent.data.control.channel = event.channel;
  1113. midiEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
  1114. }
  1115. break;
  1116. case kEngineControlEventTypeAllNotesOff:
  1117. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1118. {
  1119. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  1120. {
  1121. allNotesOffSent = true;
  1122. sendMidiAllNotesOffToCallback();
  1123. }
  1124. if (midiEventCount >= kPluginMaxMidiEvents)
  1125. continue;
  1126. snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount++]);
  1127. carla_zeroStruct<snd_seq_event_t>(midiEvent);
  1128. midiEvent.time.tick = isSampleAccurate ? startTime : event.time;
  1129. midiEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1130. midiEvent.data.control.channel = event.channel;
  1131. midiEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
  1132. midiEventCount += 1;
  1133. }
  1134. break;
  1135. } // switch (ctrlEvent.type)
  1136. break;
  1137. } // case kEngineEventTypeControl
  1138. case kEngineEventTypeMidi: {
  1139. if (midiEventCount >= kPluginMaxMidiEvents)
  1140. continue;
  1141. const EngineMidiEvent& engineEvent(event.midi);
  1142. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(engineEvent.data));
  1143. uint8_t channel = event.channel;
  1144. // Fix bad note-off (per DSSI spec)
  1145. if (MIDI_IS_STATUS_NOTE_ON(status) && engineEvent.data[2] == 0)
  1146. status = MIDI_STATUS_NOTE_OFF;
  1147. snd_seq_event_t& midiEvent(fMidiEvents[midiEventCount]);
  1148. carla_zeroStruct<snd_seq_event_t>(midiEvent);
  1149. midiEvent.time.tick = isSampleAccurate ? startTime : event.time;
  1150. switch (status)
  1151. {
  1152. case MIDI_STATUS_NOTE_OFF: {
  1153. const uint8_t note = engineEvent.data[1];
  1154. midiEvent.type = SND_SEQ_EVENT_NOTEOFF;
  1155. midiEvent.data.note.channel = channel;
  1156. midiEvent.data.note.note = note;
  1157. pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, note, 0.0f);
  1158. break;
  1159. }
  1160. case MIDI_STATUS_NOTE_ON: {
  1161. const uint8_t note = engineEvent.data[1];
  1162. const uint8_t velo = engineEvent.data[2];
  1163. midiEvent.type = SND_SEQ_EVENT_NOTEON;
  1164. midiEvent.data.note.channel = channel;
  1165. midiEvent.data.note.note = note;
  1166. midiEvent.data.note.velocity = velo;
  1167. pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, note, velo);
  1168. break;
  1169. }
  1170. case MIDI_STATUS_POLYPHONIC_AFTERTOUCH:
  1171. if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)
  1172. {
  1173. const uint8_t note = engineEvent.data[1];
  1174. const uint8_t pressure = engineEvent.data[2];
  1175. midiEvent.type = SND_SEQ_EVENT_KEYPRESS;
  1176. midiEvent.data.note.channel = channel;
  1177. midiEvent.data.note.note = note;
  1178. midiEvent.data.note.velocity = pressure;
  1179. }
  1180. break;
  1181. case MIDI_STATUS_CONTROL_CHANGE:
  1182. if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES)
  1183. {
  1184. const uint8_t control = engineEvent.data[1];
  1185. const uint8_t value = engineEvent.data[2];
  1186. midiEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1187. midiEvent.data.control.channel = channel;
  1188. midiEvent.data.control.param = control;
  1189. midiEvent.data.control.value = value;
  1190. }
  1191. break;
  1192. case MIDI_STATUS_CHANNEL_PRESSURE:
  1193. if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)
  1194. {
  1195. const uint8_t pressure = engineEvent.data[1];
  1196. midiEvent.type = SND_SEQ_EVENT_CHANPRESS;
  1197. midiEvent.data.control.channel = channel;
  1198. midiEvent.data.control.value = pressure;
  1199. }
  1200. break;
  1201. case MIDI_STATUS_PITCH_WHEEL_CONTROL:
  1202. if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND)
  1203. {
  1204. const uint8_t lsb = engineEvent.data[1];
  1205. const uint8_t msb = engineEvent.data[2];
  1206. midiEvent.type = SND_SEQ_EVENT_PITCHBEND;
  1207. midiEvent.data.control.channel = channel;
  1208. midiEvent.data.control.value = ((msb << 7) | lsb) - 8192;
  1209. }
  1210. break;
  1211. default:
  1212. continue;
  1213. break;
  1214. } // switch (status)
  1215. midiEventCount += 1;
  1216. break;
  1217. } // case kEngineEventTypeMidi
  1218. } // switch (event.type)
  1219. }
  1220. pData->postRtEvents.trySplice();
  1221. if (frames > timeOffset)
  1222. processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset, midiEventCount);
  1223. } // End of Event Input and Processing
  1224. // --------------------------------------------------------------------------------------------------------
  1225. // Plugin processing (no events)
  1226. else
  1227. {
  1228. processSingle(inBuffer, outBuffer, frames, 0, midiEventCount);
  1229. } // End of Plugin processing (no events)
  1230. #ifndef BUILD_BRIDGE
  1231. // --------------------------------------------------------------------------------------------------------
  1232. // Latency, save values for next callback
  1233. if (fLatencyIndex != -1)
  1234. {
  1235. if (pData->latency != static_cast<uint32_t>(fParamBuffers[fLatencyIndex]))
  1236. {
  1237. fLatencyChanged = true;
  1238. }
  1239. else if (pData->latency > 0)
  1240. {
  1241. if (pData->latency <= frames)
  1242. {
  1243. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1244. FloatVectorOperations::copy(pData->latencyBuffers[i], inBuffer[i]+(frames-pData->latency), static_cast<int>(pData->latency));
  1245. }
  1246. else
  1247. {
  1248. for (uint32_t i=0, j, k; i < pData->audioIn.count; ++i)
  1249. {
  1250. for (k=0; k < pData->latency-frames; ++k)
  1251. pData->latencyBuffers[i][k] = pData->latencyBuffers[i][k+frames];
  1252. for (j=0; k < pData->latency; ++j, ++k)
  1253. pData->latencyBuffers[i][k] = inBuffer[i][j];
  1254. }
  1255. }
  1256. }
  1257. }
  1258. #endif
  1259. // --------------------------------------------------------------------------------------------------------
  1260. // Control Output
  1261. if (pData->event.portOut != nullptr)
  1262. {
  1263. uint8_t channel;
  1264. uint16_t param;
  1265. float value;
  1266. for (uint32_t k=0; k < pData->param.count; ++k)
  1267. {
  1268. if (pData->param.data[k].type != PARAMETER_OUTPUT)
  1269. continue;
  1270. pData->param.ranges[k].fixValue(fParamBuffers[k]);
  1271. if (pData->param.data[k].midiCC > 0)
  1272. {
  1273. channel = pData->param.data[k].midiChannel;
  1274. param = static_cast<uint16_t>(pData->param.data[k].midiCC);
  1275. value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
  1276. pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
  1277. }
  1278. }
  1279. } // End of Control Output
  1280. }
  1281. bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset, const ulong midiEventCount)
  1282. {
  1283. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  1284. if (pData->audioIn.count > 0)
  1285. {
  1286. CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false);
  1287. }
  1288. if (pData->audioOut.count > 0)
  1289. {
  1290. CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false);
  1291. }
  1292. // --------------------------------------------------------------------------------------------------------
  1293. // Try lock, silence otherwise
  1294. if (pData->engine->isOffline())
  1295. {
  1296. pData->singleMutex.lock();
  1297. }
  1298. else if (! pData->singleMutex.tryLock())
  1299. {
  1300. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1301. {
  1302. for (uint32_t k=0; k < frames; ++k)
  1303. outBuffer[i][k+timeOffset] = 0.0f;
  1304. }
  1305. return false;
  1306. }
  1307. // --------------------------------------------------------------------------------------------------------
  1308. // Reset audio buffers
  1309. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1310. FloatVectorOperations::copy(fAudioInBuffers[i], inBuffer[i]+timeOffset, static_cast<int>(frames));
  1311. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1312. FloatVectorOperations::clear(fAudioOutBuffers[i], static_cast<int>(frames));
  1313. // --------------------------------------------------------------------------------------------------------
  1314. // Run plugin
  1315. // TODO - try catch
  1316. if (fDssiDescriptor->run_synth != nullptr)
  1317. {
  1318. fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount);
  1319. if (fHandle2 != nullptr)
  1320. fDssiDescriptor->run_synth(fHandle2, frames, fMidiEvents, midiEventCount);
  1321. }
  1322. else if (fDssiDescriptor->run_multiple_synths != nullptr)
  1323. {
  1324. ulong instances = (fHandle2 != nullptr) ? 2 : 1;
  1325. LADSPA_Handle handlePtr[2] = { fHandle, fHandle2 };
  1326. snd_seq_event_t* midiEventsPtr[2] = { fMidiEvents, fMidiEvents };
  1327. ulong midiEventCountPtr[2] = { midiEventCount, midiEventCount };
  1328. fDssiDescriptor->run_multiple_synths(instances, handlePtr, frames, midiEventsPtr, midiEventCountPtr);
  1329. }
  1330. else
  1331. {
  1332. fDescriptor->run(fHandle, frames);
  1333. if (fHandle2 != nullptr)
  1334. fDescriptor->run(fHandle2, frames);
  1335. }
  1336. #ifndef BUILD_BRIDGE
  1337. // --------------------------------------------------------------------------------------------------------
  1338. // Post-processing (dry/wet, volume and balance)
  1339. {
  1340. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f;
  1341. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f);
  1342. const bool isMono = (pData->audioIn.count == 1);
  1343. bool isPair;
  1344. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1345. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1346. {
  1347. // Dry/Wet
  1348. if (doDryWet)
  1349. {
  1350. for (uint32_t k=0; k < frames; ++k)
  1351. {
  1352. if (k < pData->latency)
  1353. bufValue = pData->latencyBuffers[isMono ? 0 : i][k];
  1354. else if (pData->latency < frames)
  1355. bufValue = fAudioInBuffers[isMono ? 0 : i][k-pData->latency];
  1356. else
  1357. bufValue = fAudioInBuffers[isMono ? 0 : i][k];
  1358. fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1359. }
  1360. }
  1361. // Balance
  1362. if (doBalance)
  1363. {
  1364. isPair = (i % 2 == 0);
  1365. if (isPair)
  1366. {
  1367. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1368. FloatVectorOperations::copy(oldBufLeft, fAudioOutBuffers[i], static_cast<int>(frames));
  1369. }
  1370. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1371. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1372. for (uint32_t k=0; k < frames; ++k)
  1373. {
  1374. if (isPair)
  1375. {
  1376. // left
  1377. fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1378. fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
  1379. }
  1380. else
  1381. {
  1382. // right
  1383. fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
  1384. fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  1385. }
  1386. }
  1387. }
  1388. // Volume (and buffer copy)
  1389. {
  1390. for (uint32_t k=0; k < frames; ++k)
  1391. outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
  1392. }
  1393. }
  1394. } // End of Post-processing
  1395. #else // BUILD_BRIDGE
  1396. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1397. {
  1398. for (uint32_t k=0; k < frames; ++k)
  1399. outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k];
  1400. }
  1401. #endif
  1402. // --------------------------------------------------------------------------------------------------------
  1403. pData->singleMutex.unlock();
  1404. return true;
  1405. }
  1406. void bufferSizeChanged(const uint32_t newBufferSize) override
  1407. {
  1408. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  1409. carla_debug("DssiPlugin::bufferSizeChanged(%i) - start", newBufferSize);
  1410. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1411. {
  1412. if (fAudioInBuffers[i] != nullptr)
  1413. delete[] fAudioInBuffers[i];
  1414. fAudioInBuffers[i] = new float[newBufferSize];
  1415. }
  1416. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1417. {
  1418. if (fAudioOutBuffers[i] != nullptr)
  1419. delete[] fAudioOutBuffers[i];
  1420. fAudioOutBuffers[i] = new float[newBufferSize];
  1421. }
  1422. if (fHandle2 == nullptr)
  1423. {
  1424. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1425. {
  1426. CARLA_ASSERT(fAudioInBuffers[i] != nullptr);
  1427. try {
  1428. fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
  1429. } CARLA_SAFE_EXCEPTION("DSSI connect_port audio input");
  1430. }
  1431. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1432. {
  1433. CARLA_ASSERT(fAudioOutBuffers[i] != nullptr);
  1434. try {
  1435. fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
  1436. } CARLA_SAFE_EXCEPTION("DSSI connect_port audio output");
  1437. }
  1438. }
  1439. else
  1440. {
  1441. if (pData->audioIn.count > 0)
  1442. {
  1443. CARLA_ASSERT(pData->audioIn.count == 2);
  1444. CARLA_ASSERT(fAudioInBuffers[0] != nullptr);
  1445. CARLA_ASSERT(fAudioInBuffers[1] != nullptr);
  1446. try {
  1447. fDescriptor->connect_port(fHandle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
  1448. } CARLA_SAFE_EXCEPTION("DSSI connect_port audio input #1");
  1449. try {
  1450. fDescriptor->connect_port(fHandle2, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
  1451. } CARLA_SAFE_EXCEPTION("DSSI connect_port audio input #2");
  1452. }
  1453. if (pData->audioOut.count > 0)
  1454. {
  1455. CARLA_ASSERT(pData->audioOut.count == 2);
  1456. CARLA_ASSERT(fAudioOutBuffers[0] != nullptr);
  1457. CARLA_ASSERT(fAudioOutBuffers[1] != nullptr);
  1458. try {
  1459. fDescriptor->connect_port(fHandle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
  1460. } CARLA_SAFE_EXCEPTION("DSSI connect_port audio output #1");
  1461. try {
  1462. fDescriptor->connect_port(fHandle2, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
  1463. } CARLA_SAFE_EXCEPTION("DSSI connect_port audio output #2");
  1464. }
  1465. }
  1466. carla_debug("DssiPlugin::bufferSizeChanged(%i) - end", newBufferSize);
  1467. }
  1468. void sampleRateChanged(const double newSampleRate) override
  1469. {
  1470. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  1471. carla_debug("DssiPlugin::sampleRateChanged(%g) - start", newSampleRate);
  1472. // TODO
  1473. (void)newSampleRate;
  1474. carla_debug("DssiPlugin::sampleRateChanged(%g) - end", newSampleRate);
  1475. }
  1476. // -------------------------------------------------------------------
  1477. // Plugin buffers
  1478. void clearBuffers() noexcept override
  1479. {
  1480. carla_debug("DssiPlugin::clearBuffers() - start");
  1481. if (fAudioInBuffers != nullptr)
  1482. {
  1483. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1484. {
  1485. if (fAudioInBuffers[i] != nullptr)
  1486. {
  1487. delete[] fAudioInBuffers[i];
  1488. fAudioInBuffers[i] = nullptr;
  1489. }
  1490. }
  1491. delete[] fAudioInBuffers;
  1492. fAudioInBuffers = nullptr;
  1493. }
  1494. if (fAudioOutBuffers != nullptr)
  1495. {
  1496. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1497. {
  1498. if (fAudioOutBuffers[i] != nullptr)
  1499. {
  1500. delete[] fAudioOutBuffers[i];
  1501. fAudioOutBuffers[i] = nullptr;
  1502. }
  1503. }
  1504. delete[] fAudioOutBuffers;
  1505. fAudioOutBuffers = nullptr;
  1506. }
  1507. if (fParamBuffers != nullptr)
  1508. {
  1509. delete[] fParamBuffers;
  1510. fParamBuffers = nullptr;
  1511. }
  1512. CarlaPlugin::clearBuffers();
  1513. carla_debug("DssiPlugin::clearBuffers() - end");
  1514. }
  1515. // -------------------------------------------------------------------
  1516. // Post-poned UI Stuff
  1517. void uiParameterChange(const uint32_t index, const float value) noexcept override
  1518. {
  1519. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  1520. if (pData->osc.data.target == nullptr)
  1521. return;
  1522. osc_send_control(pData->osc.data, pData->param.data[index].rindex, value);
  1523. }
  1524. void uiMidiProgramChange(const uint32_t index) noexcept override
  1525. {
  1526. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1527. if (pData->osc.data.target == nullptr)
  1528. return;
  1529. osc_send_program(pData->osc.data, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
  1530. }
  1531. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  1532. {
  1533. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1534. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1535. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1536. if (pData->osc.data.target == nullptr)
  1537. return;
  1538. #if 0
  1539. uint8_t midiData[4];
  1540. midiData[0] = 0;
  1541. midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_ON + channel);
  1542. midiData[2] = note;
  1543. midiData[3] = velo;
  1544. osc_send_midi(pData->osc.data, midiData);
  1545. #endif
  1546. }
  1547. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  1548. {
  1549. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1550. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1551. if (pData->osc.data.target == nullptr)
  1552. return;
  1553. #if 0
  1554. uint8_t midiData[4];
  1555. midiData[0] = 0;
  1556. midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + channel);
  1557. midiData[2] = note;
  1558. midiData[3] = 0;
  1559. osc_send_midi(pData->osc.data, midiData);
  1560. #endif
  1561. }
  1562. // -------------------------------------------------------------------
  1563. const void* getExtraStuff() const noexcept override
  1564. {
  1565. return fUiFilename;
  1566. }
  1567. bool init(const char* const filename, const char* const name, const char* const label)
  1568. {
  1569. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  1570. // ---------------------------------------------------------------
  1571. // first checks
  1572. if (pData->client != nullptr)
  1573. {
  1574. pData->engine->setLastError("Plugin client is already registered");
  1575. return false;
  1576. }
  1577. if (filename == nullptr || filename[0] == '\0')
  1578. {
  1579. pData->engine->setLastError("null filename");
  1580. return false;
  1581. }
  1582. if (label == nullptr || label[0] == '\0')
  1583. {
  1584. pData->engine->setLastError("null label");
  1585. return false;
  1586. }
  1587. // ---------------------------------------------------------------
  1588. // open DLL
  1589. if (! pData->libOpen(filename))
  1590. {
  1591. pData->engine->setLastError(pData->libError(filename));
  1592. return false;
  1593. }
  1594. // ---------------------------------------------------------------
  1595. // get DLL main entry
  1596. const DSSI_Descriptor_Function descFn = (DSSI_Descriptor_Function)pData->libSymbol("dssi_descriptor");
  1597. if (descFn == nullptr)
  1598. {
  1599. pData->engine->setLastError("Could not find the DSSI Descriptor in the plugin library");
  1600. return false;
  1601. }
  1602. // ---------------------------------------------------------------
  1603. // get descriptor that matches label
  1604. ulong i = 0;
  1605. for (;;)
  1606. {
  1607. try {
  1608. fDssiDescriptor = descFn(i++);
  1609. }
  1610. catch(...) {
  1611. carla_stderr2("Caught exception when trying to get LADSPA descriptor");
  1612. fDescriptor = nullptr;
  1613. fDssiDescriptor = nullptr;
  1614. break;
  1615. }
  1616. if (fDssiDescriptor == nullptr)
  1617. break;
  1618. fDescriptor = fDssiDescriptor->LADSPA_Plugin;
  1619. if (fDescriptor == nullptr)
  1620. {
  1621. carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin");
  1622. fDssiDescriptor = nullptr;
  1623. break;
  1624. }
  1625. if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
  1626. {
  1627. carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
  1628. fDescriptor = nullptr;
  1629. fDssiDescriptor = nullptr;
  1630. break;
  1631. }
  1632. if (fDescriptor->run == nullptr)
  1633. {
  1634. carla_stderr2("WARNING - Plugin has no run, cannot use it");
  1635. fDescriptor = nullptr;
  1636. fDssiDescriptor = nullptr;
  1637. break;
  1638. }
  1639. if (std::strcmp(fDescriptor->Label, label) == 0)
  1640. break;
  1641. }
  1642. if (fDescriptor == nullptr || fDssiDescriptor == nullptr)
  1643. {
  1644. pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
  1645. return false;
  1646. }
  1647. // ---------------------------------------------------------------
  1648. // check if uses global instance
  1649. if (fDssiDescriptor->run_synth == nullptr && fDssiDescriptor->run_multiple_synths != nullptr)
  1650. {
  1651. if (! addUniqueMultiSynth(fDescriptor->Label))
  1652. {
  1653. pData->engine->setLastError("This plugin uses a global instance and can't be used more than once safely");
  1654. return false;
  1655. }
  1656. }
  1657. // ---------------------------------------------------------------
  1658. // get info
  1659. if (name != nullptr && name[0] != '\0')
  1660. pData->name = pData->engine->getUniquePluginName(name);
  1661. else if (fDescriptor->Name != nullptr && fDescriptor->Name[0] != '\0')
  1662. pData->name = pData->engine->getUniquePluginName(fDescriptor->Name);
  1663. else
  1664. pData->name = pData->engine->getUniquePluginName(fDescriptor->Label);
  1665. pData->filename = carla_strdup(filename);
  1666. // ---------------------------------------------------------------
  1667. // register client
  1668. pData->client = pData->engine->addClient(this);
  1669. if (pData->client == nullptr || ! pData->client->isOk())
  1670. {
  1671. pData->engine->setLastError("Failed to register plugin client");
  1672. return false;
  1673. }
  1674. // ---------------------------------------------------------------
  1675. // initialize plugin
  1676. try {
  1677. fHandle = fDescriptor->instantiate(fDescriptor, (ulong)pData->engine->getSampleRate());
  1678. } CARLA_SAFE_EXCEPTION("DSSI instantiate");
  1679. if (fHandle == nullptr)
  1680. {
  1681. pData->engine->setLastError("Plugin failed to initialize");
  1682. return false;
  1683. }
  1684. // ---------------------------------------------------------------
  1685. // check for custom data extension
  1686. if (fDssiDescriptor->configure != nullptr)
  1687. {
  1688. if (char* const error = fDssiDescriptor->configure(fHandle, DSSI_CUSTOMDATA_EXTENSION_KEY, ""))
  1689. {
  1690. if (std::strcmp(error, "true") == 0 && fDssiDescriptor->get_custom_data != nullptr && fDssiDescriptor->set_custom_data != nullptr)
  1691. fUsesCustomData = true;
  1692. std::free(error);
  1693. }
  1694. }
  1695. // ---------------------------------------------------------------
  1696. // gui stuff
  1697. if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label))
  1698. {
  1699. pData->osc.thread.setOscData(guiFilename, fDescriptor->Label);
  1700. fUiFilename = guiFilename;
  1701. }
  1702. // ---------------------------------------------------------------
  1703. // set default options
  1704. #ifdef __USE_GNU
  1705. const bool isDssiVst(strcasestr(pData->filename, "dssi-vst") != nullptr);
  1706. #else
  1707. const bool isDssiVst(std::strstr(pData->filename, "dssi-vst") != nullptr);
  1708. #endif
  1709. pData->options = 0x0;
  1710. pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  1711. if (fLatencyIndex >= 0 || isDssiVst)
  1712. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  1713. if (pData->engine->getOptions().forceStereo)
  1714. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  1715. if (fUsesCustomData)
  1716. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  1717. if (fDssiDescriptor->run_synth != nullptr || fDssiDescriptor->run_multiple_synths != nullptr)
  1718. {
  1719. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  1720. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  1721. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  1722. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  1723. if (fDssiDescriptor->run_synth == nullptr)
  1724. carla_stderr("WARNING: Plugin can ONLY use run_multiple_synths!");
  1725. }
  1726. return true;
  1727. }
  1728. // -------------------------------------------------------------------
  1729. private:
  1730. LADSPA_Handle fHandle;
  1731. LADSPA_Handle fHandle2;
  1732. const LADSPA_Descriptor* fDescriptor;
  1733. const DSSI_Descriptor* fDssiDescriptor;
  1734. bool fUsesCustomData;
  1735. const char* fUiFilename;
  1736. float** fAudioInBuffers;
  1737. float** fAudioOutBuffers;
  1738. float* fParamBuffers;
  1739. bool fLatencyChanged;
  1740. int32_t fLatencyIndex; // -1 if invalid
  1741. snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents];
  1742. // -------------------------------------------------------------------
  1743. uint32_t getSafePortCount() const noexcept
  1744. {
  1745. if (fDescriptor->PortCount == 0)
  1746. return 0;
  1747. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortDescriptors != nullptr, 0);
  1748. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortRangeHints != nullptr, 0);
  1749. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames != nullptr, 0);
  1750. return static_cast<uint32_t>(fDescriptor->PortCount);
  1751. }
  1752. bool getSeparatedParameterNameOrUnit(const char* const paramName, char* const strBuf, const bool wantName) const noexcept
  1753. {
  1754. if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, true))
  1755. return true;
  1756. if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, false))
  1757. return true;
  1758. return false;
  1759. }
  1760. bool _getSeparatedParameterNameOrUnitImpl(const char* const paramName, char* const strBuf, const bool wantName, const bool useBracket) const noexcept
  1761. {
  1762. const char* const sepBracketStart(std::strstr(paramName, useBracket ? " [" : " ("));
  1763. if (sepBracketStart == nullptr)
  1764. return false;
  1765. const char* const sepBracketEnd(std::strstr(sepBracketStart, useBracket ? "]" : ")"));
  1766. if (sepBracketEnd == nullptr)
  1767. return false;
  1768. const size_t unitSize(static_cast<size_t>(sepBracketEnd-sepBracketStart-2));
  1769. if (unitSize > 7) // very unlikely to have such big unit
  1770. return false;
  1771. const size_t sepIndex(std::strlen(paramName)-unitSize-3);
  1772. // just in case
  1773. if (sepIndex > STR_MAX)
  1774. return false;
  1775. if (wantName)
  1776. {
  1777. std::strncpy(strBuf, paramName, sepIndex);
  1778. strBuf[sepIndex] = '\0';
  1779. }
  1780. else
  1781. {
  1782. std::strncpy(strBuf, paramName+(sepIndex+2), unitSize);
  1783. strBuf[unitSize] = '\0';
  1784. }
  1785. return true;
  1786. }
  1787. // -------------------------------------------------------------------
  1788. static LinkedList<const char*> sMultiSynthList;
  1789. static bool addUniqueMultiSynth(const char* const label) noexcept
  1790. {
  1791. CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0', false);
  1792. const char* dlabel = nullptr;
  1793. try {
  1794. dlabel = carla_strdup(label);
  1795. } catch(...) { return false; }
  1796. for (LinkedList<const char*>::Itenerator it = sMultiSynthList.begin(); it.valid(); it.next())
  1797. {
  1798. const char* const itLabel(it.getValue());
  1799. if (std::strcmp(dlabel, itLabel) == 0)
  1800. {
  1801. delete[] dlabel;
  1802. return false;
  1803. }
  1804. }
  1805. return sMultiSynthList.append(dlabel);
  1806. }
  1807. static void removeUniqueMultiSynth(const char* const label) noexcept
  1808. {
  1809. CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0',);
  1810. for (LinkedList<const char*>::Itenerator it = sMultiSynthList.begin(); it.valid(); it.next())
  1811. {
  1812. const char* const itLabel(it.getValue());
  1813. if (std::strcmp(label, itLabel) == 0)
  1814. {
  1815. sMultiSynthList.remove(it);
  1816. delete[] itLabel;
  1817. break;
  1818. }
  1819. }
  1820. }
  1821. // -------------------------------------------------------------------
  1822. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DssiPlugin)
  1823. };
  1824. LinkedList<const char*> DssiPlugin::sMultiSynthList;
  1825. CARLA_BACKEND_END_NAMESPACE
  1826. #endif // WANT_DSSI
  1827. // -------------------------------------------------------------------------------------------------------------------
  1828. CARLA_BACKEND_START_NAMESPACE
  1829. CarlaPlugin* CarlaPlugin::newDSSI(const Initializer& init)
  1830. {
  1831. carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId);
  1832. #ifdef WANT_DSSI
  1833. DssiPlugin* const plugin(new DssiPlugin(init.engine, init.id));
  1834. if (! plugin->init(init.filename, init.name, init.label))
  1835. {
  1836. delete plugin;
  1837. return nullptr;
  1838. }
  1839. plugin->reload();
  1840. if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack())
  1841. {
  1842. init.engine->setLastError("Carla's rack mode can only work with Mono or Stereo DSSI plugins, sorry!");
  1843. delete plugin;
  1844. return nullptr;
  1845. }
  1846. return plugin;
  1847. #else
  1848. init.engine->setLastError("DSSI support not available");
  1849. return nullptr;
  1850. #endif
  1851. }
  1852. CARLA_BACKEND_END_NAMESPACE
  1853. // -------------------------------------------------------------------------------------------------------------------