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.

CarlaPluginLADSPADSSI.cpp 117KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
8 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 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
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
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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
6 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
8 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214
  1. /*
  2. * Carla Plugin, LADSPA/DSSI implementation
  3. * Copyright (C) 2011-2023 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 "CarlaEngineUtils.hpp"
  19. #include "CarlaBackendUtils.hpp"
  20. #include "CarlaLadspaUtils.hpp"
  21. #include "CarlaDssiUtils.hpp"
  22. #include "CarlaMathUtils.hpp"
  23. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) && !defined(CARLA_OS_WASM)
  24. # define CARLA_ENABLE_DSSI_PLUGIN_GUI
  25. # include "CarlaOscUtils.hpp"
  26. # include "CarlaScopeUtils.hpp"
  27. # include "CarlaThread.hpp"
  28. # include "water/threads/ChildProcess.h"
  29. using water::ChildProcess;
  30. #endif
  31. using water::String;
  32. using water::StringArray;
  33. #define CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
  34. /* check argument count */ \
  35. if (argc != argcToCompare) \
  36. { \
  37. carla_stderr("CarlaPluginLADSPADSSI::%s() - argument count mismatch: %i != %i", \
  38. __FUNCTION__, argc, argcToCompare); \
  39. return; \
  40. } \
  41. if (argc > 0) \
  42. { \
  43. /* check for nullness */ \
  44. if (types == nullptr || typesToCompare == nullptr) \
  45. { \
  46. carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types are null", \
  47. __FUNCTION__); \
  48. return; \
  49. } \
  50. /* check argument types */ \
  51. if (std::strcmp(types, typesToCompare) != 0) \
  52. { \
  53. carla_stderr("CarlaPluginLADSPADSSI::%s() - argument types mismatch: '%s' != '%s'", \
  54. __FUNCTION__, types, typesToCompare); \
  55. return; \
  56. } \
  57. }
  58. CARLA_BACKEND_START_NAMESPACE
  59. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  60. // -------------------------------------------------------------------
  61. // Fallback data
  62. static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
  63. // -------------------------------------------------------------------
  64. class CarlaThreadDSSIUI : public CarlaThread
  65. {
  66. public:
  67. CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPlugin* const plugin, const CarlaOscData& oscData) noexcept
  68. : CarlaThread("CarlaThreadDSSIUI"),
  69. kEngine(engine),
  70. kPlugin(plugin),
  71. fBinary(),
  72. fLabel(),
  73. fUiTitle(),
  74. fOscData(oscData),
  75. fProcess() {}
  76. void setData(const char* const binary, const char* const label, const char* const uiTitle) noexcept
  77. {
  78. CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',);
  79. CARLA_SAFE_ASSERT_RETURN(label != nullptr,);
  80. CARLA_SAFE_ASSERT_RETURN(uiTitle != nullptr && uiTitle[0] != '\0',);
  81. CARLA_SAFE_ASSERT(! isThreadRunning());
  82. fBinary = binary;
  83. fLabel = label;
  84. fUiTitle = uiTitle;
  85. if (fLabel.isEmpty())
  86. fLabel = "\"\"";
  87. }
  88. void setUITitle(const char* const uiTitle) noexcept
  89. {
  90. CARLA_SAFE_ASSERT_RETURN(uiTitle != nullptr && uiTitle[0] != '\0',);
  91. fUiTitle = uiTitle;
  92. }
  93. uintptr_t getProcessId() const noexcept
  94. {
  95. CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0);
  96. return (uintptr_t)fProcess->getPID();
  97. }
  98. void run()
  99. {
  100. carla_stdout("LADSPA/DSSI UI thread started");
  101. if (fProcess == nullptr)
  102. {
  103. fProcess = new ChildProcess();
  104. }
  105. else if (fProcess->isRunning())
  106. {
  107. carla_stderr("CarlaThreadDSSI::run() - already running, giving up...");
  108. fProcess->kill();
  109. fProcess = nullptr;
  110. kEngine->callback(true, true,
  111. ENGINE_CALLBACK_UI_STATE_CHANGED,
  112. kPlugin->getId(),
  113. 0,
  114. 0, 0, 0.0f, nullptr);
  115. return;
  116. }
  117. String name(kPlugin->getName());
  118. String filename(kPlugin->getFilename());
  119. if (name.isEmpty())
  120. name = "(none)";
  121. if (filename.isEmpty())
  122. filename = "\"\"";
  123. StringArray arguments;
  124. // binary
  125. arguments.add(fBinary.buffer());
  126. // osc-url
  127. arguments.add(String(kEngine->getOscServerPathUDP()) + String("/") + String(kPlugin->getId()));
  128. // filename
  129. arguments.add(filename);
  130. // label
  131. arguments.add(fLabel.buffer());
  132. // ui-title
  133. arguments.add(fUiTitle.buffer());
  134. bool started;
  135. {
  136. #ifdef CARLA_OS_LINUX
  137. /*
  138. * If the frontend uses winId parent, set LD_PRELOAD to auto-map the DSSI UI.
  139. * If not, unset LD_PRELOAD.
  140. */
  141. const uintptr_t winId(kEngine->getOptions().frontendWinId);
  142. // for CARLA_ENGINE_OPTION_FRONTEND_WIN_ID
  143. char winIdStr[STR_MAX+1];
  144. winIdStr[STR_MAX] = '\0';
  145. // for LD_PRELOAD
  146. CarlaString ldPreloadValue;
  147. if (winId != 0)
  148. {
  149. std::snprintf(winIdStr, STR_MAX, P_UINTPTR, winId);
  150. ldPreloadValue = (CarlaString(kEngine->getOptions().binaryDir)
  151. + "/libcarla_interposer-x11.so");
  152. }
  153. else
  154. {
  155. winIdStr[0] = '\0';
  156. }
  157. const ScopedEngineEnvironmentLocker _seel(kEngine);
  158. const CarlaScopedEnvVar _sev1("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID", winIdStr[0] != '\0' ? winIdStr : nullptr);
  159. const CarlaScopedEnvVar _sev2("LD_PRELOAD", ldPreloadValue.isNotEmpty() ? ldPreloadValue.buffer() : nullptr);
  160. #endif // CARLA_OS_LINUX
  161. // start the DSSI UI application
  162. carla_stdout("starting DSSI UI...");
  163. started = fProcess->start(arguments);
  164. }
  165. if (! started)
  166. {
  167. carla_stdout("failed!");
  168. fProcess = nullptr;
  169. return;
  170. }
  171. if (waitForOscGuiShow())
  172. {
  173. for (; fProcess->isRunning() && ! shouldThreadExit();)
  174. carla_sleep(1);
  175. // we only get here if UI was closed or thread asked to exit
  176. if (fProcess->isRunning() && shouldThreadExit())
  177. {
  178. fProcess->waitForProcessToFinish(static_cast<int>(kEngine->getOptions().uiBridgesTimeout));
  179. if (fProcess->isRunning())
  180. {
  181. carla_stdout("CarlaThreadDSSIUI::run() - UI refused to close, force kill now");
  182. fProcess->kill();
  183. }
  184. else
  185. {
  186. carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully");
  187. }
  188. }
  189. else if (fProcess->getExitCodeAndClearPID() != 0)
  190. carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running");
  191. else
  192. carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly");
  193. }
  194. else
  195. {
  196. fProcess->kill();
  197. carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout");
  198. }
  199. fProcess = nullptr;
  200. kEngine->callback(true, true,
  201. ENGINE_CALLBACK_UI_STATE_CHANGED,
  202. kPlugin->getId(),
  203. 0,
  204. 0, 0, 0.0f, nullptr);
  205. carla_stdout("LADSPA/DSSI UI thread finished");
  206. }
  207. private:
  208. CarlaEngine* const kEngine;
  209. CarlaPlugin* const kPlugin;
  210. CarlaString fBinary;
  211. CarlaString fLabel;
  212. CarlaString fUiTitle;
  213. const CarlaOscData& fOscData;
  214. CarlaScopedPointer<ChildProcess> fProcess;
  215. bool waitForOscGuiShow()
  216. {
  217. carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow()");
  218. const uint uiBridgesTimeout = kEngine->getOptions().uiBridgesTimeout;
  219. // wait for UI 'update' call
  220. for (uint i=0; i < uiBridgesTimeout/100; ++i)
  221. {
  222. if (fOscData.target != nullptr)
  223. {
  224. carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - got response, asking UI to show itself now");
  225. osc_send_show(fOscData);
  226. return true;
  227. }
  228. if (fProcess != nullptr && fProcess->isRunning() && ! shouldThreadExit())
  229. carla_msleep(100);
  230. else
  231. return false;
  232. }
  233. carla_stdout("CarlaThreadDSSIUI::waitForOscGuiShow() - Timeout while waiting for UI to respond"
  234. "(waited %u msecs)", uiBridgesTimeout);
  235. return false;
  236. }
  237. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThreadDSSIUI)
  238. };
  239. #endif
  240. // -----------------------------------------------------
  241. class CarlaPluginLADSPADSSI : public CarlaPlugin
  242. {
  243. public:
  244. CarlaPluginLADSPADSSI(CarlaEngine* const engine, const uint id) noexcept
  245. : CarlaPlugin(engine, id),
  246. fHandles(),
  247. fDescriptor(nullptr),
  248. fDssiDescriptor(nullptr),
  249. fRdfDescriptor(nullptr),
  250. fAudioInBuffers(nullptr),
  251. fAudioOutBuffers(nullptr),
  252. fExtraStereoBuffer(),
  253. fParamBuffers(nullptr),
  254. fLatencyIndex(-1),
  255. fForcedStereoIn(false),
  256. fForcedStereoOut(false),
  257. fNeedsFixedBuffers(false),
  258. fUsesCustomData(false)
  259. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  260. , fOscData(),
  261. fThreadUI(engine, this, fOscData),
  262. fUiFilename(nullptr)
  263. #endif
  264. {
  265. carla_debug("CarlaPluginLADSPADSSI::CarlaPluginLADSPADSSI(%p, %i)", engine, id);
  266. carla_zeroPointers(fExtraStereoBuffer, 2);
  267. }
  268. ~CarlaPluginLADSPADSSI() noexcept override
  269. {
  270. carla_debug("CarlaPluginLADSPADSSI::~CarlaPluginLADSPADSSI()");
  271. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  272. // close UI
  273. if (fUiFilename != nullptr)
  274. {
  275. showCustomUI(false);
  276. delete[] fUiFilename;
  277. fUiFilename = nullptr;
  278. }
  279. #endif
  280. pData->singleMutex.lock();
  281. pData->masterMutex.lock();
  282. if (pData->client != nullptr && pData->client->isActive())
  283. pData->client->deactivate(true);
  284. if (pData->active)
  285. {
  286. deactivate();
  287. pData->active = false;
  288. }
  289. if (fDescriptor != nullptr)
  290. {
  291. if (fDescriptor->cleanup != nullptr)
  292. {
  293. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  294. {
  295. LADSPA_Handle const handle(it.getValue(nullptr));
  296. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  297. try {
  298. fDescriptor->cleanup(handle);
  299. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
  300. }
  301. }
  302. fHandles.clear();
  303. fDescriptor = nullptr;
  304. fDssiDescriptor = nullptr;
  305. }
  306. if (fRdfDescriptor != nullptr)
  307. {
  308. delete fRdfDescriptor;
  309. fRdfDescriptor = nullptr;
  310. }
  311. clearBuffers();
  312. }
  313. // -------------------------------------------------------------------
  314. // Information (base)
  315. PluginType getType() const noexcept override
  316. {
  317. return fDssiDescriptor != nullptr ? PLUGIN_DSSI : PLUGIN_LADSPA;
  318. }
  319. PluginCategory getCategory() const noexcept override
  320. {
  321. if (fRdfDescriptor != nullptr)
  322. {
  323. const LADSPA_RDF_PluginType category = fRdfDescriptor->Type;
  324. // Specific Types
  325. if (category & (LADSPA_RDF_PLUGIN_DELAY|LADSPA_RDF_PLUGIN_REVERB))
  326. return PLUGIN_CATEGORY_DELAY;
  327. if (category & (LADSPA_RDF_PLUGIN_PHASER|LADSPA_RDF_PLUGIN_FLANGER|LADSPA_RDF_PLUGIN_CHORUS))
  328. return PLUGIN_CATEGORY_MODULATOR;
  329. if (category & (LADSPA_RDF_PLUGIN_AMPLIFIER))
  330. return PLUGIN_CATEGORY_DYNAMICS;
  331. if (category & (LADSPA_RDF_PLUGIN_UTILITY|LADSPA_RDF_PLUGIN_SPECTRAL|LADSPA_RDF_PLUGIN_FREQUENCY_METER))
  332. return PLUGIN_CATEGORY_UTILITY;
  333. // Pre-set LADSPA Types
  334. if (LADSPA_RDF_IS_PLUGIN_DYNAMICS(category))
  335. return PLUGIN_CATEGORY_DYNAMICS;
  336. if (LADSPA_RDF_IS_PLUGIN_AMPLITUDE(category))
  337. return PLUGIN_CATEGORY_MODULATOR;
  338. if (LADSPA_RDF_IS_PLUGIN_EQ(category))
  339. return PLUGIN_CATEGORY_EQ;
  340. if (LADSPA_RDF_IS_PLUGIN_FILTER(category))
  341. return PLUGIN_CATEGORY_FILTER;
  342. if (LADSPA_RDF_IS_PLUGIN_FREQUENCY(category))
  343. return PLUGIN_CATEGORY_UTILITY;
  344. if (LADSPA_RDF_IS_PLUGIN_SIMULATOR(category))
  345. return PLUGIN_CATEGORY_OTHER;
  346. if (LADSPA_RDF_IS_PLUGIN_TIME(category))
  347. return PLUGIN_CATEGORY_DELAY;
  348. if (LADSPA_RDF_IS_PLUGIN_GENERATOR(category))
  349. return PLUGIN_CATEGORY_SYNTH;
  350. }
  351. if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
  352. if (pData->audioIn.count == 0 && pData->audioOut.count > 0)
  353. return PLUGIN_CATEGORY_SYNTH;
  354. return CarlaPlugin::getCategory();
  355. }
  356. int64_t getUniqueId() const noexcept override
  357. {
  358. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0);
  359. return static_cast<int64_t>(fDescriptor->UniqueID);
  360. }
  361. uint32_t getLatencyInFrames() const noexcept override
  362. {
  363. if (fLatencyIndex < 0 || fParamBuffers == nullptr)
  364. return 0;
  365. const float latency(fParamBuffers[fLatencyIndex]);
  366. CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0);
  367. return static_cast<uint32_t>(latency);
  368. }
  369. // -------------------------------------------------------------------
  370. // Information (count)
  371. uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
  372. {
  373. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
  374. if (fRdfDescriptor == nullptr)
  375. return 0;
  376. const int32_t rindex(pData->param.data[parameterId].rindex);
  377. CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0);
  378. if (rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
  379. return 0;
  380. const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
  381. return static_cast<uint32_t>(port.ScalePointCount);
  382. }
  383. // -------------------------------------------------------------------
  384. // Information (current data)
  385. std::size_t getChunkData(void** const dataPtr) noexcept override
  386. {
  387. CARLA_SAFE_ASSERT_RETURN(fUsesCustomData, 0);
  388. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  389. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr, 0);
  390. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->get_custom_data != nullptr, 0);
  391. CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0, 0);
  392. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  393. *dataPtr = nullptr;
  394. int ret = 0;
  395. ulong dataSize = 0;
  396. try {
  397. ret = fDssiDescriptor->get_custom_data(fHandles.getFirst(nullptr), dataPtr, &dataSize);
  398. } CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginLADSPADSSI::getChunkData", 0);
  399. return (ret != 0) ? dataSize : 0;
  400. }
  401. // -------------------------------------------------------------------
  402. // Information (per-plugin data)
  403. uint getOptionsAvailable() const noexcept override
  404. {
  405. uint options = 0x0;
  406. // can't disable fixed buffers if using latency
  407. if (fLatencyIndex == -1 && ! fNeedsFixedBuffers)
  408. options |= PLUGIN_OPTION_FIXED_BUFFERS;
  409. // can't disable forced stereo if enabled in the engine
  410. if (pData->engine->getOptions().forceStereo)
  411. pass();
  412. // if inputs or outputs are just 1, then yes we can force stereo
  413. else if (pData->audioIn.count == 1 || pData->audioOut.count == 1 || fForcedStereoIn || fForcedStereoOut)
  414. options |= PLUGIN_OPTION_FORCE_STEREO;
  415. if (fDssiDescriptor != nullptr)
  416. {
  417. if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
  418. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  419. if (fUsesCustomData)
  420. options |= PLUGIN_OPTION_USE_CHUNKS;
  421. if (fDssiDescriptor->run_synth != nullptr)
  422. {
  423. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  424. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  425. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  426. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  427. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  428. options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
  429. }
  430. }
  431. return options;
  432. }
  433. float getParameterValue(const uint32_t parameterId) const noexcept override
  434. {
  435. CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f);
  436. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  437. // bad plugins might have set output values out of bounds
  438. if (pData->param.data[parameterId].type == PARAMETER_OUTPUT)
  439. return pData->param.ranges[parameterId].getFixedValue(fParamBuffers[parameterId]);
  440. // not output, should be fine
  441. return fParamBuffers[parameterId];
  442. }
  443. float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
  444. {
  445. CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f);
  446. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  447. const int32_t rindex(pData->param.data[parameterId].rindex);
  448. CARLA_SAFE_ASSERT_RETURN(rindex >= 0, 0.0f);
  449. CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->PortCount), 0.0f);
  450. const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
  451. CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, 0.0f);
  452. const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]);
  453. return pData->param.ranges[parameterId].getFixedValue(scalePoint.Value);
  454. }
  455. bool getLabel(char* const strBuf) const noexcept override
  456. {
  457. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
  458. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Label != nullptr, false);
  459. std::strncpy(strBuf, fDescriptor->Label, STR_MAX);
  460. return true;
  461. }
  462. bool getMaker(char* const strBuf) const noexcept override
  463. {
  464. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
  465. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Maker != nullptr, false);
  466. if (fRdfDescriptor != nullptr && fRdfDescriptor->Creator != nullptr)
  467. std::strncpy(strBuf, fRdfDescriptor->Creator, STR_MAX);
  468. else
  469. std::strncpy(strBuf, fDescriptor->Maker, STR_MAX);
  470. return true;
  471. }
  472. bool getCopyright(char* const strBuf) const noexcept override
  473. {
  474. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
  475. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Copyright != nullptr, false);
  476. std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX);
  477. return true;
  478. }
  479. bool getRealName(char* const strBuf) const noexcept override
  480. {
  481. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
  482. CARLA_SAFE_ASSERT_RETURN(fDescriptor->Name != nullptr, false);
  483. if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr)
  484. std::strncpy(strBuf, fRdfDescriptor->Title, STR_MAX);
  485. else
  486. std::strncpy(strBuf, fDescriptor->Name, STR_MAX);
  487. return true;
  488. }
  489. bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  490. {
  491. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, false);
  492. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  493. const int32_t rindex(pData->param.data[parameterId].rindex);
  494. CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
  495. CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), false);
  496. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false);
  497. if (! getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, true))
  498. std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX);
  499. return true;
  500. }
  501. bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  502. {
  503. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  504. const int32_t rindex(pData->param.data[parameterId].rindex);
  505. CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
  506. if (fRdfDescriptor != nullptr && rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
  507. {
  508. const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
  509. if (LADSPA_RDF_PORT_HAS_UNIT(port.Hints))
  510. {
  511. switch (port.Unit)
  512. {
  513. case LADSPA_RDF_UNIT_DB:
  514. std::strncpy(strBuf, "dB", STR_MAX);
  515. return true;
  516. case LADSPA_RDF_UNIT_COEF:
  517. std::strncpy(strBuf, "(coef)", STR_MAX);
  518. return true;
  519. case LADSPA_RDF_UNIT_HZ:
  520. std::strncpy(strBuf, "Hz", STR_MAX);
  521. return true;
  522. case LADSPA_RDF_UNIT_S:
  523. std::strncpy(strBuf, "s", STR_MAX);
  524. return true;
  525. case LADSPA_RDF_UNIT_MS:
  526. std::strncpy(strBuf, "ms", STR_MAX);
  527. return true;
  528. case LADSPA_RDF_UNIT_MIN:
  529. std::strncpy(strBuf, "min", STR_MAX);
  530. return true;
  531. }
  532. }
  533. }
  534. CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fDescriptor->PortCount), false);
  535. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames[rindex] != nullptr, false);
  536. return getSeparatedParameterNameOrUnit(fDescriptor->PortNames[rindex], strBuf, false);
  537. }
  538. bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
  539. {
  540. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  541. if (fRdfDescriptor == nullptr)
  542. return false;
  543. const int32_t rindex(pData->param.data[parameterId].rindex);
  544. CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
  545. if (rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
  546. return false;
  547. const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
  548. if (! LADSPA_RDF_PORT_HAS_LABEL(port.Hints))
  549. return false;
  550. CARLA_SAFE_ASSERT_RETURN(port.Label != nullptr, false);
  551. std::strncpy(strBuf, port.Label, STR_MAX);
  552. return true;
  553. }
  554. bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
  555. {
  556. CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
  557. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  558. const int32_t rindex(pData->param.data[parameterId].rindex);
  559. CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
  560. CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->PortCount), false);
  561. const LADSPA_RDF_Port& port(fRdfDescriptor->Ports[rindex]);
  562. CARLA_SAFE_ASSERT_RETURN(scalePointId < port.ScalePointCount, false);
  563. const LADSPA_RDF_ScalePoint& scalePoint(port.ScalePoints[scalePointId]);
  564. CARLA_SAFE_ASSERT_RETURN(scalePoint.Label != nullptr, false);
  565. std::strncpy(strBuf, scalePoint.Label, STR_MAX);
  566. return true;
  567. }
  568. // -------------------------------------------------------------------
  569. // Set data (state)
  570. // nothing
  571. // -------------------------------------------------------------------
  572. // Set data (internal stuff)
  573. void setId(const uint newId) noexcept override
  574. {
  575. CarlaPlugin::setId(newId);
  576. // UI osc-url uses Id, so we need to close it when it changes
  577. // FIXME - must be RT safe
  578. showCustomUI(false);
  579. }
  580. // -------------------------------------------------------------------
  581. // Set data (plugin-specific stuff)
  582. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  583. {
  584. CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
  585. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  586. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  587. fParamBuffers[parameterId] = fixedValue;
  588. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  589. }
  590. void setParameterValueRT(const uint32_t parameterId, const float value, const uint32_t frameOffset, const bool sendCallbackLater) noexcept override
  591. {
  592. CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
  593. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  594. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  595. fParamBuffers[parameterId] = fixedValue;
  596. CarlaPlugin::setParameterValueRT(parameterId, fixedValue, frameOffset, sendCallbackLater);
  597. }
  598. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  599. {
  600. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  601. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  602. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  603. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  604. carla_debug("CarlaPluginLADSPADSSI::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
  605. if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
  606. return CarlaPlugin::setCustomData(type, key, value, sendGui);
  607. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
  608. return carla_stderr2("CarlaPluginLADSPADSSI::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string",
  609. type, key, value, bool2str(sendGui));
  610. if (fDssiDescriptor->configure != nullptr && fHandles.count() > 0)
  611. {
  612. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  613. {
  614. LADSPA_Handle const handle(it.getValue(nullptr));
  615. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  616. try {
  617. fDssiDescriptor->configure(handle, key, value);
  618. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setCustomData");
  619. }
  620. }
  621. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  622. if (sendGui && fOscData.target != nullptr)
  623. osc_send_configure(fOscData, key, value);
  624. #endif
  625. if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0)
  626. {
  627. const ScopedSingleProcessLocker spl(this, true);
  628. reloadPrograms(false);
  629. }
  630. CarlaPlugin::setCustomData(type, key, value, sendGui);
  631. }
  632. void setChunkData(const void* const data, const std::size_t dataSize) override
  633. {
  634. CARLA_SAFE_ASSERT_RETURN(fUsesCustomData,);
  635. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  636. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  637. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->set_custom_data != nullptr,);
  638. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  639. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  640. if (fHandles.count() > 0)
  641. {
  642. const ScopedSingleProcessLocker spl(this, true);
  643. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  644. {
  645. LADSPA_Handle const handle(it.getValue(nullptr));
  646. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  647. try {
  648. fDssiDescriptor->set_custom_data(handle, const_cast<void*>(data), static_cast<ulong>(dataSize));
  649. } CARLA_SAFE_EXCEPTION("CarlaPluginLADSPADSSI::setChunkData");
  650. }
  651. }
  652. pData->updateParameterValues(this, true, true, false);
  653. }
  654. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
  655. {
  656. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  657. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
  658. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  659. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
  660. if (index >= 0 && fHandles.count() > 0)
  661. {
  662. const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  663. setMidiProgramInDSSI(static_cast<uint32_t>(index));
  664. }
  665. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
  666. }
  667. void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
  668. {
  669. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor != nullptr,);
  670. CARLA_SAFE_ASSERT_RETURN(fDssiDescriptor->select_program != nullptr,);
  671. CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
  672. setMidiProgramInDSSI(uindex);
  673. CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
  674. }
  675. void setMidiProgramInDSSI(const uint32_t uindex) noexcept
  676. {
  677. const uint32_t bank(pData->midiprog.data[uindex].bank);
  678. const uint32_t program(pData->midiprog.data[uindex].program);
  679. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  680. {
  681. LADSPA_Handle const handle(it.getValue(nullptr));
  682. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  683. try {
  684. fDssiDescriptor->select_program(handle, bank, program);
  685. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI setMidiProgram")
  686. }
  687. }
  688. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  689. // -------------------------------------------------------------------
  690. // Set ui stuff
  691. void setCustomUITitle(const char* title) noexcept override
  692. {
  693. fThreadUI.setUITitle(title);
  694. CarlaPlugin::setCustomUITitle(title);
  695. }
  696. void showCustomUI(const bool yesNo) override
  697. {
  698. if (yesNo)
  699. {
  700. fOscData.clear();
  701. fThreadUI.startThread();
  702. }
  703. else
  704. {
  705. #ifndef BUILD_BRIDGE
  706. pData->transientTryCounter = 0;
  707. #endif
  708. if (fOscData.target != nullptr)
  709. {
  710. osc_send_hide(fOscData);
  711. osc_send_quit(fOscData);
  712. fOscData.clear();
  713. }
  714. fThreadUI.stopThread(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
  715. }
  716. }
  717. #endif
  718. // -------------------------------------------------------------------
  719. // Plugin state
  720. void reload() override
  721. {
  722. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  723. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  724. CARLA_SAFE_ASSERT_RETURN(fHandles.count() > 0,);
  725. carla_debug("CarlaPluginLADSPADSSI::reload() - start");
  726. const EngineProcessMode processMode(pData->engine->getProccessMode());
  727. // Safely disable plugin for reload
  728. const ScopedDisabler sd(this);
  729. if (pData->active)
  730. deactivate();
  731. clearBuffers();
  732. const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
  733. const uint32_t portCount(getSafePortCount());
  734. uint32_t aIns, aOuts, mIns, params;
  735. aIns = aOuts = mIns = params = 0;
  736. bool forcedStereoIn, forcedStereoOut;
  737. forcedStereoIn = forcedStereoOut = false;
  738. bool needsCtrlIn, needsCtrlOut;
  739. needsCtrlIn = needsCtrlOut = false;
  740. for (uint32_t i=0; i < portCount; ++i)
  741. {
  742. const LADSPA_PortDescriptor portType(fDescriptor->PortDescriptors[i]);
  743. if (LADSPA_IS_PORT_AUDIO(portType))
  744. {
  745. if (LADSPA_IS_PORT_INPUT(portType))
  746. aIns += 1;
  747. else if (LADSPA_IS_PORT_OUTPUT(portType))
  748. aOuts += 1;
  749. }
  750. else if (LADSPA_IS_PORT_CONTROL(portType))
  751. params += 1;
  752. }
  753. if (pData->options & PLUGIN_OPTION_FORCE_STEREO)
  754. {
  755. if ((aIns == 1 || aOuts == 1) && fHandles.count() == 1 && addInstance())
  756. {
  757. if (aIns == 1)
  758. {
  759. aIns = 2;
  760. forcedStereoIn = true;
  761. }
  762. if (aOuts == 1)
  763. {
  764. aOuts = 2;
  765. forcedStereoOut = true;
  766. }
  767. }
  768. }
  769. if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
  770. {
  771. mIns = 1;
  772. needsCtrlIn = true;
  773. }
  774. if (aIns > 0)
  775. {
  776. pData->audioIn.createNew(aIns);
  777. fAudioInBuffers = new float*[aIns];
  778. for (uint32_t i=0; i < aIns; ++i)
  779. fAudioInBuffers[i] = nullptr;
  780. }
  781. if (aOuts > 0)
  782. {
  783. pData->audioOut.createNew(aOuts);
  784. fAudioOutBuffers = new float*[aOuts];
  785. needsCtrlIn = true;
  786. for (uint32_t i=0; i < aOuts; ++i)
  787. fAudioOutBuffers[i] = nullptr;
  788. }
  789. if (params > 0)
  790. {
  791. pData->param.createNew(params, true);
  792. fParamBuffers = new float[params];
  793. carla_zeroFloats(fParamBuffers, params);
  794. }
  795. const uint portNameSize(pData->engine->getMaxPortNameSize());
  796. CarlaString portName;
  797. for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCtrl=0; i < portCount; ++i)
  798. {
  799. const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i];
  800. const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i];
  801. const bool hasPortRDF = (fRdfDescriptor != nullptr && i < fRdfDescriptor->PortCount);
  802. if (LADSPA_IS_PORT_AUDIO(portType))
  803. {
  804. portName.clear();
  805. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  806. {
  807. portName = pData->name;
  808. portName += ":";
  809. }
  810. if (fDescriptor->PortNames[i] != nullptr && fDescriptor->PortNames[i][0] != '\0')
  811. {
  812. portName += fDescriptor->PortNames[i];
  813. }
  814. else
  815. {
  816. if (LADSPA_IS_PORT_INPUT(portType))
  817. {
  818. if (aIns > 1)
  819. {
  820. portName += "audio-in_";
  821. portName += CarlaString(iAudioIn+1);
  822. }
  823. else
  824. portName += "audio-in";
  825. }
  826. else
  827. {
  828. if (aOuts > 1)
  829. {
  830. portName += "audio-out_";
  831. portName += CarlaString(iAudioOut+1);
  832. }
  833. else
  834. portName += "audio-out";
  835. }
  836. }
  837. portName.truncate(portNameSize);
  838. if (LADSPA_IS_PORT_INPUT(portType))
  839. {
  840. const uint32_t j = iAudioIn++;
  841. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
  842. pData->audioIn.ports[j].rindex = i;
  843. if (forcedStereoIn)
  844. {
  845. portName += "_2";
  846. pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1);
  847. pData->audioIn.ports[1].rindex = i;
  848. }
  849. }
  850. else if (LADSPA_IS_PORT_OUTPUT(portType))
  851. {
  852. const uint32_t j = iAudioOut++;
  853. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
  854. pData->audioOut.ports[j].rindex = i;
  855. if (forcedStereoOut)
  856. {
  857. portName += "_2";
  858. pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1);
  859. pData->audioOut.ports[1].rindex = i;
  860. }
  861. }
  862. else
  863. carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
  864. }
  865. else if (LADSPA_IS_PORT_CONTROL(portType))
  866. {
  867. const uint32_t j = iCtrl++;
  868. pData->param.data[j].index = static_cast<int32_t>(j);
  869. pData->param.data[j].rindex = static_cast<int32_t>(i);
  870. const char* const paramName(fDescriptor->PortNames[i] != nullptr ? fDescriptor->PortNames[i] : "unknown");
  871. float min, max, def, step, stepSmall, stepLarge;
  872. // min value
  873. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  874. min = portRangeHints.LowerBound;
  875. else
  876. min = 0.0f;
  877. // max value
  878. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  879. max = portRangeHints.UpperBound;
  880. else
  881. max = 1.0f;
  882. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  883. {
  884. min *= sampleRate;
  885. max *= sampleRate;
  886. pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  887. }
  888. if (min >= max)
  889. {
  890. carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", paramName);
  891. max = min + 0.1f;
  892. }
  893. // default value
  894. if (hasPortRDF && LADSPA_RDF_PORT_HAS_DEFAULT(fRdfDescriptor->Ports[i].Hints))
  895. def = fRdfDescriptor->Ports[i].Default;
  896. else
  897. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  898. if (def < min)
  899. def = min;
  900. else if (def > max)
  901. def = max;
  902. if (LADSPA_IS_HINT_TOGGLED(portRangeHints.HintDescriptor))
  903. {
  904. step = max - min;
  905. stepSmall = step;
  906. stepLarge = step;
  907. pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  908. }
  909. else if (LADSPA_IS_HINT_INTEGER(portRangeHints.HintDescriptor))
  910. {
  911. step = 1.0f;
  912. stepSmall = 1.0f;
  913. stepLarge = 10.0f;
  914. pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  915. }
  916. else
  917. {
  918. const float range = max - min;
  919. step = range/100.0f;
  920. stepSmall = range/1000.0f;
  921. stepLarge = range/10.0f;
  922. }
  923. if (LADSPA_IS_PORT_INPUT(portType))
  924. {
  925. pData->param.data[j].type = PARAMETER_INPUT;
  926. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  927. pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
  928. pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED;
  929. needsCtrlIn = true;
  930. // MIDI CC value
  931. if (fDssiDescriptor != nullptr && fDssiDescriptor->get_midi_controller_for_port != nullptr)
  932. {
  933. const int ctrl = fDssiDescriptor->get_midi_controller_for_port(fHandles.getFirst(nullptr), i);
  934. if (DSSI_CONTROLLER_IS_SET(ctrl) && DSSI_IS_CC(ctrl))
  935. {
  936. const int16_t cc = DSSI_CC_NUMBER(ctrl);
  937. if (cc < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(cc))
  938. pData->param.data[j].mappedControlIndex = cc;
  939. }
  940. }
  941. }
  942. else if (LADSPA_IS_PORT_OUTPUT(portType))
  943. {
  944. pData->param.data[j].type = PARAMETER_OUTPUT;
  945. if (std::strcmp(paramName, "latency") == 0 || std::strcmp(paramName, "_latency") == 0)
  946. {
  947. min = 0.0f;
  948. max = sampleRate;
  949. def = 0.0f;
  950. step = 1.0f;
  951. stepSmall = 1.0f;
  952. stepLarge = 1.0f;
  953. pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
  954. CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast<int32_t>(j), fLatencyIndex, j);
  955. }
  956. else
  957. {
  958. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  959. pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
  960. needsCtrlOut = true;
  961. }
  962. }
  963. else
  964. {
  965. carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
  966. }
  967. // extra parameter hints
  968. if (LADSPA_IS_HINT_LOGARITHMIC(portRangeHints.HintDescriptor))
  969. pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  970. // check for scalepoints, require at least 2 to make it useful
  971. if (hasPortRDF && fRdfDescriptor->Ports[i].ScalePointCount >= 2)
  972. pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
  973. pData->param.ranges[j].min = min;
  974. pData->param.ranges[j].max = max;
  975. pData->param.ranges[j].def = def;
  976. pData->param.ranges[j].step = step;
  977. pData->param.ranges[j].stepSmall = stepSmall;
  978. pData->param.ranges[j].stepLarge = stepLarge;
  979. // Start parameters in their default values
  980. fParamBuffers[j] = def;
  981. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  982. {
  983. LADSPA_Handle const handle(it.getValue(nullptr));
  984. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  985. try {
  986. fDescriptor->connect_port(handle, i, &fParamBuffers[j]);
  987. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (parameter)");
  988. }
  989. }
  990. else
  991. {
  992. // Not Audio or Control
  993. carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)");
  994. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  995. {
  996. LADSPA_Handle const handle(it.getValue(nullptr));
  997. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  998. try {
  999. fDescriptor->connect_port(handle, i, nullptr);
  1000. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (null)");
  1001. }
  1002. }
  1003. }
  1004. if (needsCtrlIn)
  1005. {
  1006. portName.clear();
  1007. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1008. {
  1009. portName = pData->name;
  1010. portName += ":";
  1011. }
  1012. portName += "events-in";
  1013. portName.truncate(portNameSize);
  1014. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
  1015. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1016. pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
  1017. #endif
  1018. }
  1019. if (needsCtrlOut)
  1020. {
  1021. portName.clear();
  1022. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1023. {
  1024. portName = pData->name;
  1025. portName += ":";
  1026. }
  1027. portName += "events-out";
  1028. portName.truncate(portNameSize);
  1029. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
  1030. }
  1031. if (forcedStereoIn || forcedStereoOut)
  1032. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  1033. else
  1034. pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
  1035. // plugin hints
  1036. pData->hints = 0x0;
  1037. if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties))
  1038. pData->hints |= PLUGIN_IS_RTSAFE;
  1039. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  1040. if (fUiFilename != nullptr)
  1041. pData->hints |= PLUGIN_HAS_CUSTOM_UI;
  1042. #endif
  1043. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1044. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  1045. pData->hints |= PLUGIN_CAN_DRYWET;
  1046. if (aOuts > 0)
  1047. pData->hints |= PLUGIN_CAN_VOLUME;
  1048. if (aOuts >= 2 && aOuts % 2 == 0)
  1049. pData->hints |= PLUGIN_CAN_BALANCE;
  1050. #endif
  1051. // extra plugin hints
  1052. pData->extraHints = 0x0;
  1053. if (mIns > 0)
  1054. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  1055. // check initial latency
  1056. findInitialLatencyValue(aIns, aOuts);
  1057. fForcedStereoIn = forcedStereoIn;
  1058. fForcedStereoOut = forcedStereoOut;
  1059. bufferSizeChanged(pData->engine->getBufferSize());
  1060. reloadPrograms(true);
  1061. if (pData->active)
  1062. activate();
  1063. carla_debug("CarlaPluginLADSPADSSI::reload() - end");
  1064. }
  1065. void findInitialLatencyValue(const uint32_t aIns, const uint32_t aOuts) const
  1066. {
  1067. if (fLatencyIndex < 0 || fHandles.count() == 0)
  1068. return;
  1069. // we need to pre-run the plugin so it can update its latency control-port
  1070. const LADSPA_Handle handle(fHandles.getFirst(nullptr));
  1071. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  1072. float tmpIn[64][2];
  1073. float tmpOut[64][2];
  1074. for (uint32_t j=0; j < aIns; ++j)
  1075. {
  1076. tmpIn[j][0] = 0.0f;
  1077. tmpIn[j][1] = 0.0f;
  1078. try {
  1079. fDescriptor->connect_port(handle, pData->audioIn.ports[j].rindex, tmpIn[j]);
  1080. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency input)");
  1081. }
  1082. for (uint32_t j=0; j < aOuts; ++j)
  1083. {
  1084. tmpOut[j][0] = 0.0f;
  1085. tmpOut[j][1] = 0.0f;
  1086. try {
  1087. fDescriptor->connect_port(handle, pData->audioOut.ports[j].rindex, tmpOut[j]);
  1088. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (latency output)");
  1089. }
  1090. if (fDescriptor->activate != nullptr)
  1091. {
  1092. try {
  1093. fDescriptor->activate(handle);
  1094. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency activate");
  1095. }
  1096. try {
  1097. fDescriptor->run(handle, 2);
  1098. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency run");
  1099. if (fDescriptor->deactivate != nullptr)
  1100. {
  1101. try {
  1102. fDescriptor->deactivate(handle);
  1103. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI latency deactivate");
  1104. }
  1105. // done, let's get the value
  1106. if (const uint32_t latency = getLatencyInFrames())
  1107. {
  1108. pData->client->setLatency(latency);
  1109. #ifndef BUILD_BRIDGE
  1110. pData->latency.recreateBuffers(std::max(aIns, aOuts), latency);
  1111. #endif
  1112. }
  1113. }
  1114. void reloadPrograms(const bool doInit) override
  1115. {
  1116. carla_debug("CarlaPluginLADSPADSSI::reloadPrograms(%s)", bool2str(doInit));
  1117. const LADSPA_Handle handle(fHandles.getFirst(nullptr));
  1118. CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
  1119. const uint32_t oldCount = pData->midiprog.count;
  1120. const int32_t current = pData->midiprog.current;
  1121. // Delete old programs
  1122. pData->midiprog.clear();
  1123. // nothing to do for simple LADSPA plugins (do we want to bother with lrdf presets?)
  1124. if (fDssiDescriptor == nullptr)
  1125. return;
  1126. // Query new programs
  1127. uint32_t newCount = 0;
  1128. if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
  1129. {
  1130. for (; fDssiDescriptor->get_program(handle, newCount) != nullptr;)
  1131. ++newCount;
  1132. }
  1133. if (newCount > 0)
  1134. {
  1135. pData->midiprog.createNew(newCount);
  1136. // Update data
  1137. for (uint32_t i=0; i < newCount; ++i)
  1138. {
  1139. const DSSI_Program_Descriptor* const pdesc(fDssiDescriptor->get_program(handle, i));
  1140. CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr);
  1141. CARLA_SAFE_ASSERT(pdesc->Name != nullptr);
  1142. pData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
  1143. pData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
  1144. pData->midiprog.data[i].name = carla_strdup(pdesc->Name);
  1145. }
  1146. }
  1147. if (doInit)
  1148. {
  1149. if (newCount > 0)
  1150. setMidiProgram(0, false, false, false, true);
  1151. }
  1152. else
  1153. {
  1154. // Check if current program is invalid
  1155. bool programChanged = false;
  1156. if (newCount == oldCount+1)
  1157. {
  1158. // one midi program added, probably created by user
  1159. pData->midiprog.current = static_cast<int32_t>(oldCount);
  1160. programChanged = true;
  1161. }
  1162. else if (current < 0 && newCount > 0)
  1163. {
  1164. // programs exist now, but not before
  1165. pData->midiprog.current = 0;
  1166. programChanged = true;
  1167. }
  1168. else if (current >= 0 && newCount == 0)
  1169. {
  1170. // programs existed before, but not anymore
  1171. pData->midiprog.current = -1;
  1172. programChanged = true;
  1173. }
  1174. else if (current >= static_cast<int32_t>(newCount))
  1175. {
  1176. // current midi program > count
  1177. pData->midiprog.current = 0;
  1178. programChanged = true;
  1179. }
  1180. else
  1181. {
  1182. // no change
  1183. pData->midiprog.current = current;
  1184. }
  1185. if (programChanged)
  1186. setMidiProgram(pData->midiprog.current, true, true, true, false);
  1187. pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr);
  1188. }
  1189. }
  1190. // -------------------------------------------------------------------
  1191. // Plugin processing
  1192. void activate() noexcept override
  1193. {
  1194. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1195. if (fDescriptor->activate != nullptr)
  1196. {
  1197. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  1198. {
  1199. LADSPA_Handle const handle(it.getValue(nullptr));
  1200. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  1201. try {
  1202. fDescriptor->activate(handle);
  1203. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI activate");
  1204. }
  1205. }
  1206. }
  1207. void deactivate() noexcept override
  1208. {
  1209. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1210. if (fDescriptor->deactivate != nullptr)
  1211. {
  1212. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  1213. {
  1214. LADSPA_Handle const handle(it.getValue(nullptr));
  1215. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  1216. try {
  1217. fDescriptor->deactivate(handle);
  1218. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI deactivate");
  1219. }
  1220. }
  1221. }
  1222. void process(const float* const* const audioIn, float** const audioOut,
  1223. const float* const* const cvIn, float**,
  1224. const uint32_t frames) override
  1225. {
  1226. // --------------------------------------------------------------------------------------------------------
  1227. // Check if active
  1228. if (! pData->active)
  1229. {
  1230. // disable any output sound
  1231. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1232. carla_zeroFloats(audioOut[i], frames);
  1233. return;
  1234. }
  1235. ulong midiEventCount = 0;
  1236. carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents);
  1237. // --------------------------------------------------------------------------------------------------------
  1238. // Check if needs reset
  1239. if (pData->needsReset)
  1240. {
  1241. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1242. {
  1243. midiEventCount = MAX_MIDI_CHANNELS*2;
  1244. for (uchar i=0, k=MAX_MIDI_CHANNELS; i < MAX_MIDI_CHANNELS; ++i)
  1245. {
  1246. fMidiEvents[i].type = SND_SEQ_EVENT_CONTROLLER;
  1247. fMidiEvents[i].data.control.channel = i;
  1248. fMidiEvents[i].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
  1249. fMidiEvents[k+i].type = SND_SEQ_EVENT_CONTROLLER;
  1250. fMidiEvents[k+i].data.control.channel = i;
  1251. fMidiEvents[k+i].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
  1252. }
  1253. }
  1254. else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
  1255. {
  1256. midiEventCount = MAX_MIDI_NOTE;
  1257. for (uchar i=0; i < MAX_MIDI_NOTE; ++i)
  1258. {
  1259. fMidiEvents[i].type = SND_SEQ_EVENT_NOTEOFF;
  1260. fMidiEvents[i].data.note.channel = static_cast<uchar>(pData->ctrlChannel);
  1261. fMidiEvents[i].data.note.note = i;
  1262. }
  1263. }
  1264. pData->needsReset = false;
  1265. }
  1266. // --------------------------------------------------------------------------------------------------------
  1267. // Event Input and Processing
  1268. if (pData->event.portIn != nullptr)
  1269. {
  1270. // ----------------------------------------------------------------------------------------------------
  1271. // MIDI Input (External)
  1272. if (pData->extNotes.mutex.tryLock())
  1273. {
  1274. ExternalMidiNote note = { 0, 0, 0 };
  1275. for (; midiEventCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();)
  1276. {
  1277. note = pData->extNotes.data.getFirst(note, true);
  1278. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  1279. snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
  1280. carla_zeroStruct(seqEvent);
  1281. seqEvent.type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
  1282. seqEvent.data.note.channel = static_cast<uchar>(note.channel);
  1283. seqEvent.data.note.note = note.note;
  1284. seqEvent.data.note.velocity = note.velo;
  1285. }
  1286. pData->extNotes.mutex.unlock();
  1287. } // End of MIDI Input (External)
  1288. // ----------------------------------------------------------------------------------------------------
  1289. // Event Input (System)
  1290. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1291. bool allNotesOffSent = false;
  1292. #endif
  1293. const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
  1294. uint32_t startTime = 0;
  1295. uint32_t timeOffset = 0;
  1296. uint32_t nextBankId;
  1297. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  1298. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  1299. else
  1300. nextBankId = 0;
  1301. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1302. if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
  1303. pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, isSampleAccurate, pData->event.portIn);
  1304. #endif
  1305. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  1306. {
  1307. EngineEvent& event(pData->event.portIn->getEvent(i));
  1308. uint32_t eventTime = event.time;
  1309. CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
  1310. if (eventTime < timeOffset)
  1311. {
  1312. carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
  1313. eventTime, timeOffset, pData->name);
  1314. eventTime = timeOffset;
  1315. }
  1316. if (isSampleAccurate && eventTime > timeOffset)
  1317. {
  1318. if (processSingle(audioIn, audioOut, eventTime - timeOffset, timeOffset, midiEventCount))
  1319. {
  1320. startTime = 0;
  1321. timeOffset = eventTime;
  1322. midiEventCount = 0;
  1323. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  1324. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  1325. else
  1326. nextBankId = 0;
  1327. }
  1328. else
  1329. startTime += timeOffset;
  1330. }
  1331. switch (event.type)
  1332. {
  1333. case kEngineEventTypeNull:
  1334. break;
  1335. case kEngineEventTypeControl: {
  1336. EngineControlEvent& ctrlEvent(event.ctrl);
  1337. switch (ctrlEvent.type)
  1338. {
  1339. case kEngineControlEventTypeNull:
  1340. break;
  1341. case kEngineControlEventTypeParameter: {
  1342. float value;
  1343. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1344. // non-midi
  1345. if (event.channel == kEngineEventNonMidiChannel)
  1346. {
  1347. const uint32_t k = ctrlEvent.param;
  1348. CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
  1349. ctrlEvent.handled = true;
  1350. value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
  1351. setParameterValueRT(k, value, event.time, true);
  1352. continue;
  1353. }
  1354. // Control backend stuff
  1355. if (event.channel == pData->ctrlChannel)
  1356. {
  1357. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  1358. {
  1359. ctrlEvent.handled = true;
  1360. value = ctrlEvent.normalizedValue;
  1361. setDryWetRT(value, true);
  1362. }
  1363. else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  1364. {
  1365. ctrlEvent.handled = true;
  1366. value = ctrlEvent.normalizedValue*127.0f/100.0f;
  1367. setVolumeRT(value, true);
  1368. }
  1369. else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  1370. {
  1371. float left, right;
  1372. value = ctrlEvent.normalizedValue/0.5f - 1.0f;
  1373. if (value < 0.0f)
  1374. {
  1375. left = -1.0f;
  1376. right = (value*2.0f)+1.0f;
  1377. }
  1378. else if (value > 0.0f)
  1379. {
  1380. left = (value*2.0f)-1.0f;
  1381. right = 1.0f;
  1382. }
  1383. else
  1384. {
  1385. left = -1.0f;
  1386. right = 1.0f;
  1387. }
  1388. ctrlEvent.handled = true;
  1389. setBalanceLeftRT(left, true);
  1390. setBalanceRightRT(right, true);
  1391. }
  1392. }
  1393. #endif
  1394. // Control plugin parameters
  1395. for (uint32_t k=0; k < pData->param.count; ++k)
  1396. {
  1397. if (pData->param.data[k].midiChannel != event.channel)
  1398. continue;
  1399. if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
  1400. continue;
  1401. if (pData->param.data[k].type != PARAMETER_INPUT)
  1402. continue;
  1403. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMATABLE) == 0)
  1404. continue;
  1405. ctrlEvent.handled = true;
  1406. value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
  1407. setParameterValueRT(k, value, event.time, true);
  1408. }
  1409. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
  1410. {
  1411. if (midiEventCount >= kPluginMaxMidiEvents)
  1412. continue;
  1413. snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
  1414. carla_zeroStruct(seqEvent);
  1415. seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
  1416. seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1417. seqEvent.data.control.channel = event.channel;
  1418. seqEvent.data.control.param = ctrlEvent.param;
  1419. seqEvent.data.control.value = int8_t(ctrlEvent.normalizedValue*127.0f + 0.5f);
  1420. }
  1421. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1422. if (! ctrlEvent.handled)
  1423. checkForMidiLearn(event);
  1424. #endif
  1425. break;
  1426. } // case kEngineControlEventTypeParameter
  1427. case kEngineControlEventTypeMidiBank:
  1428. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1429. nextBankId = ctrlEvent.param;
  1430. break;
  1431. case kEngineControlEventTypeMidiProgram:
  1432. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1433. {
  1434. const uint32_t nextProgramId = ctrlEvent.param;
  1435. for (uint32_t k=0; k < pData->midiprog.count; ++k)
  1436. {
  1437. if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
  1438. {
  1439. setMidiProgramRT(k, true);
  1440. break;
  1441. }
  1442. }
  1443. }
  1444. break;
  1445. case kEngineControlEventTypeAllSoundOff:
  1446. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1447. {
  1448. if (midiEventCount >= kPluginMaxMidiEvents)
  1449. continue;
  1450. snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
  1451. carla_zeroStruct(seqEvent);
  1452. seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
  1453. seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1454. seqEvent.data.control.channel = event.channel;
  1455. seqEvent.data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
  1456. }
  1457. break;
  1458. case kEngineControlEventTypeAllNotesOff:
  1459. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1460. {
  1461. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1462. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  1463. {
  1464. allNotesOffSent = true;
  1465. postponeRtAllNotesOff();
  1466. }
  1467. #endif
  1468. if (midiEventCount >= kPluginMaxMidiEvents)
  1469. continue;
  1470. snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
  1471. carla_zeroStruct(seqEvent);
  1472. seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
  1473. seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1474. seqEvent.data.control.channel = event.channel;
  1475. seqEvent.data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
  1476. }
  1477. break;
  1478. } // switch (ctrlEvent.type)
  1479. break;
  1480. } // case kEngineEventTypeControl
  1481. case kEngineEventTypeMidi: {
  1482. if (midiEventCount >= kPluginMaxMidiEvents)
  1483. continue;
  1484. const EngineMidiEvent& midiEvent(event.midi);
  1485. if (midiEvent.size > EngineMidiEvent::kDataSize)
  1486. continue;
  1487. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data));
  1488. // Fix bad note-off (per DSSI spec)
  1489. if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
  1490. status = MIDI_STATUS_NOTE_OFF;
  1491. snd_seq_event_t& seqEvent(fMidiEvents[midiEventCount++]);
  1492. carla_zeroStruct(seqEvent);
  1493. seqEvent.time.tick = isSampleAccurate ? startTime : eventTime;
  1494. switch (status)
  1495. {
  1496. case MIDI_STATUS_NOTE_OFF:
  1497. if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
  1498. {
  1499. const uint8_t note = midiEvent.data[1];
  1500. seqEvent.type = SND_SEQ_EVENT_NOTEOFF;
  1501. seqEvent.data.note.channel = event.channel;
  1502. seqEvent.data.note.note = note;
  1503. pData->postponeNoteOffRtEvent(true, event.channel, note);
  1504. }
  1505. break;
  1506. case MIDI_STATUS_NOTE_ON:
  1507. if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
  1508. {
  1509. const uint8_t note = midiEvent.data[1];
  1510. const uint8_t velo = midiEvent.data[2];
  1511. seqEvent.type = SND_SEQ_EVENT_NOTEON;
  1512. seqEvent.data.note.channel = event.channel;
  1513. seqEvent.data.note.note = note;
  1514. seqEvent.data.note.velocity = velo;
  1515. pData->postponeNoteOnRtEvent(true, event.channel, note, velo);
  1516. }
  1517. break;
  1518. case MIDI_STATUS_POLYPHONIC_AFTERTOUCH:
  1519. if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)
  1520. {
  1521. const uint8_t note = midiEvent.data[1];
  1522. const uint8_t pressure = midiEvent.data[2];
  1523. seqEvent.type = SND_SEQ_EVENT_KEYPRESS;
  1524. seqEvent.data.note.channel = event.channel;
  1525. seqEvent.data.note.note = note;
  1526. seqEvent.data.note.velocity = pressure;
  1527. }
  1528. break;
  1529. case MIDI_STATUS_CONTROL_CHANGE:
  1530. if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES)
  1531. {
  1532. const uint8_t control = midiEvent.data[1];
  1533. const uint8_t value = midiEvent.data[2];
  1534. seqEvent.type = SND_SEQ_EVENT_CONTROLLER;
  1535. seqEvent.data.control.channel = event.channel;
  1536. seqEvent.data.control.param = control;
  1537. seqEvent.data.control.value = value;
  1538. }
  1539. break;
  1540. case MIDI_STATUS_CHANNEL_PRESSURE:
  1541. if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)
  1542. {
  1543. const uint8_t pressure = midiEvent.data[1];
  1544. seqEvent.type = SND_SEQ_EVENT_CHANPRESS;
  1545. seqEvent.data.control.channel = event.channel;
  1546. seqEvent.data.control.value = pressure;
  1547. }
  1548. break;
  1549. case MIDI_STATUS_PITCH_WHEEL_CONTROL:
  1550. if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND)
  1551. {
  1552. const uint8_t lsb = midiEvent.data[1];
  1553. const uint8_t msb = midiEvent.data[2];
  1554. seqEvent.type = SND_SEQ_EVENT_PITCHBEND;
  1555. seqEvent.data.control.channel = event.channel;
  1556. seqEvent.data.control.value = ((msb << 7) | lsb) - 8192;
  1557. }
  1558. break;
  1559. default:
  1560. --midiEventCount;
  1561. break;
  1562. } // switch (status)
  1563. } break;
  1564. } // switch (event.type)
  1565. }
  1566. pData->postRtEvents.trySplice();
  1567. if (frames > timeOffset)
  1568. processSingle(audioIn, audioOut, frames - timeOffset, timeOffset, midiEventCount);
  1569. } // End of Event Input and Processing
  1570. // --------------------------------------------------------------------------------------------------------
  1571. // Plugin processing (no events)
  1572. else
  1573. {
  1574. processSingle(audioIn, audioOut, frames, 0, midiEventCount);
  1575. } // End of Plugin processing (no events)
  1576. // --------------------------------------------------------------------------------------------------------
  1577. // Control Output
  1578. if (pData->event.portOut != nullptr)
  1579. {
  1580. uint8_t channel;
  1581. uint16_t param;
  1582. float value;
  1583. for (uint32_t k=0; k < pData->param.count; ++k)
  1584. {
  1585. if (pData->param.data[k].type != PARAMETER_OUTPUT)
  1586. continue;
  1587. pData->param.ranges[k].fixValue(fParamBuffers[k]);
  1588. if (pData->param.data[k].mappedControlIndex > 0)
  1589. {
  1590. channel = pData->param.data[k].midiChannel;
  1591. param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
  1592. value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
  1593. pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter,
  1594. param, -1, value);
  1595. }
  1596. }
  1597. } // End of Control Output
  1598. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1599. return;
  1600. // unused
  1601. (void)cvIn;
  1602. #endif
  1603. }
  1604. bool processSingle(const float* const* const audioIn, float** const audioOut, const uint32_t frames,
  1605. const uint32_t timeOffset, const ulong midiEventCount)
  1606. {
  1607. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  1608. if (pData->audioIn.count > 0)
  1609. {
  1610. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  1611. }
  1612. if (pData->audioOut.count > 0)
  1613. {
  1614. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  1615. }
  1616. // --------------------------------------------------------------------------------------------------------
  1617. // Try lock, silence otherwise
  1618. #ifndef STOAT_TEST_BUILD
  1619. if (pData->engine->isOffline())
  1620. {
  1621. pData->singleMutex.lock();
  1622. }
  1623. else
  1624. #endif
  1625. if (! pData->singleMutex.tryLock())
  1626. {
  1627. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1628. {
  1629. for (uint32_t k=0; k < frames; ++k)
  1630. audioOut[i][k+timeOffset] = 0.0f;
  1631. }
  1632. return false;
  1633. }
  1634. // --------------------------------------------------------------------------------------------------------
  1635. // Set audio buffers
  1636. const bool customMonoOut = pData->audioOut.count == 2 && fForcedStereoOut && ! fForcedStereoIn;
  1637. const bool customStereoOut = pData->audioOut.count == 2 && fForcedStereoIn && ! fForcedStereoOut;
  1638. if (! customMonoOut)
  1639. {
  1640. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1641. carla_zeroFloats(fAudioOutBuffers[i], frames);
  1642. }
  1643. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1644. carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames);
  1645. // --------------------------------------------------------------------------------------------------------
  1646. // Run plugin
  1647. uint instn = 0;
  1648. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next(), ++instn)
  1649. {
  1650. LADSPA_Handle const handle(it.getValue(nullptr));
  1651. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  1652. // ----------------------------------------------------------------------------------------------------
  1653. // Mixdown for forced stereo
  1654. if (customMonoOut)
  1655. carla_zeroFloats(fAudioOutBuffers[instn], frames);
  1656. // ----------------------------------------------------------------------------------------------------
  1657. // Run it
  1658. if (fDssiDescriptor != nullptr && fDssiDescriptor->run_synth != nullptr)
  1659. {
  1660. try {
  1661. fDssiDescriptor->run_synth(handle, frames, fMidiEvents, midiEventCount);
  1662. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run_synth");
  1663. }
  1664. else
  1665. {
  1666. try {
  1667. fDescriptor->run(handle, frames);
  1668. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI run");
  1669. }
  1670. // ----------------------------------------------------------------------------------------------------
  1671. // Mixdown for forced stereo
  1672. if (customMonoOut)
  1673. carla_multiply(fAudioOutBuffers[instn], 0.5f, frames);
  1674. else if (customStereoOut)
  1675. carla_copyFloats(fExtraStereoBuffer[instn], fAudioOutBuffers[instn], frames);
  1676. }
  1677. if (customStereoOut)
  1678. {
  1679. carla_copyFloats(fAudioOutBuffers[0], fExtraStereoBuffer[0], frames);
  1680. carla_copyFloats(fAudioOutBuffers[1], fExtraStereoBuffer[1], frames);
  1681. }
  1682. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1683. // --------------------------------------------------------------------------------------------------------
  1684. // Post-processing (dry/wet, volume and balance)
  1685. {
  1686. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
  1687. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
  1688. const bool isMono = (pData->audioIn.count == 1);
  1689. bool isPair;
  1690. float bufValue;
  1691. float* const oldBufLeft = pData->postProc.extraBuffer;
  1692. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1693. {
  1694. // Dry/Wet
  1695. if (doDryWet)
  1696. {
  1697. const uint32_t c = isMono ? 0 : i;
  1698. for (uint32_t k=0; k < frames; ++k)
  1699. {
  1700. # ifndef BUILD_BRIDGE
  1701. if (k < pData->latency.frames && pData->latency.buffers != nullptr)
  1702. bufValue = pData->latency.buffers[c][k];
  1703. else if (pData->latency.frames < frames)
  1704. bufValue = fAudioInBuffers[c][k-pData->latency.frames];
  1705. else
  1706. # endif
  1707. bufValue = fAudioInBuffers[c][k];
  1708. fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1709. }
  1710. }
  1711. // Balance
  1712. if (doBalance)
  1713. {
  1714. isPair = (i % 2 == 0);
  1715. if (isPair)
  1716. {
  1717. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1718. carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames);
  1719. }
  1720. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1721. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1722. for (uint32_t k=0; k < frames; ++k)
  1723. {
  1724. if (isPair)
  1725. {
  1726. // left
  1727. fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1728. fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
  1729. }
  1730. else
  1731. {
  1732. // right
  1733. fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
  1734. fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  1735. }
  1736. }
  1737. }
  1738. // Volume (and buffer copy)
  1739. {
  1740. for (uint32_t k=0; k < frames; ++k)
  1741. audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
  1742. }
  1743. }
  1744. } // End of Post-processing
  1745. # ifndef BUILD_BRIDGE
  1746. // --------------------------------------------------------------------------------------------------------
  1747. // Save latency values for next callback
  1748. if (pData->latency.frames != 0 && pData->latency.buffers != nullptr)
  1749. {
  1750. CARLA_SAFE_ASSERT(timeOffset == 0);
  1751. const uint32_t latframes = pData->latency.frames;
  1752. if (latframes <= frames)
  1753. {
  1754. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1755. carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
  1756. }
  1757. else
  1758. {
  1759. const uint32_t diff = latframes - frames;
  1760. for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
  1761. {
  1762. // push back buffer by 'frames'
  1763. for (k=0; k < diff; ++k)
  1764. pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
  1765. // put current input at the end
  1766. for (uint32_t j=0; k < latframes; ++j, ++k)
  1767. pData->latency.buffers[i][k] = audioIn[i][j];
  1768. }
  1769. }
  1770. }
  1771. # endif
  1772. #else // BUILD_BRIDGE_ALTERNATIVE_ARCH
  1773. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1774. {
  1775. for (uint32_t k=0; k < frames; ++k)
  1776. audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
  1777. }
  1778. #endif
  1779. // --------------------------------------------------------------------------------------------------------
  1780. pData->singleMutex.unlock();
  1781. return true;
  1782. }
  1783. void bufferSizeChanged(const uint32_t newBufferSize) override
  1784. {
  1785. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  1786. carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - start", newBufferSize);
  1787. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1788. {
  1789. if (fAudioInBuffers[i] != nullptr)
  1790. delete[] fAudioInBuffers[i];
  1791. fAudioInBuffers[i] = new float[newBufferSize];
  1792. carla_zeroFloats(fAudioInBuffers[i], newBufferSize);
  1793. }
  1794. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1795. {
  1796. if (fAudioOutBuffers[i] != nullptr)
  1797. delete[] fAudioOutBuffers[i];
  1798. fAudioOutBuffers[i] = new float[newBufferSize];
  1799. carla_zeroFloats(fAudioOutBuffers[i], newBufferSize);
  1800. }
  1801. if (fExtraStereoBuffer[0] != nullptr)
  1802. {
  1803. delete[] fExtraStereoBuffer[0];
  1804. fExtraStereoBuffer[0] = nullptr;
  1805. }
  1806. if (fExtraStereoBuffer[1] != nullptr)
  1807. {
  1808. delete[] fExtraStereoBuffer[1];
  1809. fExtraStereoBuffer[1] = nullptr;
  1810. }
  1811. if (fForcedStereoIn && pData->audioOut.count == 2)
  1812. {
  1813. fExtraStereoBuffer[0] = new float[newBufferSize];
  1814. fExtraStereoBuffer[1] = new float[newBufferSize];
  1815. carla_zeroFloats(fExtraStereoBuffer[0], newBufferSize);
  1816. carla_zeroFloats(fExtraStereoBuffer[1], newBufferSize);
  1817. }
  1818. reconnectAudioPorts();
  1819. carla_debug("CarlaPluginLADSPADSSI::bufferSizeChanged(%i) - end", newBufferSize);
  1820. CarlaPlugin::bufferSizeChanged(newBufferSize);
  1821. }
  1822. void sampleRateChanged(const double newSampleRate) override
  1823. {
  1824. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  1825. carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - start", newSampleRate);
  1826. // TODO - handle UI stuff
  1827. if (pData->active)
  1828. deactivate();
  1829. const std::size_t instanceCount(fHandles.count());
  1830. if (fDescriptor->cleanup != nullptr)
  1831. {
  1832. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  1833. {
  1834. LADSPA_Handle const handle(it.getValue(nullptr));
  1835. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  1836. try {
  1837. fDescriptor->cleanup(handle);
  1838. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
  1839. }
  1840. }
  1841. fHandles.clear();
  1842. for (std::size_t i=0; i<instanceCount; ++i)
  1843. addInstance();
  1844. reconnectAudioPorts();
  1845. if (pData->active)
  1846. activate();
  1847. carla_debug("CarlaPluginLADSPADSSI::sampleRateChanged(%g) - end", newSampleRate);
  1848. }
  1849. void reconnectAudioPorts() const noexcept
  1850. {
  1851. if (fForcedStereoIn)
  1852. {
  1853. if (LADSPA_Handle const handle = fHandles.getFirst(nullptr))
  1854. {
  1855. try {
  1856. fDescriptor->connect_port(handle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
  1857. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, first)");
  1858. }
  1859. if (LADSPA_Handle const handle = fHandles.getLast(nullptr))
  1860. {
  1861. try {
  1862. fDescriptor->connect_port(handle, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
  1863. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo input, last)");
  1864. }
  1865. }
  1866. else
  1867. {
  1868. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  1869. {
  1870. LADSPA_Handle const handle(it.getValue(nullptr));
  1871. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  1872. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1873. {
  1874. try {
  1875. fDescriptor->connect_port(handle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
  1876. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio input)");
  1877. }
  1878. }
  1879. }
  1880. if (fForcedStereoOut)
  1881. {
  1882. if (LADSPA_Handle const handle = fHandles.getFirst(nullptr))
  1883. {
  1884. try {
  1885. fDescriptor->connect_port(handle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
  1886. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, first)");
  1887. }
  1888. if (LADSPA_Handle const handle = fHandles.getLast(nullptr))
  1889. {
  1890. try {
  1891. fDescriptor->connect_port(handle, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
  1892. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (forced stereo output, last)");
  1893. }
  1894. }
  1895. else
  1896. {
  1897. for (LinkedList<LADSPA_Handle>::Itenerator it = fHandles.begin2(); it.valid(); it.next())
  1898. {
  1899. LADSPA_Handle const handle(it.getValue(nullptr));
  1900. CARLA_SAFE_ASSERT_CONTINUE(handle != nullptr);
  1901. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1902. {
  1903. try {
  1904. fDescriptor->connect_port(handle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
  1905. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port (audio output)");
  1906. }
  1907. }
  1908. }
  1909. }
  1910. // -------------------------------------------------------------------
  1911. // Plugin buffers
  1912. void clearBuffers() noexcept override
  1913. {
  1914. carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - start");
  1915. if (fAudioInBuffers != nullptr)
  1916. {
  1917. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1918. {
  1919. if (fAudioInBuffers[i] != nullptr)
  1920. {
  1921. delete[] fAudioInBuffers[i];
  1922. fAudioInBuffers[i] = nullptr;
  1923. }
  1924. }
  1925. delete[] fAudioInBuffers;
  1926. fAudioInBuffers = nullptr;
  1927. }
  1928. if (fAudioOutBuffers != nullptr)
  1929. {
  1930. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1931. {
  1932. if (fAudioOutBuffers[i] != nullptr)
  1933. {
  1934. delete[] fAudioOutBuffers[i];
  1935. fAudioOutBuffers[i] = nullptr;
  1936. }
  1937. }
  1938. delete[] fAudioOutBuffers;
  1939. fAudioOutBuffers = nullptr;
  1940. }
  1941. if (fExtraStereoBuffer[0] != nullptr)
  1942. {
  1943. delete[] fExtraStereoBuffer[0];
  1944. fExtraStereoBuffer[0] = nullptr;
  1945. }
  1946. if (fExtraStereoBuffer[1] != nullptr)
  1947. {
  1948. delete[] fExtraStereoBuffer[1];
  1949. fExtraStereoBuffer[1] = nullptr;
  1950. }
  1951. if (fParamBuffers != nullptr)
  1952. {
  1953. delete[] fParamBuffers;
  1954. fParamBuffers = nullptr;
  1955. }
  1956. CarlaPlugin::clearBuffers();
  1957. carla_debug("CarlaPluginLADSPADSSI::clearBuffers() - end");
  1958. }
  1959. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  1960. // -------------------------------------------------------------------
  1961. // OSC stuff
  1962. void handleOscMessage(const char* const method, const int argc, const void* const argvx, const char* const types, const lo_message msg) override
  1963. {
  1964. const lo_address source(lo_message_get_source(msg));
  1965. CARLA_SAFE_ASSERT_RETURN(source != nullptr,);
  1966. // protocol for DSSI UIs *must* be UDP
  1967. CARLA_SAFE_ASSERT_RETURN(lo_address_get_protocol(source) == LO_UDP,);
  1968. if (fOscData.source == nullptr)
  1969. {
  1970. // if no UI is registered yet only "configure" and "update" messages are valid
  1971. CARLA_SAFE_ASSERT_RETURN(std::strcmp(method, "configure") == 0 || std::strcmp(method, "update") == 0,)
  1972. }
  1973. else
  1974. {
  1975. // make sure message source is the DSSI UI
  1976. const char* const msghost = lo_address_get_hostname(source);
  1977. const char* const msgport = lo_address_get_port(source);
  1978. const char* const ourhost = lo_address_get_hostname(fOscData.source);
  1979. const char* const ourport = lo_address_get_port(fOscData.source);
  1980. CARLA_SAFE_ASSERT_RETURN(std::strcmp(msghost, ourhost) == 0,);
  1981. CARLA_SAFE_ASSERT_RETURN(std::strcmp(msgport, ourport) == 0,);
  1982. }
  1983. const lo_arg* const* const argv(static_cast<const lo_arg* const*>(argvx));
  1984. if (std::strcmp(method, "configure") == 0)
  1985. return handleOscMessageConfigure(argc, argv, types);
  1986. if (std::strcmp(method, "control") == 0)
  1987. return handleOscMessageControl(argc, argv, types);
  1988. if (std::strcmp(method, "program") == 0)
  1989. return handleOscMessageProgram(argc, argv, types);
  1990. if (std::strcmp(method, "midi") == 0)
  1991. return handleOscMessageMIDI(argc, argv, types);
  1992. if (std::strcmp(method, "update") == 0)
  1993. return handleOscMessageUpdate(argc, argv, types, lo_message_get_source(msg));
  1994. if (std::strcmp(method, "exiting") == 0)
  1995. return handleOscMessageExiting();
  1996. carla_stdout("CarlaPluginLADSPADSSI::handleOscMessage() - unknown method '%s'", method);
  1997. }
  1998. void handleOscMessageConfigure(const int argc, const lo_arg* const* const argv, const char* const types)
  1999. {
  2000. carla_debug("CarlaPluginLADSPADSSI::handleMsgConfigure()");
  2001. CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ss");
  2002. const char* const key = (const char*)&argv[0]->s;
  2003. const char* const value = (const char*)&argv[1]->s;
  2004. setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false);
  2005. }
  2006. void handleOscMessageControl(const int argc, const lo_arg* const* const argv, const char* const types)
  2007. {
  2008. carla_debug("CarlaPluginLADSPADSSI::handleMsgControl()");
  2009. CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "if");
  2010. const int32_t rindex = argv[0]->i;
  2011. const float value = argv[1]->f;
  2012. setParameterValueByRealIndex(rindex, value, false, true, true);
  2013. }
  2014. void handleOscMessageProgram(const int argc, const lo_arg* const* const argv, const char* const types)
  2015. {
  2016. carla_debug("CarlaPluginLADSPADSSI::handleMsgProgram()");
  2017. CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ii");
  2018. const int32_t bank = argv[0]->i;
  2019. const int32_t program = argv[1]->i;
  2020. CARLA_SAFE_ASSERT_RETURN(bank >= 0,);
  2021. CARLA_SAFE_ASSERT_RETURN(program >= 0,);
  2022. setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true);
  2023. }
  2024. void handleOscMessageMIDI(const int argc, const lo_arg* const* const argv, const char* const types)
  2025. {
  2026. carla_debug("CarlaPluginLADSPADSSI::handleMsgMidi()");
  2027. CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "m");
  2028. if (getMidiInCount() == 0)
  2029. {
  2030. carla_stderr("CarlaPluginLADSPADSSI::handleMsgMidi() - received midi when plugin has no midi inputs");
  2031. return;
  2032. }
  2033. const uint8_t* const data = argv[0]->m;
  2034. uint8_t status = data[1];
  2035. uint8_t channel = status & 0x0F;
  2036. // Fix bad note-off
  2037. if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0)
  2038. status = MIDI_STATUS_NOTE_OFF;
  2039. if (MIDI_IS_STATUS_NOTE_OFF(status))
  2040. {
  2041. const uint8_t note = data[2];
  2042. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  2043. sendMidiSingleNote(channel, note, 0, false, true, true);
  2044. }
  2045. else if (MIDI_IS_STATUS_NOTE_ON(status))
  2046. {
  2047. const uint8_t note = data[2];
  2048. const uint8_t velo = data[3];
  2049. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  2050. CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,);
  2051. sendMidiSingleNote(channel, note, velo, false, true, true);
  2052. }
  2053. }
  2054. void handleOscMessageUpdate(const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source)
  2055. {
  2056. carla_debug("CarlaPluginLADSPADSSI::handleMsgUpdate()");
  2057. CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "s");
  2058. const char* const url = (const char*)&argv[0]->s;
  2059. // FIXME - remove debug prints later
  2060. carla_stdout("CarlaPluginLADSPADSSI::updateOscData(%p, \"%s\")", source, url);
  2061. fOscData.clear();
  2062. const int proto = lo_address_get_protocol(source);
  2063. {
  2064. const char* host = lo_address_get_hostname(source);
  2065. const char* port = lo_address_get_port(source);
  2066. fOscData.source = lo_address_new_with_proto(proto, host, port);
  2067. carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port);
  2068. }
  2069. {
  2070. char* host = lo_url_get_hostname(url);
  2071. char* port = lo_url_get_port(url);
  2072. fOscData.path = carla_strdup_free(lo_url_get_path(url));
  2073. fOscData.target = lo_address_new_with_proto(proto, host, port);
  2074. carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, fOscData.path);
  2075. std::free(host);
  2076. std::free(port);
  2077. }
  2078. osc_send_sample_rate(fOscData, static_cast<float>(pData->engine->getSampleRate()));
  2079. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
  2080. {
  2081. const CustomData& customData(it.getValue(kCustomDataFallback));
  2082. CARLA_SAFE_ASSERT_CONTINUE(customData.isValid());
  2083. if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0)
  2084. osc_send_configure(fOscData, customData.key, customData.value);
  2085. }
  2086. if (pData->prog.current >= 0)
  2087. osc_send_program(fOscData, static_cast<uint32_t>(pData->prog.current));
  2088. if (pData->midiprog.current >= 0)
  2089. {
  2090. const MidiProgramData& curMidiProg(pData->midiprog.getCurrent());
  2091. osc_send_program(fOscData, curMidiProg.bank, curMidiProg.program);
  2092. }
  2093. for (uint32_t i=0; i < pData->param.count; ++i)
  2094. osc_send_control(fOscData, pData->param.data[i].rindex, getParameterValue(i));
  2095. #ifndef BUILD_BRIDGE
  2096. if (pData->engine->getOptions().frontendWinId != 0)
  2097. pData->transientTryCounter = 1;
  2098. #endif
  2099. carla_stdout("CarlaPluginLADSPADSSI::updateOscData() - done");
  2100. }
  2101. void handleOscMessageExiting()
  2102. {
  2103. carla_debug("CarlaPluginLADSPADSSI::handleMsgExiting()");
  2104. // hide UI
  2105. showCustomUI(false);
  2106. // tell frontend
  2107. pData->engine->callback(true, true,
  2108. ENGINE_CALLBACK_UI_STATE_CHANGED,
  2109. pData->id,
  2110. 0,
  2111. 0, 0, 0.0f, nullptr);
  2112. }
  2113. // -------------------------------------------------------------------
  2114. // Post-poned UI Stuff
  2115. void uiParameterChange(const uint32_t index, const float value) noexcept override
  2116. {
  2117. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  2118. if (fOscData.target == nullptr)
  2119. return;
  2120. osc_send_control(fOscData, pData->param.data[index].rindex, value);
  2121. }
  2122. void uiMidiProgramChange(const uint32_t index) noexcept override
  2123. {
  2124. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  2125. if (fOscData.target == nullptr)
  2126. return;
  2127. osc_send_program(fOscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
  2128. }
  2129. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  2130. {
  2131. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  2132. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  2133. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  2134. if (fOscData.target == nullptr)
  2135. return;
  2136. #if 0
  2137. uint8_t midiData[4];
  2138. midiData[0] = 0;
  2139. midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
  2140. midiData[2] = note;
  2141. midiData[3] = velo;
  2142. osc_send_midi(fOscData, midiData);
  2143. #endif
  2144. }
  2145. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  2146. {
  2147. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  2148. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  2149. if (fOscData.target == nullptr)
  2150. return;
  2151. #if 0
  2152. uint8_t midiData[4];
  2153. midiData[0] = 0;
  2154. midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
  2155. midiData[2] = note;
  2156. midiData[3] = 0;
  2157. osc_send_midi(fOscData, midiData);
  2158. #endif
  2159. }
  2160. #endif // CARLA_ENABLE_DSSI_PLUGIN_GUI
  2161. // -------------------------------------------------------------------
  2162. const void* getNativeDescriptor() const noexcept override
  2163. {
  2164. return fDssiDescriptor != nullptr
  2165. ? (const void*)fDssiDescriptor
  2166. : (const void*)fDescriptor;
  2167. }
  2168. const void* getExtraStuff() const noexcept override
  2169. {
  2170. if (fDssiDescriptor != nullptr)
  2171. {
  2172. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  2173. return fUiFilename;
  2174. #else
  2175. return nullptr;
  2176. #endif
  2177. }
  2178. return fRdfDescriptor;
  2179. }
  2180. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  2181. uintptr_t getUiBridgeProcessId() const noexcept override
  2182. {
  2183. return fThreadUI.getProcessId();
  2184. }
  2185. #endif
  2186. // -------------------------------------------------------------------
  2187. bool initLADSPA(const CarlaPluginPtr plugin,
  2188. const char* const filename, const char* name, const char* const label, const uint options,
  2189. const LADSPA_RDF_Descriptor* const rdfDescriptor)
  2190. {
  2191. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  2192. // ---------------------------------------------------------------
  2193. // first checks
  2194. if (pData->client != nullptr)
  2195. {
  2196. pData->engine->setLastError("Plugin client is already registered");
  2197. return false;
  2198. }
  2199. if (filename == nullptr || filename[0] == '\0')
  2200. {
  2201. pData->engine->setLastError("null filename");
  2202. return false;
  2203. }
  2204. // ---------------------------------------------------------------
  2205. // open DLL
  2206. if (! pData->libOpen(filename))
  2207. {
  2208. pData->engine->setLastError(pData->libError(filename));
  2209. return false;
  2210. }
  2211. // ---------------------------------------------------------------
  2212. // get DLL main entry
  2213. const LADSPA_Descriptor_Function descFn = pData->libSymbol<LADSPA_Descriptor_Function>("ladspa_descriptor");
  2214. if (descFn == nullptr)
  2215. {
  2216. pData->engine->setLastError("Could not find the LASDPA Descriptor in the plugin library");
  2217. return false;
  2218. }
  2219. // ---------------------------------------------------------------
  2220. // get descriptor that matches label
  2221. // if label is null, get first valid plugin
  2222. const bool nullLabel = (label == nullptr || label[0] == '\0');
  2223. for (ulong d=0;; ++d)
  2224. {
  2225. try {
  2226. fDescriptor = descFn(d);
  2227. }
  2228. catch(...) {
  2229. carla_stderr2("Caught exception when trying to get LADSPA descriptor");
  2230. fDescriptor = nullptr;
  2231. break;
  2232. }
  2233. if (fDescriptor == nullptr)
  2234. break;
  2235. if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
  2236. {
  2237. carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
  2238. fDescriptor = nullptr;
  2239. break;
  2240. }
  2241. if (fDescriptor->run == nullptr)
  2242. {
  2243. carla_stderr2("WARNING - Plugin has no run, cannot use it");
  2244. fDescriptor = nullptr;
  2245. break;
  2246. }
  2247. if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0)
  2248. break;
  2249. }
  2250. if (fDescriptor == nullptr)
  2251. {
  2252. pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
  2253. return false;
  2254. }
  2255. return init2(plugin, filename, name, options, rdfDescriptor);
  2256. }
  2257. bool initDSSI(const CarlaPluginPtr plugin,
  2258. const char* const filename, const char* name, const char* const label, const uint options)
  2259. {
  2260. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  2261. // ---------------------------------------------------------------
  2262. // first checks
  2263. if (pData->client != nullptr)
  2264. {
  2265. pData->engine->setLastError("Plugin client is already registered");
  2266. return false;
  2267. }
  2268. if (filename == nullptr || filename[0] == '\0')
  2269. {
  2270. pData->engine->setLastError("null filename");
  2271. return false;
  2272. }
  2273. // ---------------------------------------------------------------
  2274. // open DLL
  2275. if (! pData->libOpen(filename))
  2276. {
  2277. pData->engine->setLastError(pData->libError(filename));
  2278. return false;
  2279. }
  2280. // ---------------------------------------------------------------
  2281. // get DLL main entry
  2282. const DSSI_Descriptor_Function descFn = pData->libSymbol<DSSI_Descriptor_Function>("dssi_descriptor");
  2283. if (descFn == nullptr)
  2284. {
  2285. pData->engine->setLastError("Could not find the DSSI Descriptor in the plugin library");
  2286. return false;
  2287. }
  2288. // ---------------------------------------------------------------
  2289. // get descriptor that matches label
  2290. // if label is null, get first valid plugin
  2291. const bool nullLabel = (label == nullptr || label[0] == '\0');
  2292. for (ulong d=0;; ++d)
  2293. {
  2294. try {
  2295. fDssiDescriptor = descFn(d);
  2296. }
  2297. catch(...) {
  2298. carla_stderr2("Caught exception when trying to get DSSI descriptor");
  2299. fDescriptor = nullptr;
  2300. fDssiDescriptor = nullptr;
  2301. break;
  2302. }
  2303. if (fDssiDescriptor == nullptr)
  2304. break;
  2305. fDescriptor = fDssiDescriptor->LADSPA_Plugin;
  2306. if (fDescriptor == nullptr)
  2307. {
  2308. carla_stderr2("WARNING - Missing LADSPA interface, will not use this plugin");
  2309. fDssiDescriptor = nullptr;
  2310. break;
  2311. }
  2312. if (fDescriptor->Label == nullptr || fDescriptor->Label[0] == '\0')
  2313. {
  2314. carla_stderr2("WARNING - Got an invalid label, will not use this plugin");
  2315. fDescriptor = nullptr;
  2316. fDssiDescriptor = nullptr;
  2317. break;
  2318. }
  2319. if (fDescriptor->run == nullptr)
  2320. {
  2321. carla_stderr2("WARNING - Plugin has no run, cannot use it");
  2322. fDescriptor = nullptr;
  2323. fDssiDescriptor = nullptr;
  2324. break;
  2325. }
  2326. if (nullLabel || std::strcmp(fDescriptor->Label, label) == 0)
  2327. break;
  2328. }
  2329. if (fDescriptor == nullptr || fDssiDescriptor == nullptr)
  2330. {
  2331. pData->engine->setLastError("Could not find the requested plugin label in the plugin library");
  2332. return false;
  2333. }
  2334. // ---------------------------------------------------------------
  2335. // check if uses global instance
  2336. if (fDssiDescriptor->run_synth == nullptr && fDssiDescriptor->run_multiple_synths != nullptr)
  2337. {
  2338. pData->engine->setLastError("This plugin requires run_multiple_synths which is not supported");
  2339. return false;
  2340. }
  2341. return init2(plugin, filename, name, options, nullptr);
  2342. }
  2343. bool init2(const CarlaPluginPtr plugin,
  2344. const char* const filename, const char* name, const uint options,
  2345. const LADSPA_RDF_Descriptor* const rdfDescriptor)
  2346. {
  2347. // ---------------------------------------------------------------
  2348. // check for fixed buffer size requirement
  2349. fNeedsFixedBuffers = CarlaString(filename).contains("dssi-vst", true);
  2350. if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize())
  2351. {
  2352. pData->engine->setLastError("Cannot use this plugin under the current engine.\n"
  2353. "The plugin requires a fixed block size which is not possible right now.");
  2354. return false;
  2355. }
  2356. // ---------------------------------------------------------------
  2357. // get info
  2358. if (is_ladspa_rdf_descriptor_valid(rdfDescriptor, fDescriptor))
  2359. fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor);
  2360. if (name == nullptr || name[0] == '\0')
  2361. {
  2362. /**/ if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr && fRdfDescriptor->Title[0] != '\0')
  2363. name = fRdfDescriptor->Title;
  2364. else if (fDescriptor->Name != nullptr && fDescriptor->Name[0] != '\0')
  2365. name = fDescriptor->Name;
  2366. else
  2367. name = fDescriptor->Label;
  2368. }
  2369. pData->name = pData->engine->getUniquePluginName(name);
  2370. pData->filename = carla_strdup(filename);
  2371. // ---------------------------------------------------------------
  2372. // register client
  2373. pData->client = pData->engine->addClient(plugin);
  2374. if (pData->client == nullptr || ! pData->client->isOk())
  2375. {
  2376. pData->engine->setLastError("Failed to register plugin client");
  2377. return false;
  2378. }
  2379. // ---------------------------------------------------------------
  2380. // initialize plugin
  2381. if (! addInstance())
  2382. return false;
  2383. // ---------------------------------------------------------------
  2384. // find latency port index
  2385. for (uint32_t i=0, iCtrl=0, count=getSafePortCount(); i<count; ++i)
  2386. {
  2387. const int portType(fDescriptor->PortDescriptors[i]);
  2388. if (! LADSPA_IS_PORT_CONTROL(portType))
  2389. continue;
  2390. const uint32_t index(iCtrl++);
  2391. if (! LADSPA_IS_PORT_OUTPUT(portType))
  2392. continue;
  2393. const char* const portName(fDescriptor->PortNames[i]);
  2394. CARLA_SAFE_ASSERT_BREAK(portName != nullptr);
  2395. if (std::strcmp(portName, "latency") == 0 ||
  2396. std::strcmp(portName, "_latency") == 0)
  2397. {
  2398. fLatencyIndex = static_cast<int32_t>(index);
  2399. break;
  2400. }
  2401. }
  2402. // ---------------------------------------------------------------
  2403. // check for custom data extension
  2404. if (fDssiDescriptor != nullptr && fDssiDescriptor->configure != nullptr)
  2405. {
  2406. if (char* const error = fDssiDescriptor->configure(fHandles.getFirst(nullptr), DSSI_CUSTOMDATA_EXTENSION_KEY, ""))
  2407. {
  2408. if (std::strcmp(error, "true") == 0 && fDssiDescriptor->get_custom_data != nullptr
  2409. && fDssiDescriptor->set_custom_data != nullptr)
  2410. fUsesCustomData = true;
  2411. std::free(error);
  2412. }
  2413. }
  2414. // ---------------------------------------------------------------
  2415. // get engine options
  2416. const EngineOptions& opts(pData->engine->getOptions());
  2417. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  2418. // ---------------------------------------------------------------
  2419. // check for gui
  2420. if (opts.oscEnabled && opts.oscPortUDP >= 0)
  2421. {
  2422. if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label))
  2423. {
  2424. fUiFilename = guiFilename;
  2425. CarlaString uiTitle;
  2426. if (pData->uiTitle.isNotEmpty())
  2427. {
  2428. uiTitle = pData->uiTitle;
  2429. }
  2430. else
  2431. {
  2432. uiTitle = pData->name;
  2433. uiTitle += " (GUI)";
  2434. }
  2435. fThreadUI.setData(guiFilename, fDescriptor->Label, uiTitle);
  2436. }
  2437. }
  2438. #endif
  2439. // ---------------------------------------------------------------
  2440. // set options
  2441. pData->options = 0x0;
  2442. /**/ if (fLatencyIndex >= 0 || fNeedsFixedBuffers)
  2443. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  2444. else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
  2445. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  2446. /**/ if (opts.forceStereo)
  2447. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  2448. else if (options & PLUGIN_OPTION_FORCE_STEREO)
  2449. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  2450. if (fDssiDescriptor != nullptr)
  2451. {
  2452. if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
  2453. if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
  2454. pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  2455. if (fUsesCustomData)
  2456. if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS))
  2457. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  2458. if (fDssiDescriptor->run_synth != nullptr)
  2459. {
  2460. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
  2461. pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  2462. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
  2463. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  2464. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
  2465. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  2466. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
  2467. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  2468. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
  2469. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  2470. if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
  2471. pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
  2472. }
  2473. }
  2474. return true;
  2475. }
  2476. // -------------------------------------------------------------------
  2477. private:
  2478. LinkedList<LADSPA_Handle> fHandles;
  2479. const LADSPA_Descriptor* fDescriptor;
  2480. const DSSI_Descriptor* fDssiDescriptor;
  2481. const LADSPA_RDF_Descriptor* fRdfDescriptor;
  2482. float** fAudioInBuffers;
  2483. float** fAudioOutBuffers;
  2484. float* fExtraStereoBuffer[2]; // used only if forcedStereoIn and audioOut == 2
  2485. float* fParamBuffers;
  2486. snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents];
  2487. int32_t fLatencyIndex; // -1 if invalid
  2488. bool fForcedStereoIn;
  2489. bool fForcedStereoOut;
  2490. bool fNeedsFixedBuffers;
  2491. bool fUsesCustomData;
  2492. #ifdef CARLA_ENABLE_DSSI_PLUGIN_GUI
  2493. CarlaOscData fOscData;
  2494. CarlaThreadDSSIUI fThreadUI;
  2495. const char* fUiFilename;
  2496. #endif
  2497. // -------------------------------------------------------------------
  2498. bool addInstance()
  2499. {
  2500. LADSPA_Handle handle;
  2501. try {
  2502. handle = fDescriptor->instantiate(fDescriptor, static_cast<ulong>(pData->engine->getSampleRate()));
  2503. } CARLA_SAFE_EXCEPTION_RETURN_ERR("LADSPA/DSSI instantiate", "Plugin failed to initialize");
  2504. for (uint32_t i=0, count=pData->param.count; i<count; ++i)
  2505. {
  2506. const int32_t rindex(pData->param.data[i].rindex);
  2507. CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0);
  2508. try {
  2509. fDescriptor->connect_port(handle, static_cast<ulong>(rindex), &fParamBuffers[i]);
  2510. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI connect_port");
  2511. }
  2512. if (fHandles.append(handle))
  2513. return true;
  2514. try {
  2515. fDescriptor->cleanup(handle);
  2516. } CARLA_SAFE_EXCEPTION("LADSPA/DSSI cleanup");
  2517. pData->engine->setLastError("Out of memory");
  2518. return false;
  2519. }
  2520. uint32_t getSafePortCount() const noexcept
  2521. {
  2522. if (fDescriptor->PortCount == 0)
  2523. return 0;
  2524. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortDescriptors != nullptr, 0);
  2525. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortRangeHints != nullptr, 0);
  2526. CARLA_SAFE_ASSERT_RETURN(fDescriptor->PortNames != nullptr, 0);
  2527. return static_cast<uint32_t>(fDescriptor->PortCount);
  2528. }
  2529. bool getSeparatedParameterNameOrUnit(const char* const paramName, char* const strBuf, const bool wantName) const noexcept
  2530. {
  2531. if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, true))
  2532. return true;
  2533. if (_getSeparatedParameterNameOrUnitImpl(paramName, strBuf, wantName, false))
  2534. return true;
  2535. return false;
  2536. }
  2537. static bool _getSeparatedParameterNameOrUnitImpl(const char* const paramName, char* const strBuf,
  2538. const bool wantName, const bool useBracket) noexcept
  2539. {
  2540. const char* const sepBracketStart = std::strstr(paramName, useBracket ? " [" : " (");
  2541. if (sepBracketStart == nullptr)
  2542. return false;
  2543. const char* const sepBracketEnd = std::strstr(sepBracketStart, useBracket ? "]" : ")");
  2544. if (sepBracketEnd == nullptr)
  2545. return false;
  2546. const std::size_t unitSize = static_cast<std::size_t>(sepBracketEnd-sepBracketStart-2);
  2547. if (unitSize > 7) // very unlikely to have such big unit
  2548. return false;
  2549. const std::size_t sepIndex = std::strlen(paramName)-unitSize-3;
  2550. // just in case
  2551. if (sepIndex > STR_MAX-3)
  2552. return false;
  2553. if (wantName)
  2554. {
  2555. std::strncpy(strBuf, paramName, sepIndex);
  2556. strBuf[sepIndex] = '\0';
  2557. }
  2558. else
  2559. {
  2560. std::strncpy(strBuf, paramName+(sepIndex+2), unitSize);
  2561. strBuf[unitSize] = '\0';
  2562. }
  2563. return true;
  2564. }
  2565. // -------------------------------------------------------------------
  2566. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLADSPADSSI)
  2567. };
  2568. // -------------------------------------------------------------------------------------------------------------------
  2569. CarlaPluginPtr CarlaPlugin::newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor)
  2570. {
  2571. carla_debug("CarlaPlugin::newLADSPA({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x}, %p)",
  2572. init.engine, init.filename, init.name, init.label, init.uniqueId, init.options, rdfDescriptor);
  2573. std::shared_ptr<CarlaPluginLADSPADSSI> plugin(new CarlaPluginLADSPADSSI(init.engine, init.id));
  2574. if (! plugin->initLADSPA(plugin, init.filename, init.name, init.label, init.options, rdfDescriptor))
  2575. return nullptr;
  2576. return plugin;
  2577. }
  2578. CarlaPluginPtr CarlaPlugin::newDSSI(const Initializer& init)
  2579. {
  2580. carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\", " P_INT64 ", %x})",
  2581. init.engine, init.filename, init.name, init.label, init.uniqueId, init.options);
  2582. std::shared_ptr<CarlaPluginLADSPADSSI> plugin(new CarlaPluginLADSPADSSI(init.engine, init.id));
  2583. if (! plugin->initDSSI(plugin, init.filename, init.name, init.label, init.options))
  2584. return nullptr;
  2585. return plugin;
  2586. }
  2587. // -------------------------------------------------------------------------------------------------------------------
  2588. CARLA_BACKEND_END_NAMESPACE