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.

CarlaPluginBridge.cpp 115KB

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
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
11 years ago
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
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
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
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
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207
  1. /*
  2. * Carla Plugin Bridge
  3. * Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #include "CarlaBackendUtils.hpp"
  19. #include "CarlaBase64Utils.hpp"
  20. #include "CarlaBridgeUtils.hpp"
  21. #include "CarlaEngineUtils.hpp"
  22. #include "CarlaMathUtils.hpp"
  23. #include "CarlaPipeUtils.hpp"
  24. #include "CarlaScopeUtils.hpp"
  25. #include "CarlaShmUtils.hpp"
  26. #include "CarlaThread.hpp"
  27. #include "jackbridge/JackBridge.hpp"
  28. #include <ctime>
  29. #include "water/files/File.h"
  30. #include "water/misc/Time.h"
  31. #include "water/threads/ChildProcess.h"
  32. // ---------------------------------------------------------------------------------------------------------------------
  33. using water::ChildProcess;
  34. using water::File;
  35. using water::String;
  36. using water::StringArray;
  37. using water::Time;
  38. CARLA_BACKEND_START_NAMESPACE
  39. // ---------------------------------------------------------------------------------------------------------------------
  40. // Fallback data
  41. static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
  42. // ---------------------------------------------------------------------------------------------------------------------
  43. static String findWinePrefix(const String filename, const int recursionLimit = 10)
  44. {
  45. if (recursionLimit == 0 || filename.length() < 5 || ! filename.contains("/"))
  46. return "";
  47. const String path(filename.upToLastOccurrenceOf("/", false, false));
  48. if (File(path + "/dosdevices").isDirectory())
  49. return path;
  50. return findWinePrefix(path, recursionLimit-1);
  51. }
  52. // ---------------------------------------------------------------------------------------------------------------------
  53. struct BridgeParamInfo {
  54. float value;
  55. CarlaString name;
  56. CarlaString symbol;
  57. CarlaString unit;
  58. BridgeParamInfo() noexcept
  59. : value(0.0f),
  60. name(),
  61. symbol(),
  62. unit() {}
  63. CARLA_DECLARE_NON_COPY_STRUCT(BridgeParamInfo)
  64. };
  65. // ---------------------------------------------------------------------------------------------------------------------
  66. class CarlaPluginBridgeThread : public CarlaThread
  67. {
  68. public:
  69. CarlaPluginBridgeThread(CarlaEngine* const engine, CarlaPlugin* const plugin) noexcept
  70. : CarlaThread("CarlaPluginBridgeThread"),
  71. kEngine(engine),
  72. kPlugin(plugin),
  73. fBinaryArchName(),
  74. fBridgeBinary(),
  75. fLabel(),
  76. fShmIds(),
  77. #ifndef CARLA_OS_WIN
  78. fWinePrefix(),
  79. #endif
  80. fProcess() {}
  81. void setData(
  82. #ifndef CARLA_OS_WIN
  83. const char* const winePrefix,
  84. #endif
  85. const char* const binaryArchName,
  86. const char* const bridgeBinary,
  87. const char* const label,
  88. const char* const shmIds) noexcept
  89. {
  90. CARLA_SAFE_ASSERT_RETURN(bridgeBinary != nullptr && bridgeBinary[0] != '\0',);
  91. CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',);
  92. CARLA_SAFE_ASSERT(! isThreadRunning());
  93. #ifndef CARLA_OS_WIN
  94. fWinePrefix = winePrefix;
  95. #endif
  96. fBinaryArchName = binaryArchName;
  97. fBridgeBinary = bridgeBinary;
  98. fShmIds = shmIds;
  99. if (label != nullptr)
  100. fLabel = label;
  101. if (fLabel.isEmpty())
  102. fLabel = "(none)";
  103. }
  104. uintptr_t getProcessPID() const noexcept
  105. {
  106. CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0);
  107. return (uintptr_t)fProcess->getPID();
  108. }
  109. protected:
  110. void run()
  111. {
  112. if (fProcess == nullptr)
  113. {
  114. fProcess = new ChildProcess();
  115. }
  116. else if (fProcess->isRunning())
  117. {
  118. carla_stderr("CarlaPluginBridgeThread::run() - already running");
  119. }
  120. char strBuf[STR_MAX+1];
  121. strBuf[STR_MAX] = '\0';
  122. const EngineOptions& options(kEngine->getOptions());
  123. String filename(kPlugin->getFilename());
  124. if (filename.isEmpty())
  125. filename = "(none)";
  126. StringArray arguments;
  127. #ifndef CARLA_OS_WIN
  128. // start with "wine" if needed
  129. if (fBridgeBinary.endsWithIgnoreCase(".exe"))
  130. {
  131. String wineCMD;
  132. if (options.wine.executable != nullptr && options.wine.executable[0] != '\0')
  133. {
  134. wineCMD = options.wine.executable;
  135. if (fBridgeBinary.endsWithIgnoreCase("64.exe")
  136. && options.wine.executable[0] == CARLA_OS_SEP
  137. && File(wineCMD + "64").existsAsFile())
  138. wineCMD += "64";
  139. }
  140. else
  141. {
  142. wineCMD = "wine";
  143. }
  144. arguments.add(wineCMD);
  145. }
  146. #endif
  147. // setup binary arch
  148. ChildProcess::Type childType;
  149. #ifdef CARLA_OS_MAC
  150. if (fBinaryArchName == "arm64")
  151. childType = ChildProcess::TypeARM;
  152. else if (fBinaryArchName == "x86_64")
  153. childType = ChildProcess::TypeIntel;
  154. else
  155. #endif
  156. childType = ChildProcess::TypeAny;
  157. // bridge binary
  158. arguments.add(fBridgeBinary);
  159. // plugin type
  160. arguments.add(getPluginTypeAsString(kPlugin->getType()));
  161. // filename
  162. arguments.add(filename);
  163. // label
  164. arguments.add(fLabel);
  165. // uniqueId
  166. arguments.add(String(static_cast<water::int64>(kPlugin->getUniqueId())));
  167. bool started;
  168. {
  169. const ScopedEngineEnvironmentLocker _seel(kEngine);
  170. #ifdef CARLA_OS_LINUX
  171. const CarlaScopedEnvVar sev1("LD_LIBRARY_PATH", nullptr);
  172. const CarlaScopedEnvVar sev2("LD_PRELOAD", nullptr);
  173. #endif
  174. carla_setenv("ENGINE_OPTION_FORCE_STEREO", bool2str(options.forceStereo));
  175. carla_setenv("ENGINE_OPTION_PREFER_PLUGIN_BRIDGES", bool2str(options.preferPluginBridges));
  176. carla_setenv("ENGINE_OPTION_PREFER_UI_BRIDGES", bool2str(options.preferUiBridges));
  177. carla_setenv("ENGINE_OPTION_UIS_ALWAYS_ON_TOP", bool2str(options.uisAlwaysOnTop));
  178. std::snprintf(strBuf, STR_MAX, "%u", options.maxParameters);
  179. carla_setenv("ENGINE_OPTION_MAX_PARAMETERS", strBuf);
  180. std::snprintf(strBuf, STR_MAX, "%u", options.uiBridgesTimeout);
  181. carla_setenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT",strBuf);
  182. if (options.pathLADSPA != nullptr)
  183. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA", options.pathLADSPA);
  184. else
  185. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA", "");
  186. if (options.pathDSSI != nullptr)
  187. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_DSSI", options.pathDSSI);
  188. else
  189. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_DSSI", "");
  190. if (options.pathLV2 != nullptr)
  191. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LV2", options.pathLV2);
  192. else
  193. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LV2", "");
  194. if (options.pathVST2 != nullptr)
  195. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST2", options.pathVST2);
  196. else
  197. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST2", "");
  198. if (options.pathVST3 != nullptr)
  199. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST3", options.pathVST3);
  200. else
  201. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST3", "");
  202. if (options.pathSF2 != nullptr)
  203. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SF2", options.pathSF2);
  204. else
  205. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SF2", "");
  206. if (options.pathSFZ != nullptr)
  207. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SFZ", options.pathSFZ);
  208. else
  209. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SFZ", "");
  210. if (options.pathJSFX != nullptr)
  211. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_JSFX", options.pathJSFX);
  212. else
  213. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_JSFX", "");
  214. if (options.binaryDir != nullptr)
  215. carla_setenv("ENGINE_OPTION_PATH_BINARIES", options.binaryDir);
  216. else
  217. carla_setenv("ENGINE_OPTION_PATH_BINARIES", "");
  218. if (options.resourceDir != nullptr)
  219. carla_setenv("ENGINE_OPTION_PATH_RESOURCES", options.resourceDir);
  220. else
  221. carla_setenv("ENGINE_OPTION_PATH_RESOURCES", "");
  222. carla_setenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR", bool2str(options.preventBadBehaviour));
  223. std::snprintf(strBuf, STR_MAX, P_UINTPTR, options.frontendWinId);
  224. carla_setenv("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf);
  225. carla_setenv("ENGINE_BRIDGE_SHM_IDS", fShmIds.toRawUTF8());
  226. #ifndef CARLA_OS_WIN
  227. if (fWinePrefix.isNotEmpty())
  228. {
  229. carla_setenv("WINEDEBUG", "-all");
  230. carla_setenv("WINEPREFIX", fWinePrefix.toRawUTF8());
  231. if (options.wine.rtPrio)
  232. {
  233. carla_setenv("STAGING_SHARED_MEMORY", "1");
  234. carla_setenv("WINE_RT_POLICY", "FF");
  235. std::snprintf(strBuf, STR_MAX, "%i", options.wine.baseRtPrio);
  236. carla_setenv("STAGING_RT_PRIORITY_BASE", strBuf);
  237. carla_setenv("WINE_RT", strBuf);
  238. carla_setenv("WINE_RT_PRIO", strBuf);
  239. std::snprintf(strBuf, STR_MAX, "%i", options.wine.serverRtPrio);
  240. carla_setenv("STAGING_RT_PRIORITY_SERVER", strBuf);
  241. carla_setenv("WINE_SVR_RT", strBuf);
  242. carla_stdout("Using WINEPREFIX '%s', with base RT prio %i and server RT prio %i",
  243. fWinePrefix.toRawUTF8(), options.wine.baseRtPrio, options.wine.serverRtPrio);
  244. }
  245. else
  246. {
  247. carla_unsetenv("STAGING_SHARED_MEMORY");
  248. carla_unsetenv("WINE_RT_POLICY");
  249. carla_unsetenv("STAGING_RT_PRIORITY_BASE");
  250. carla_unsetenv("STAGING_RT_PRIORITY_SERVER");
  251. carla_unsetenv("WINE_RT");
  252. carla_unsetenv("WINE_RT_PRIO");
  253. carla_unsetenv("WINE_SVR_RT");
  254. carla_stdout("Using WINEPREFIX '%s', without RT priorities", fWinePrefix.toRawUTF8());
  255. }
  256. }
  257. #endif
  258. carla_stdout("Starting plugin bridge, command is:\n%s \"%s\" \"%s\" \"%s\" " P_INT64,
  259. fBridgeBinary.toRawUTF8(), getPluginTypeAsString(kPlugin->getType()), filename.toRawUTF8(), fLabel.toRawUTF8(), kPlugin->getUniqueId());
  260. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  261. const File projFolder(kEngine->getCurrentProjectFolder());
  262. if (projFolder.isNotNull())
  263. {
  264. const File oldFolder(File::getCurrentWorkingDirectory());
  265. projFolder.setAsCurrentWorkingDirectory();
  266. started = fProcess->start(arguments, childType);
  267. oldFolder.setAsCurrentWorkingDirectory();
  268. }
  269. else
  270. #endif
  271. {
  272. started = fProcess->start(arguments, childType);
  273. }
  274. }
  275. if (! started)
  276. {
  277. carla_stdout("failed!");
  278. fProcess = nullptr;
  279. return;
  280. }
  281. for (; fProcess->isRunning() && ! shouldThreadExit();)
  282. carla_sleep(1);
  283. // we only get here if bridge crashed or thread asked to exit
  284. if (fProcess->isRunning() && shouldThreadExit())
  285. {
  286. fProcess->waitForProcessToFinish(2000);
  287. if (fProcess->isRunning())
  288. {
  289. carla_stdout("CarlaPluginBridgeThread::run() - bridge refused to close, force kill now");
  290. fProcess->kill();
  291. }
  292. else
  293. {
  294. carla_stdout("CarlaPluginBridgeThread::run() - bridge auto-closed successfully");
  295. }
  296. }
  297. else
  298. {
  299. // forced quit, may have crashed
  300. if (fProcess->getExitCodeAndClearPID() != 0)
  301. {
  302. carla_stderr("CarlaPluginBridgeThread::run() - bridge crashed");
  303. CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n"
  304. "Saving now will lose its current settings.\n"
  305. "Please remove this plugin, and not rely on it from this point.");
  306. kEngine->callback(true, true,
  307. CarlaBackend::ENGINE_CALLBACK_ERROR, kPlugin->getId(), 0, 0, 0, 0.0f, errorString);
  308. }
  309. }
  310. fProcess = nullptr;
  311. }
  312. private:
  313. CarlaEngine* const kEngine;
  314. CarlaPlugin* const kPlugin;
  315. String fBinaryArchName;
  316. String fBridgeBinary;
  317. String fLabel;
  318. String fShmIds;
  319. #ifndef CARLA_OS_WIN
  320. String fWinePrefix;
  321. #endif
  322. CarlaScopedPointer<ChildProcess> fProcess;
  323. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridgeThread)
  324. };
  325. // ---------------------------------------------------------------------------------------------------------------------
  326. class CarlaPluginBridge : public CarlaPlugin
  327. {
  328. public:
  329. CarlaPluginBridge(CarlaEngine* const engine, const uint id, const BinaryType btype, const PluginType ptype)
  330. : CarlaPlugin(engine, id),
  331. fBinaryType(btype),
  332. fPluginType(ptype),
  333. fBridgeVersion(6), // before kPluginBridgeNonRtServerVersion was a thing, API was at 6
  334. fInitiated(false),
  335. fInitError(false),
  336. fSaved(true),
  337. fTimedOut(false),
  338. fTimedError(false),
  339. fBufferSize(engine->getBufferSize()),
  340. fProcWaitTime(0),
  341. fBridgeBinary(),
  342. fBridgeThread(engine, this),
  343. fShmAudioPool(),
  344. fShmRtClientControl(),
  345. fShmNonRtClientControl(),
  346. fShmNonRtServerControl(),
  347. #ifndef CARLA_OS_WIN
  348. fWinePrefix(),
  349. #endif
  350. fReceivingParamText(),
  351. fInfo(),
  352. fUniqueId(0),
  353. fLatency(0),
  354. fParams(nullptr)
  355. {
  356. carla_debug("CarlaPluginBridge::CarlaPluginBridge(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  357. pData->hints |= PLUGIN_IS_BRIDGE;
  358. }
  359. ~CarlaPluginBridge() override
  360. {
  361. carla_debug("CarlaPluginBridge::~CarlaPluginBridge()");
  362. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  363. // close UI
  364. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  365. pData->transientTryCounter = 0;
  366. #endif
  367. pData->singleMutex.lock();
  368. pData->masterMutex.lock();
  369. if (pData->client != nullptr && pData->client->isActive())
  370. pData->client->deactivate(true);
  371. if (pData->active)
  372. {
  373. deactivate();
  374. pData->active = false;
  375. }
  376. if (fBridgeThread.isThreadRunning())
  377. {
  378. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientQuit);
  379. fShmNonRtClientControl.commitWrite();
  380. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientQuit);
  381. fShmRtClientControl.commitWrite();
  382. if (! fTimedOut)
  383. waitForClient("stopping", 3000);
  384. }
  385. fBridgeThread.stopThread(3000);
  386. fShmNonRtServerControl.clear();
  387. fShmNonRtClientControl.clear();
  388. fShmRtClientControl.clear();
  389. fShmAudioPool.clear();
  390. clearBuffers();
  391. fInfo.chunk.clear();
  392. }
  393. // -------------------------------------------------------------------
  394. // Information (base)
  395. BinaryType getBinaryType() const noexcept override
  396. {
  397. return fBinaryType;
  398. }
  399. PluginType getType() const noexcept override
  400. {
  401. return fPluginType;
  402. }
  403. PluginCategory getCategory() const noexcept override
  404. {
  405. return fInfo.category;
  406. }
  407. int64_t getUniqueId() const noexcept override
  408. {
  409. return fUniqueId;
  410. }
  411. uint32_t getLatencyInFrames() const noexcept override
  412. {
  413. return fLatency;
  414. }
  415. // -------------------------------------------------------------------
  416. // Information (count)
  417. uint32_t getMidiInCount() const noexcept override
  418. {
  419. return fInfo.mIns;
  420. }
  421. uint32_t getMidiOutCount() const noexcept override
  422. {
  423. return fInfo.mOuts;
  424. }
  425. // -------------------------------------------------------------------
  426. // Information (current data)
  427. std::size_t getChunkData(void** const dataPtr) noexcept override
  428. {
  429. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  430. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  431. waitForSaved();
  432. CARLA_SAFE_ASSERT_RETURN(fInfo.chunk.size() > 0, 0);
  433. #ifdef CARLA_PROPER_CPP11_SUPPORT
  434. *dataPtr = fInfo.chunk.data();
  435. #else
  436. *dataPtr = &fInfo.chunk.front();
  437. #endif
  438. return fInfo.chunk.size();
  439. }
  440. // -------------------------------------------------------------------
  441. // Information (per-plugin data)
  442. uint getOptionsAvailable() const noexcept override
  443. {
  444. return fInfo.optionsAvailable;
  445. }
  446. float getParameterValue(const uint32_t parameterId) const noexcept override
  447. {
  448. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  449. return fParams[parameterId].value;
  450. }
  451. bool getLabel(char* const strBuf) const noexcept override
  452. {
  453. std::strncpy(strBuf, fInfo.label, STR_MAX);
  454. return true;
  455. }
  456. bool getMaker(char* const strBuf) const noexcept override
  457. {
  458. std::strncpy(strBuf, fInfo.maker, STR_MAX);
  459. return true;
  460. }
  461. bool getCopyright(char* const strBuf) const noexcept override
  462. {
  463. std::strncpy(strBuf, fInfo.copyright, STR_MAX);
  464. return true;
  465. }
  466. bool getRealName(char* const strBuf) const noexcept override
  467. {
  468. std::strncpy(strBuf, fInfo.name, STR_MAX);
  469. return true;
  470. }
  471. bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  472. {
  473. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  474. std::strncpy(strBuf, fParams[parameterId].name.buffer(), STR_MAX);
  475. return true;
  476. }
  477. bool getParameterText(const uint32_t parameterId, char* const strBuf) noexcept override
  478. {
  479. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  480. CARLA_SAFE_ASSERT_RETURN(! fReceivingParamText.isCurrentlyWaitingData(), false);
  481. const int32_t parameterIdi = static_cast<int32_t>(parameterId);
  482. fReceivingParamText.setTargetData(parameterIdi, strBuf);
  483. {
  484. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  485. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientGetParameterText);
  486. fShmNonRtClientControl.writeInt(parameterIdi);
  487. fShmNonRtClientControl.commitWrite();
  488. }
  489. if (waitForParameterText())
  490. return true;
  491. std::snprintf(strBuf, STR_MAX, "%.12g", static_cast<double>(fParams[parameterId].value));
  492. return false;
  493. }
  494. bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
  495. {
  496. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  497. std::strncpy(strBuf, fParams[parameterId].symbol.buffer(), STR_MAX);
  498. return true;
  499. }
  500. bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  501. {
  502. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
  503. std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX);
  504. return true;
  505. }
  506. // -------------------------------------------------------------------
  507. // Set data (state)
  508. void prepareForSave(bool) noexcept override
  509. {
  510. fSaved = false;
  511. {
  512. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  513. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPrepareForSave);
  514. fShmNonRtClientControl.commitWrite();
  515. }
  516. }
  517. bool waitForParameterText()
  518. {
  519. bool success;
  520. if (fReceivingParamText.wasDataReceived(&success))
  521. return success;
  522. const uint32_t timeoutEnd = Time::getMillisecondCounter() + 500; // 500 ms
  523. const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;
  524. for (; Time::getMillisecondCounter() < timeoutEnd && fBridgeThread.isThreadRunning();)
  525. {
  526. if (fReceivingParamText.wasDataReceived(&success))
  527. return success;
  528. if (needsEngineIdle)
  529. pData->engine->idle();
  530. carla_msleep(5);
  531. }
  532. if (! fBridgeThread.isThreadRunning())
  533. {
  534. carla_stderr("CarlaPluginBridge::waitForParameterText() - Bridge is not running");
  535. return false;
  536. }
  537. carla_stderr("CarlaPluginBridge::waitForParameterText() - Timeout while requesting text");
  538. return false;
  539. }
  540. void waitForSaved()
  541. {
  542. if (fSaved)
  543. return;
  544. // TODO: only wait 1 minute for NI plugins
  545. const uint32_t timeoutEnd = Time::getMillisecondCounter() + 60*1000; // 60 secs, 1 minute
  546. const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;
  547. for (; Time::getMillisecondCounter() < timeoutEnd && fBridgeThread.isThreadRunning();)
  548. {
  549. pData->engine->callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  550. if (needsEngineIdle)
  551. pData->engine->idle();
  552. if (fSaved)
  553. break;
  554. carla_msleep(20);
  555. }
  556. if (! fBridgeThread.isThreadRunning())
  557. return carla_stderr("CarlaPluginBridge::waitForSaved() - Bridge is not running");
  558. if (! fSaved)
  559. return carla_stderr("CarlaPluginBridge::waitForSaved() - Timeout while requesting save state");
  560. }
  561. // -------------------------------------------------------------------
  562. // Set data (internal stuff)
  563. void setOption(const uint option, const bool yesNo, const bool sendCallback) override
  564. {
  565. {
  566. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  567. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOption);
  568. fShmNonRtClientControl.writeUInt(option);
  569. fShmNonRtClientControl.writeBool(yesNo);
  570. fShmNonRtClientControl.commitWrite();
  571. }
  572. CarlaPlugin::setOption(option, yesNo, sendCallback);
  573. }
  574. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  575. {
  576. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,);
  577. {
  578. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  579. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCtrlChannel);
  580. fShmNonRtClientControl.writeShort(channel);
  581. fShmNonRtClientControl.commitWrite();
  582. }
  583. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  584. }
  585. void setName(const char* const newName) override
  586. {
  587. CarlaPlugin::setName(newName);
  588. if (pData->uiTitle.isEmpty() && fBridgeVersion >= 8)
  589. _setUiTitleFromName();
  590. }
  591. // -------------------------------------------------------------------
  592. // Set data (plugin-specific stuff)
  593. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  594. {
  595. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  596. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,);
  597. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  598. fParams[parameterId].value = fixedValue;
  599. {
  600. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  601. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterValue);
  602. fShmNonRtClientControl.writeUInt(parameterId);
  603. fShmNonRtClientControl.writeFloat(value);
  604. fShmNonRtClientControl.commitWrite();
  605. fShmNonRtClientControl.waitIfDataIsReachingLimit();
  606. }
  607. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  608. }
  609. void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override
  610. {
  611. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  612. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  613. fParams[parameterId].value = fixedValue;
  614. {
  615. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  616. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterValue);
  617. fShmNonRtClientControl.writeUInt(parameterId);
  618. fShmNonRtClientControl.writeFloat(value);
  619. fShmNonRtClientControl.commitWrite();
  620. fShmNonRtClientControl.waitIfDataIsReachingLimit();
  621. }
  622. CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater);
  623. }
  624. void setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  625. {
  626. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  627. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  628. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,);
  629. {
  630. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  631. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiChannel);
  632. fShmNonRtClientControl.writeUInt(parameterId);
  633. fShmNonRtClientControl.writeByte(channel);
  634. fShmNonRtClientControl.commitWrite();
  635. }
  636. CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback);
  637. }
  638. void setParameterMappedControlIndex(const uint32_t parameterId, const int16_t index,
  639. const bool sendOsc, const bool sendCallback,
  640. const bool reconfigureNow) noexcept override
  641. {
  642. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  643. CARLA_SAFE_ASSERT_RETURN(index >= CONTROL_INDEX_NONE && index <= CONTROL_INDEX_MAX_ALLOWED,);
  644. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,);
  645. {
  646. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  647. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedControlIndex);
  648. fShmNonRtClientControl.writeUInt(parameterId);
  649. fShmNonRtClientControl.writeShort(index);
  650. fShmNonRtClientControl.commitWrite();
  651. }
  652. CarlaPlugin::setParameterMappedControlIndex(parameterId, index, sendOsc, sendCallback, reconfigureNow);
  653. }
  654. void setParameterMappedRange(const uint32_t parameterId, const float minimum, const float maximum, const bool sendOsc, const bool sendCallback) noexcept override
  655. {
  656. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  657. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,);
  658. // kPluginBridgeNonRtClientSetParameterMappedRange was added in API 7
  659. if (fBridgeVersion >= 7)
  660. {
  661. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  662. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMappedRange);
  663. fShmNonRtClientControl.writeUInt(parameterId);
  664. fShmNonRtClientControl.writeFloat(minimum);
  665. fShmNonRtClientControl.writeFloat(maximum);
  666. fShmNonRtClientControl.commitWrite();
  667. }
  668. CarlaPlugin::setParameterMappedRange(parameterId, minimum, maximum, sendOsc, sendCallback);
  669. }
  670. void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
  671. {
  672. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  673. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
  674. {
  675. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  676. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetProgram);
  677. fShmNonRtClientControl.writeInt(index);
  678. fShmNonRtClientControl.commitWrite();
  679. }
  680. CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit);
  681. }
  682. void setProgramRT(const uint32_t index, const bool sendCallbackLater) noexcept override
  683. {
  684. CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,);
  685. {
  686. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  687. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetProgram);
  688. fShmNonRtClientControl.writeInt(static_cast<int32_t>(index));
  689. fShmNonRtClientControl.commitWrite();
  690. }
  691. CarlaPlugin::setProgramRT(index, sendCallbackLater);
  692. }
  693. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
  694. {
  695. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  696. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
  697. {
  698. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  699. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram);
  700. fShmNonRtClientControl.writeInt(index);
  701. fShmNonRtClientControl.commitWrite();
  702. }
  703. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
  704. }
  705. void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
  706. {
  707. CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
  708. {
  709. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  710. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram);
  711. fShmNonRtClientControl.writeInt(static_cast<int32_t>(uindex));
  712. fShmNonRtClientControl.commitWrite();
  713. }
  714. CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
  715. }
  716. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  717. {
  718. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  719. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  720. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  721. if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
  722. return CarlaPlugin::setCustomData(type, key, value, sendGui);
  723. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(key, "__CarlaPingOnOff__") == 0)
  724. {
  725. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  726. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPingOnOff);
  727. fShmNonRtClientControl.writeBool(std::strcmp(value, "true") == 0);
  728. fShmNonRtClientControl.commitWrite();
  729. return;
  730. }
  731. const uint32_t typeLen(static_cast<uint32_t>(std::strlen(type)));
  732. const uint32_t keyLen(static_cast<uint32_t>(std::strlen(key)));
  733. const uint32_t valueLen(static_cast<uint32_t>(std::strlen(value)));
  734. {
  735. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  736. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCustomData);
  737. fShmNonRtClientControl.writeUInt(typeLen);
  738. fShmNonRtClientControl.writeCustomData(type, typeLen);
  739. fShmNonRtClientControl.writeUInt(keyLen);
  740. fShmNonRtClientControl.writeCustomData(key, keyLen);
  741. fShmNonRtClientControl.writeUInt(valueLen);
  742. if (valueLen > 0)
  743. fShmNonRtClientControl.writeCustomData(value, valueLen);
  744. fShmNonRtClientControl.commitWrite();
  745. }
  746. CarlaPlugin::setCustomData(type, key, value, sendGui);
  747. }
  748. void setChunkData(const void* const data, const std::size_t dataSize) override
  749. {
  750. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  751. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  752. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  753. CarlaString dataBase64(CarlaString::asBase64(data, dataSize));
  754. CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0,);
  755. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  756. filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
  757. filePath += fShmAudioPool.getFilenameSuffix();
  758. if (File(filePath).replaceWithText(dataBase64.buffer()))
  759. {
  760. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  761. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  762. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile);
  763. fShmNonRtClientControl.writeUInt(ulength);
  764. fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength);
  765. fShmNonRtClientControl.commitWrite();
  766. }
  767. // save data internally as well
  768. fInfo.chunk.resize(dataSize);
  769. #ifdef CARLA_PROPER_CPP11_SUPPORT
  770. std::memcpy(fInfo.chunk.data(), data, dataSize);
  771. #else
  772. std::memcpy(&fInfo.chunk.front(), data, dataSize);
  773. #endif
  774. }
  775. // -------------------------------------------------------------------
  776. // Set ui stuff
  777. void setCustomUITitle(const char* const title) noexcept override
  778. {
  779. carla_debug("CarlaPluginBridge::setCustomUITitle(%s)", title);
  780. if (fBridgeVersion >= 8)
  781. {
  782. const uint32_t size = static_cast<uint32_t>(std::strlen(title));
  783. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  784. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetWindowTitle);
  785. fShmNonRtClientControl.writeUInt(size);
  786. fShmNonRtClientControl.writeCustomData(title, size);
  787. fShmNonRtClientControl.commitWrite();
  788. }
  789. CarlaPlugin::setCustomUITitle(title);
  790. }
  791. void showCustomUI(const bool yesNo) override
  792. {
  793. if (yesNo && pData->uiTitle.isEmpty() && fBridgeVersion >= 8)
  794. _setUiTitleFromName();
  795. {
  796. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  797. fShmNonRtClientControl.writeOpcode(yesNo ? kPluginBridgeNonRtClientShowUI : kPluginBridgeNonRtClientHideUI);
  798. fShmNonRtClientControl.commitWrite();
  799. }
  800. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  801. if (yesNo)
  802. {
  803. pData->tryTransient();
  804. }
  805. else
  806. {
  807. pData->transientTryCounter = 0;
  808. }
  809. #endif
  810. }
  811. void idle() override
  812. {
  813. if (fBridgeThread.isThreadRunning())
  814. {
  815. if (fInitiated && fTimedOut && pData->active)
  816. setActive(false, true, true);
  817. {
  818. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  819. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPing);
  820. fShmNonRtClientControl.commitWrite();
  821. }
  822. try {
  823. handleNonRtData();
  824. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  825. }
  826. else if (fInitiated)
  827. {
  828. fTimedOut = true;
  829. fTimedError = true;
  830. fInitiated = false;
  831. handleProcessStopped();
  832. }
  833. CarlaPlugin::idle();
  834. }
  835. // -------------------------------------------------------------------
  836. // Plugin state
  837. void reload() override
  838. {
  839. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  840. carla_debug("CarlaPluginBridge::reload() - start");
  841. const EngineProcessMode processMode(pData->engine->getProccessMode());
  842. // Safely disable plugin for reload
  843. const ScopedDisabler sd(this);
  844. // cleanup of previous data
  845. pData->audioIn.clear();
  846. pData->audioOut.clear();
  847. pData->cvIn.clear();
  848. pData->cvOut.clear();
  849. pData->event.clear();
  850. bool needsCtrlIn, needsCtrlOut;
  851. needsCtrlIn = needsCtrlOut = false;
  852. if (fInfo.aIns > 0)
  853. {
  854. pData->audioIn.createNew(fInfo.aIns);
  855. }
  856. if (fInfo.aOuts > 0)
  857. {
  858. pData->audioOut.createNew(fInfo.aOuts);
  859. needsCtrlIn = true;
  860. }
  861. if (fInfo.cvIns > 0)
  862. {
  863. pData->cvIn.createNew(fInfo.cvIns);
  864. }
  865. if (fInfo.cvOuts > 0)
  866. {
  867. pData->cvOut.createNew(fInfo.cvOuts);
  868. }
  869. if (fInfo.mIns > 0)
  870. needsCtrlIn = true;
  871. if (fInfo.mOuts > 0)
  872. needsCtrlOut = true;
  873. const uint portNameSize(pData->engine->getMaxPortNameSize());
  874. CarlaString portName;
  875. // Audio Ins
  876. for (uint32_t j=0; j < fInfo.aIns; ++j)
  877. {
  878. portName.clear();
  879. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  880. {
  881. portName = pData->name;
  882. portName += ":";
  883. }
  884. if (fInfo.aInNames != nullptr && fInfo.aInNames[j] != nullptr)
  885. {
  886. portName += fInfo.aInNames[j];
  887. }
  888. else if (fInfo.aIns > 1)
  889. {
  890. portName += "input_";
  891. portName += CarlaString(j+1);
  892. }
  893. else
  894. portName += "input";
  895. portName.truncate(portNameSize);
  896. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
  897. pData->audioIn.ports[j].rindex = j;
  898. }
  899. // Audio Outs
  900. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  901. {
  902. portName.clear();
  903. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  904. {
  905. portName = pData->name;
  906. portName += ":";
  907. }
  908. if (fInfo.aOutNames != nullptr && fInfo.aOutNames[j] != nullptr)
  909. {
  910. portName += fInfo.aOutNames[j];
  911. }
  912. else if (fInfo.aOuts > 1)
  913. {
  914. portName += "output_";
  915. portName += CarlaString(j+1);
  916. }
  917. else
  918. portName += "output";
  919. portName.truncate(portNameSize);
  920. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
  921. pData->audioOut.ports[j].rindex = j;
  922. }
  923. // TODO - MIDI
  924. // CV Ins
  925. for (uint32_t j=0; j < fInfo.cvIns; ++j)
  926. {
  927. portName.clear();
  928. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  929. {
  930. portName = pData->name;
  931. portName += ":";
  932. }
  933. if (fInfo.cvInNames != nullptr && fInfo.cvInNames[j] != nullptr)
  934. {
  935. portName += fInfo.cvInNames[j];
  936. }
  937. else if (fInfo.cvIns > 1)
  938. {
  939. portName += "cv_input_";
  940. portName += CarlaString(j+1);
  941. }
  942. else
  943. portName += "cv_input";
  944. portName.truncate(portNameSize);
  945. pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, j);
  946. pData->cvIn.ports[j].rindex = j;
  947. }
  948. // CV Outs
  949. for (uint32_t j=0; j < fInfo.cvOuts; ++j)
  950. {
  951. portName.clear();
  952. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  953. {
  954. portName = pData->name;
  955. portName += ":";
  956. }
  957. if (fInfo.cvOutNames != nullptr && fInfo.cvOutNames[j] != nullptr)
  958. {
  959. portName += fInfo.cvOutNames[j];
  960. }
  961. else if (fInfo.cvOuts > 1)
  962. {
  963. portName += "cv_output_";
  964. portName += CarlaString(j+1);
  965. }
  966. else
  967. portName += "cv_output";
  968. portName.truncate(portNameSize);
  969. pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, false, j);
  970. pData->cvOut.ports[j].rindex = j;
  971. }
  972. if (needsCtrlIn)
  973. {
  974. portName.clear();
  975. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  976. {
  977. portName = pData->name;
  978. portName += ":";
  979. }
  980. portName += "event-in";
  981. portName.truncate(portNameSize);
  982. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
  983. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  984. pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
  985. #endif
  986. }
  987. if (needsCtrlOut)
  988. {
  989. portName.clear();
  990. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  991. {
  992. portName = pData->name;
  993. portName += ":";
  994. }
  995. portName += "event-out";
  996. portName.truncate(portNameSize);
  997. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
  998. }
  999. // extra plugin hints
  1000. pData->extraHints = 0x0;
  1001. if (fInfo.mIns > 0)
  1002. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  1003. if (fInfo.mOuts > 0)
  1004. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  1005. bufferSizeChanged(pData->engine->getBufferSize());
  1006. reloadPrograms(true);
  1007. carla_debug("CarlaPluginBridge::reload() - end");
  1008. }
  1009. // -------------------------------------------------------------------
  1010. // Plugin processing
  1011. void activate() noexcept override
  1012. {
  1013. if (! fBridgeThread.isThreadRunning())
  1014. {
  1015. CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),);
  1016. }
  1017. {
  1018. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1019. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate);
  1020. fShmNonRtClientControl.commitWrite();
  1021. }
  1022. fTimedOut = false;
  1023. try {
  1024. waitForClient("activate", 2000);
  1025. } CARLA_SAFE_EXCEPTION("activate - waitForClient");
  1026. }
  1027. void deactivate() noexcept override
  1028. {
  1029. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  1030. {
  1031. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1032. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate);
  1033. fShmNonRtClientControl.commitWrite();
  1034. }
  1035. fTimedOut = false;
  1036. try {
  1037. waitForClient("deactivate", 2000);
  1038. } CARLA_SAFE_EXCEPTION("deactivate - waitForClient");
  1039. }
  1040. void process(const float* const* const audioIn,
  1041. float** const audioOut,
  1042. const float* const* const cvIn,
  1043. float** const cvOut,
  1044. const uint32_t frames) override
  1045. {
  1046. // --------------------------------------------------------------------------------------------------------
  1047. // Check if active
  1048. if (fTimedOut || fTimedError || ! pData->active)
  1049. {
  1050. // disable any output sound
  1051. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1052. carla_zeroFloats(audioOut[i], frames);
  1053. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1054. carla_zeroFloats(cvOut[i], frames);
  1055. return;
  1056. }
  1057. // --------------------------------------------------------------------------------------------------------
  1058. // Check if needs reset
  1059. if (pData->needsReset)
  1060. {
  1061. // TODO
  1062. pData->needsReset = false;
  1063. }
  1064. // --------------------------------------------------------------------------------------------------------
  1065. // Event Input
  1066. if (pData->event.portIn != nullptr)
  1067. {
  1068. // ----------------------------------------------------------------------------------------------------
  1069. // MIDI Input (External)
  1070. if (pData->extNotes.mutex.tryLock())
  1071. {
  1072. for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next())
  1073. {
  1074. const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback));
  1075. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  1076. uint8_t data1, data2, data3;
  1077. data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  1078. data2 = note.note;
  1079. data3 = note.velo;
  1080. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  1081. fShmRtClientControl.writeUInt(0); // time
  1082. fShmRtClientControl.writeByte(0); // port
  1083. fShmRtClientControl.writeByte(3); // size
  1084. fShmRtClientControl.writeByte(data1);
  1085. fShmRtClientControl.writeByte(data2);
  1086. fShmRtClientControl.writeByte(data3);
  1087. fShmRtClientControl.commitWrite();
  1088. }
  1089. pData->extNotes.data.clear();
  1090. pData->extNotes.mutex.unlock();
  1091. } // End of MIDI Input (External)
  1092. // ----------------------------------------------------------------------------------------------------
  1093. // Event Input (System)
  1094. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1095. bool allNotesOffSent = false;
  1096. if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
  1097. {
  1098. const bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0x0;
  1099. pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn);
  1100. }
  1101. #endif
  1102. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  1103. {
  1104. EngineEvent& event(pData->event.portIn->getEvent(i));
  1105. // Control change
  1106. switch (event.type)
  1107. {
  1108. case kEngineEventTypeNull:
  1109. break;
  1110. case kEngineEventTypeControl: {
  1111. EngineControlEvent& ctrlEvent = event.ctrl;
  1112. switch (ctrlEvent.type)
  1113. {
  1114. case kEngineControlEventTypeNull:
  1115. break;
  1116. case kEngineControlEventTypeParameter: {
  1117. float value;
  1118. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1119. // non-midi
  1120. if (event.channel == kEngineEventNonMidiChannel)
  1121. {
  1122. const uint32_t k = ctrlEvent.param;
  1123. CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
  1124. ctrlEvent.handled = true;
  1125. value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
  1126. setParameterValueRT(k, value, true);
  1127. continue;
  1128. }
  1129. // Control backend stuff
  1130. if (event.channel == pData->ctrlChannel)
  1131. {
  1132. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  1133. {
  1134. ctrlEvent.handled = true;
  1135. value = ctrlEvent.normalizedValue;
  1136. setDryWetRT(value, true);
  1137. }
  1138. else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  1139. {
  1140. ctrlEvent.handled = true;
  1141. value = ctrlEvent.normalizedValue*127.0f/100.0f;
  1142. setVolumeRT(value, true);
  1143. }
  1144. else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  1145. {
  1146. float left, right;
  1147. value = ctrlEvent.normalizedValue/0.5f - 1.0f;
  1148. if (value < 0.0f)
  1149. {
  1150. left = -1.0f;
  1151. right = (value*2.0f)+1.0f;
  1152. }
  1153. else if (value > 0.0f)
  1154. {
  1155. left = (value*2.0f)-1.0f;
  1156. right = 1.0f;
  1157. }
  1158. else
  1159. {
  1160. left = -1.0f;
  1161. right = 1.0f;
  1162. }
  1163. ctrlEvent.handled = true;
  1164. setBalanceLeftRT(left, true);
  1165. setBalanceRightRT(right, true);
  1166. }
  1167. }
  1168. #endif
  1169. // Control plugin parameters
  1170. for (uint32_t k=0; k < pData->param.count; ++k)
  1171. {
  1172. if (pData->param.data[k].midiChannel != event.channel)
  1173. continue;
  1174. if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
  1175. continue;
  1176. if (pData->param.data[k].type != PARAMETER_INPUT)
  1177. continue;
  1178. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  1179. continue;
  1180. ctrlEvent.handled = true;
  1181. value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
  1182. setParameterValueRT(k, value, true);
  1183. }
  1184. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1185. if (! ctrlEvent.handled)
  1186. checkForMidiLearn(event);
  1187. #endif
  1188. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
  1189. {
  1190. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  1191. fShmRtClientControl.writeUInt(event.time);
  1192. fShmRtClientControl.writeByte(0); // port
  1193. fShmRtClientControl.writeByte(3); // size
  1194. fShmRtClientControl.writeByte(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)));
  1195. fShmRtClientControl.writeByte(uint8_t(ctrlEvent.param));
  1196. fShmRtClientControl.writeByte(uint8_t(ctrlEvent.normalizedValue*127.0f));
  1197. }
  1198. break;
  1199. }
  1200. case kEngineControlEventTypeMidiBank:
  1201. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  1202. {
  1203. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiBank);
  1204. fShmRtClientControl.writeUInt(event.time);
  1205. fShmRtClientControl.writeByte(event.channel);
  1206. fShmRtClientControl.writeUShort(event.ctrl.param);
  1207. fShmRtClientControl.commitWrite();
  1208. }
  1209. else if ((pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) != 0)
  1210. {
  1211. // VST2's that use banks usually require both a MSB bank message and a LSB bank message. The MSB bank message can just be 0
  1212. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  1213. fShmRtClientControl.writeUInt(event.time);
  1214. fShmRtClientControl.writeByte(0); // port
  1215. fShmRtClientControl.writeByte(3); // size
  1216. fShmRtClientControl.writeByte(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)));
  1217. fShmRtClientControl.writeByte(MIDI_CONTROL_BANK_SELECT);
  1218. fShmRtClientControl.writeByte(0);
  1219. fShmRtClientControl.commitWrite();
  1220. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  1221. fShmRtClientControl.writeUInt(event.time);
  1222. fShmRtClientControl.writeByte(0); // port
  1223. fShmRtClientControl.writeByte(3); // size
  1224. fShmRtClientControl.writeByte(uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT)));
  1225. fShmRtClientControl.writeByte(MIDI_CONTROL_BANK_SELECT__LSB);
  1226. fShmRtClientControl.writeByte(uint8_t(event.ctrl.param));
  1227. fShmRtClientControl.commitWrite();
  1228. }
  1229. break;
  1230. case kEngineControlEventTypeMidiProgram:
  1231. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES || pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
  1232. {
  1233. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiProgram);
  1234. fShmRtClientControl.writeUInt(event.time);
  1235. fShmRtClientControl.writeByte(event.channel);
  1236. fShmRtClientControl.writeUShort(event.ctrl.param);
  1237. fShmRtClientControl.commitWrite();
  1238. }
  1239. break;
  1240. case kEngineControlEventTypeAllSoundOff:
  1241. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1242. {
  1243. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllSoundOff);
  1244. fShmRtClientControl.writeUInt(event.time);
  1245. fShmRtClientControl.writeByte(event.channel);
  1246. fShmRtClientControl.commitWrite();
  1247. }
  1248. break;
  1249. case kEngineControlEventTypeAllNotesOff:
  1250. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1251. {
  1252. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1253. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  1254. {
  1255. allNotesOffSent = true;
  1256. postponeRtAllNotesOff();
  1257. }
  1258. #endif
  1259. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllNotesOff);
  1260. fShmRtClientControl.writeUInt(event.time);
  1261. fShmRtClientControl.writeByte(event.channel);
  1262. fShmRtClientControl.commitWrite();
  1263. }
  1264. break;
  1265. } // switch (ctrlEvent.type)
  1266. break;
  1267. } // case kEngineEventTypeControl
  1268. case kEngineEventTypeMidi: {
  1269. const EngineMidiEvent& midiEvent(event.midi);
  1270. if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE)
  1271. continue;
  1272. const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
  1273. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
  1274. if ((status == MIDI_STATUS_NOTE_OFF || status == MIDI_STATUS_NOTE_ON) && (pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES))
  1275. continue;
  1276. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  1277. continue;
  1278. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  1279. continue;
  1280. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  1281. continue;
  1282. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  1283. continue;
  1284. // Fix bad note-off
  1285. if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
  1286. status = MIDI_STATUS_NOTE_OFF;
  1287. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  1288. fShmRtClientControl.writeUInt(event.time);
  1289. fShmRtClientControl.writeByte(midiEvent.port);
  1290. fShmRtClientControl.writeByte(midiEvent.size);
  1291. fShmRtClientControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT)));
  1292. for (uint8_t j=1; j < midiEvent.size; ++j)
  1293. fShmRtClientControl.writeByte(midiData[j]);
  1294. fShmRtClientControl.commitWrite();
  1295. if (status == MIDI_STATUS_NOTE_ON)
  1296. {
  1297. pData->postponeNoteOnRtEvent(true, event.channel, midiData[1], midiData[2]);
  1298. }
  1299. else if (status == MIDI_STATUS_NOTE_OFF)
  1300. {
  1301. pData->postponeNoteOffRtEvent(true, event.channel, midiData[1]);
  1302. }
  1303. } break;
  1304. }
  1305. }
  1306. pData->postRtEvents.trySplice();
  1307. } // End of Event Input
  1308. if (! processSingle(audioIn, audioOut, cvIn, cvOut, frames))
  1309. return;
  1310. // --------------------------------------------------------------------------------------------------------
  1311. // Control and MIDI Output
  1312. if (pData->event.portOut != nullptr)
  1313. {
  1314. float value;
  1315. for (uint32_t k=0; k < pData->param.count; ++k)
  1316. {
  1317. if (pData->param.data[k].type != PARAMETER_OUTPUT)
  1318. continue;
  1319. if (pData->param.data[k].mappedControlIndex > 0)
  1320. {
  1321. value = pData->param.ranges[k].getNormalizedValue(fParams[k].value);
  1322. pData->event.portOut->writeControlEvent(0,
  1323. pData->param.data[k].midiChannel,
  1324. kEngineControlEventTypeParameter,
  1325. static_cast<uint16_t>(pData->param.data[k].mappedControlIndex),
  1326. -1,
  1327. value);
  1328. }
  1329. }
  1330. uint32_t time;
  1331. uint8_t port, size;
  1332. const uint8_t* midiData(fShmRtClientControl.data->midiOut);
  1333. for (std::size_t read=0; read<kBridgeRtClientDataMidiOutSize-kBridgeBaseMidiOutHeaderSize;)
  1334. {
  1335. // get time
  1336. time = *(const uint32_t*)midiData;
  1337. midiData += 4;
  1338. // get port and size
  1339. port = *midiData++;
  1340. size = *midiData++;
  1341. if (size == 0)
  1342. break;
  1343. // store midi data advancing as needed
  1344. uint8_t data[size];
  1345. for (uint8_t j=0; j<size; ++j)
  1346. data[j] = *midiData++;
  1347. pData->event.portOut->writeMidiEvent(time, size, data);
  1348. read += kBridgeBaseMidiOutHeaderSize + size;
  1349. }
  1350. // TODO
  1351. (void)port;
  1352. } // End of Control and MIDI Output
  1353. }
  1354. bool processSingle(const float* const* const audioIn, float** const audioOut,
  1355. const float* const* const cvIn, float** const cvOut, const uint32_t frames)
  1356. {
  1357. CARLA_SAFE_ASSERT_RETURN(! fTimedError, false);
  1358. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  1359. CARLA_SAFE_ASSERT_RETURN(frames <= fBufferSize, false);
  1360. if (pData->audioIn.count > 0)
  1361. {
  1362. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  1363. }
  1364. if (pData->audioOut.count > 0)
  1365. {
  1366. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  1367. }
  1368. if (pData->cvIn.count > 0)
  1369. {
  1370. CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
  1371. }
  1372. if (pData->cvOut.count > 0)
  1373. {
  1374. CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
  1375. }
  1376. // --------------------------------------------------------------------------------------------------------
  1377. // Try lock, silence otherwise
  1378. #ifndef STOAT_TEST_BUILD
  1379. if (pData->engine->isOffline())
  1380. {
  1381. pData->singleMutex.lock();
  1382. }
  1383. else
  1384. #endif
  1385. if (! pData->singleMutex.tryLock())
  1386. {
  1387. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1388. carla_zeroFloats(audioOut[i], frames);
  1389. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1390. carla_zeroFloats(cvOut[i], frames);
  1391. return false;
  1392. }
  1393. // --------------------------------------------------------------------------------------------------------
  1394. // Reset audio buffers
  1395. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1396. carla_copyFloats(fShmAudioPool.data + (i * fBufferSize), audioIn[i], frames);
  1397. for (uint32_t i=0; i < pData->cvIn.count; ++i)
  1398. carla_copyFloats(fShmAudioPool.data + ((pData->audioIn.count + pData->audioOut.count + i) * fBufferSize), cvIn[i], frames);
  1399. // --------------------------------------------------------------------------------------------------------
  1400. // TimeInfo
  1401. const EngineTimeInfo timeInfo(pData->engine->getTimeInfo());
  1402. BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  1403. bridgeTimeInfo.playing = timeInfo.playing;
  1404. bridgeTimeInfo.frame = timeInfo.frame;
  1405. bridgeTimeInfo.usecs = timeInfo.usecs;
  1406. bridgeTimeInfo.validFlags = timeInfo.bbt.valid ? kPluginBridgeTimeInfoValidBBT : 0x0;
  1407. if (timeInfo.bbt.valid)
  1408. {
  1409. bridgeTimeInfo.bar = timeInfo.bbt.bar;
  1410. bridgeTimeInfo.beat = timeInfo.bbt.beat;
  1411. bridgeTimeInfo.tick = timeInfo.bbt.tick;
  1412. bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar;
  1413. bridgeTimeInfo.beatType = timeInfo.bbt.beatType;
  1414. bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  1415. bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  1416. bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick;
  1417. }
  1418. // --------------------------------------------------------------------------------------------------------
  1419. // Run plugin
  1420. {
  1421. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientProcess);
  1422. fShmRtClientControl.writeUInt(frames);
  1423. fShmRtClientControl.commitWrite();
  1424. }
  1425. waitForClient("process", fProcWaitTime);
  1426. if (fTimedOut)
  1427. {
  1428. pData->singleMutex.unlock();
  1429. return false;
  1430. }
  1431. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1432. carla_copyFloats(audioOut[i], fShmAudioPool.data + ((pData->audioIn.count + i) * fBufferSize), frames);
  1433. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1434. carla_copyFloats(cvOut[i], fShmAudioPool.data + ((pData->audioIn.count + pData->audioOut.count + pData->cvIn.count + i) * fBufferSize), frames);
  1435. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1436. // --------------------------------------------------------------------------------------------------------
  1437. // Post-processing (dry/wet, volume and balance)
  1438. {
  1439. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f);
  1440. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
  1441. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
  1442. const bool isMono = (pData->audioIn.count == 1);
  1443. bool isPair;
  1444. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1445. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1446. {
  1447. // Dry/Wet
  1448. if (doDryWet)
  1449. {
  1450. const uint32_t c = isMono ? 0 : i;
  1451. for (uint32_t k=0; k < frames; ++k)
  1452. {
  1453. # ifndef BUILD_BRIDGE
  1454. if (k < pData->latency.frames && pData->latency.buffers != nullptr)
  1455. bufValue = pData->latency.buffers[c][k];
  1456. else if (pData->latency.frames < frames)
  1457. bufValue = audioIn[c][k-pData->latency.frames];
  1458. else
  1459. # endif
  1460. bufValue = audioIn[c][k];
  1461. audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1462. }
  1463. }
  1464. // Balance
  1465. if (doBalance)
  1466. {
  1467. isPair = (i % 2 == 0);
  1468. if (isPair)
  1469. {
  1470. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1471. carla_copyFloats(oldBufLeft, audioOut[i], frames);
  1472. }
  1473. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1474. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1475. for (uint32_t k=0; k < frames; ++k)
  1476. {
  1477. if (isPair)
  1478. {
  1479. // left
  1480. audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1481. audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR);
  1482. }
  1483. else
  1484. {
  1485. // right
  1486. audioOut[i][k] = audioOut[i][k] * balRangeR;
  1487. audioOut[i][k] += oldBufLeft[k] * balRangeL;
  1488. }
  1489. }
  1490. }
  1491. // Volume (and buffer copy)
  1492. if (doVolume)
  1493. {
  1494. for (uint32_t k=0; k < frames; ++k)
  1495. audioOut[i][k] *= pData->postProc.volume;
  1496. }
  1497. }
  1498. } // End of Post-processing
  1499. # ifndef BUILD_BRIDGE
  1500. // --------------------------------------------------------------------------------------------------------
  1501. // Save latency values for next callback
  1502. if (pData->latency.frames != 0 && pData->latency.buffers != nullptr)
  1503. {
  1504. const uint32_t latframes = pData->latency.frames;
  1505. if (latframes <= frames)
  1506. {
  1507. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1508. carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
  1509. }
  1510. else
  1511. {
  1512. const uint32_t diff = latframes - frames;
  1513. for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
  1514. {
  1515. // push back buffer by 'frames'
  1516. for (k=0; k < diff; ++k)
  1517. pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
  1518. // put current input at the end
  1519. for (uint32_t j=0; k < latframes; ++j, ++k)
  1520. pData->latency.buffers[i][k] = audioIn[i][j];
  1521. }
  1522. }
  1523. }
  1524. # endif
  1525. #endif // BUILD_BRIDGE_ALTERNATIVE_ARCH
  1526. // --------------------------------------------------------------------------------------------------------
  1527. pData->singleMutex.unlock();
  1528. return true;
  1529. }
  1530. void bufferSizeChanged(const uint32_t newBufferSize) override
  1531. {
  1532. fBufferSize = newBufferSize;
  1533. resizeAudioPool(newBufferSize);
  1534. {
  1535. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetBufferSize);
  1536. fShmRtClientControl.writeUInt(newBufferSize);
  1537. fShmRtClientControl.commitWrite();
  1538. }
  1539. //fProcWaitTime = newBufferSize*1000/pData->engine->getSampleRate();
  1540. fProcWaitTime = 1000;
  1541. waitForClient("buffersize", 1000);
  1542. }
  1543. void sampleRateChanged(const double newSampleRate) override
  1544. {
  1545. {
  1546. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetSampleRate);
  1547. fShmRtClientControl.writeDouble(newSampleRate);
  1548. fShmRtClientControl.commitWrite();
  1549. }
  1550. //fProcWaitTime = pData->engine->getBufferSize()*1000/newSampleRate;
  1551. fProcWaitTime = 1000;
  1552. waitForClient("samplerate", 1000);
  1553. }
  1554. void offlineModeChanged(const bool isOffline) override
  1555. {
  1556. {
  1557. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetOnline);
  1558. fShmRtClientControl.writeBool(isOffline);
  1559. fShmRtClientControl.commitWrite();
  1560. }
  1561. waitForClient("offline", 1000);
  1562. }
  1563. // -------------------------------------------------------------------
  1564. // Plugin buffers
  1565. void clearBuffers() noexcept override
  1566. {
  1567. if (fParams != nullptr)
  1568. {
  1569. delete[] fParams;
  1570. fParams = nullptr;
  1571. }
  1572. CarlaPlugin::clearBuffers();
  1573. }
  1574. // -------------------------------------------------------------------
  1575. // Post-poned UI Stuff
  1576. void uiParameterChange(const uint32_t index, const float value) noexcept override
  1577. {
  1578. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  1579. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1580. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiParameterChange);
  1581. fShmNonRtClientControl.writeUInt(index);
  1582. fShmNonRtClientControl.writeFloat(value);
  1583. fShmNonRtClientControl.commitWrite();
  1584. }
  1585. void uiProgramChange(const uint32_t index) noexcept override
  1586. {
  1587. CARLA_SAFE_ASSERT_RETURN(index < pData->prog.count,);
  1588. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1589. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiProgramChange);
  1590. fShmNonRtClientControl.writeUInt(index);
  1591. fShmNonRtClientControl.commitWrite();
  1592. }
  1593. void uiMidiProgramChange(const uint32_t index) noexcept override
  1594. {
  1595. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1596. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1597. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiMidiProgramChange);
  1598. fShmNonRtClientControl.writeUInt(index);
  1599. fShmNonRtClientControl.commitWrite();
  1600. }
  1601. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  1602. {
  1603. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1604. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1605. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1606. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1607. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOn);
  1608. fShmNonRtClientControl.writeByte(channel);
  1609. fShmNonRtClientControl.writeByte(note);
  1610. fShmNonRtClientControl.writeByte(velo);
  1611. fShmNonRtClientControl.commitWrite();
  1612. }
  1613. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  1614. {
  1615. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1616. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1617. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1618. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOff);
  1619. fShmNonRtClientControl.writeByte(channel);
  1620. fShmNonRtClientControl.writeByte(note);
  1621. fShmNonRtClientControl.commitWrite();
  1622. }
  1623. // -------------------------------------------------------------------
  1624. // Internal helper functions
  1625. void restoreLV2State(bool) noexcept override
  1626. {
  1627. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1628. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientRestoreLV2State);
  1629. fShmNonRtClientControl.commitWrite();
  1630. }
  1631. void waitForBridgeSaveSignal() noexcept override
  1632. {
  1633. // VSTs only save chunks, for which we already have a waitForSaved there
  1634. if (fPluginType != PLUGIN_VST2)
  1635. waitForSaved();
  1636. }
  1637. // -------------------------------------------------------------------
  1638. void handleNonRtData()
  1639. {
  1640. for (; fShmNonRtServerControl.isDataAvailableForReading();)
  1641. {
  1642. const PluginBridgeNonRtServerOpcode opcode(fShmNonRtServerControl.readOpcode());
  1643. #ifdef DEBUG
  1644. if (opcode != kPluginBridgeNonRtServerPong && opcode != kPluginBridgeNonRtServerParameterValue2) {
  1645. carla_debug("CarlaPluginBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode));
  1646. }
  1647. #endif
  1648. switch (opcode)
  1649. {
  1650. case kPluginBridgeNonRtServerNull:
  1651. case kPluginBridgeNonRtServerPong:
  1652. break;
  1653. case kPluginBridgeNonRtServerVersion:
  1654. fBridgeVersion = fShmNonRtServerControl.readUInt();
  1655. break;
  1656. case kPluginBridgeNonRtServerPluginInfo1: {
  1657. // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  1658. const uint32_t category = fShmNonRtServerControl.readUInt();
  1659. const uint32_t hints = fShmNonRtServerControl.readUInt();
  1660. const uint32_t optionAv = fShmNonRtServerControl.readUInt();
  1661. const uint32_t optionEn = fShmNonRtServerControl.readUInt();
  1662. const int64_t uniqueId = fShmNonRtServerControl.readLong();
  1663. if (fUniqueId != 0) {
  1664. CARLA_SAFE_ASSERT_INT2(fUniqueId == uniqueId, fUniqueId, uniqueId);
  1665. }
  1666. pData->hints = hints | PLUGIN_IS_BRIDGE;
  1667. pData->options = optionEn;
  1668. fInfo.category = static_cast<PluginCategory>(category);
  1669. fInfo.optionsAvailable = optionAv;
  1670. } break;
  1671. case kPluginBridgeNonRtServerPluginInfo2: {
  1672. // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  1673. // realName
  1674. const uint32_t realNameSize(fShmNonRtServerControl.readUInt());
  1675. char realName[realNameSize+1];
  1676. carla_zeroChars(realName, realNameSize+1);
  1677. fShmNonRtServerControl.readCustomData(realName, realNameSize);
  1678. // label
  1679. const uint32_t labelSize(fShmNonRtServerControl.readUInt());
  1680. char label[labelSize+1];
  1681. carla_zeroChars(label, labelSize+1);
  1682. fShmNonRtServerControl.readCustomData(label, labelSize);
  1683. // maker
  1684. const uint32_t makerSize(fShmNonRtServerControl.readUInt());
  1685. char maker[makerSize+1];
  1686. carla_zeroChars(maker, makerSize+1);
  1687. fShmNonRtServerControl.readCustomData(maker, makerSize);
  1688. // copyright
  1689. const uint32_t copyrightSize(fShmNonRtServerControl.readUInt());
  1690. char copyright[copyrightSize+1];
  1691. carla_zeroChars(copyright, copyrightSize+1);
  1692. fShmNonRtServerControl.readCustomData(copyright, copyrightSize);
  1693. fInfo.name = realName;
  1694. fInfo.label = label;
  1695. fInfo.maker = maker;
  1696. fInfo.copyright = copyright;
  1697. if (pData->name == nullptr)
  1698. pData->name = pData->engine->getUniquePluginName(realName);
  1699. } break;
  1700. case kPluginBridgeNonRtServerAudioCount: {
  1701. // uint/ins, uint/outs
  1702. fInfo.clear();
  1703. fInfo.aIns = fShmNonRtServerControl.readUInt();
  1704. fInfo.aOuts = fShmNonRtServerControl.readUInt();
  1705. if (fInfo.aIns > 0)
  1706. {
  1707. fInfo.aInNames = new const char*[fInfo.aIns];
  1708. carla_zeroPointers(fInfo.aInNames, fInfo.aIns);
  1709. }
  1710. if (fInfo.aOuts > 0)
  1711. {
  1712. fInfo.aOutNames = new const char*[fInfo.aOuts];
  1713. carla_zeroPointers(fInfo.aOutNames, fInfo.aOuts);
  1714. }
  1715. } break;
  1716. case kPluginBridgeNonRtServerMidiCount: {
  1717. // uint/ins, uint/outs
  1718. fInfo.mIns = fShmNonRtServerControl.readUInt();
  1719. fInfo.mOuts = fShmNonRtServerControl.readUInt();
  1720. } break;
  1721. case kPluginBridgeNonRtServerCvCount: {
  1722. // uint/ins, uint/outs
  1723. fInfo.cvIns = fShmNonRtServerControl.readUInt();
  1724. fInfo.cvOuts = fShmNonRtServerControl.readUInt();
  1725. } break;
  1726. case kPluginBridgeNonRtServerParameterCount: {
  1727. // uint/count
  1728. const uint32_t count = fShmNonRtServerControl.readUInt();
  1729. // delete old data
  1730. pData->param.clear();
  1731. if (fParams != nullptr)
  1732. {
  1733. delete[] fParams;
  1734. fParams = nullptr;
  1735. }
  1736. if (count > 0)
  1737. {
  1738. pData->param.createNew(count, false);
  1739. fParams = new BridgeParamInfo[count];
  1740. // we might not receive all parameter data, so ensure range max is not 0
  1741. for (uint32_t i=0; i<count; ++i)
  1742. {
  1743. pData->param.ranges[i].def = 0.0f;
  1744. pData->param.ranges[i].min = 0.0f;
  1745. pData->param.ranges[i].max = 1.0f;
  1746. pData->param.ranges[i].step = 0.001f;
  1747. pData->param.ranges[i].stepSmall = 0.0001f;
  1748. pData->param.ranges[i].stepLarge = 0.1f;
  1749. }
  1750. }
  1751. } break;
  1752. case kPluginBridgeNonRtServerProgramCount: {
  1753. // uint/count
  1754. pData->prog.clear();
  1755. if (const uint32_t count = fShmNonRtServerControl.readUInt())
  1756. pData->prog.createNew(count);
  1757. } break;
  1758. case kPluginBridgeNonRtServerMidiProgramCount: {
  1759. // uint/count
  1760. pData->midiprog.clear();
  1761. if (const uint32_t count = fShmNonRtServerControl.readUInt())
  1762. pData->midiprog.createNew(count);
  1763. } break;
  1764. case kPluginBridgeNonRtServerPortName: {
  1765. // byte/type, uint/index, uint/size, str[] (name)
  1766. const uint8_t portType = fShmNonRtServerControl.readByte();
  1767. const uint32_t index = fShmNonRtServerControl.readUInt();
  1768. // name
  1769. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1770. char* const name = new char[nameSize+1];
  1771. carla_zeroChars(name, nameSize+1);
  1772. fShmNonRtServerControl.readCustomData(name, nameSize);
  1773. CARLA_SAFE_ASSERT_BREAK(portType > kPluginBridgePortNull && portType < kPluginBridgePortTypeCount);
  1774. switch (portType)
  1775. {
  1776. case kPluginBridgePortAudioInput:
  1777. CARLA_SAFE_ASSERT_BREAK(index < fInfo.aIns);
  1778. fInfo.aInNames[index] = name;
  1779. break;
  1780. case kPluginBridgePortAudioOutput:
  1781. CARLA_SAFE_ASSERT_BREAK(index < fInfo.aOuts);
  1782. fInfo.aOutNames[index] = name;
  1783. break;
  1784. }
  1785. } break;
  1786. case kPluginBridgeNonRtServerParameterData1: {
  1787. // uint/index, int/rindex, uint/type, uint/hints, int/cc
  1788. const uint32_t index = fShmNonRtServerControl.readUInt();
  1789. const int32_t rindex = fShmNonRtServerControl.readInt();
  1790. const uint32_t type = fShmNonRtServerControl.readUInt();
  1791. const uint32_t hints = fShmNonRtServerControl.readUInt();
  1792. const int16_t ctrl = fShmNonRtServerControl.readShort();
  1793. CARLA_SAFE_ASSERT_BREAK(ctrl >= CONTROL_INDEX_NONE && ctrl <= CONTROL_INDEX_MAX_ALLOWED);
  1794. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1795. if (index < pData->param.count)
  1796. {
  1797. pData->param.data[index].type = static_cast<ParameterType>(type);
  1798. pData->param.data[index].index = static_cast<int32_t>(index);
  1799. pData->param.data[index].rindex = rindex;
  1800. pData->param.data[index].hints = hints;
  1801. pData->param.data[index].mappedControlIndex = ctrl;
  1802. }
  1803. } break;
  1804. case kPluginBridgeNonRtServerParameterData2: {
  1805. // uint/index, uint/size, str[] (name), uint/size, str[] (unit)
  1806. const uint32_t index = fShmNonRtServerControl.readUInt();
  1807. // name
  1808. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1809. char name[nameSize+1];
  1810. carla_zeroChars(name, nameSize+1);
  1811. fShmNonRtServerControl.readCustomData(name, nameSize);
  1812. // symbol
  1813. const uint32_t symbolSize(fShmNonRtServerControl.readUInt());
  1814. char symbol[symbolSize+1];
  1815. carla_zeroChars(symbol, symbolSize+1);
  1816. fShmNonRtServerControl.readCustomData(symbol, symbolSize);
  1817. // unit
  1818. const uint32_t unitSize(fShmNonRtServerControl.readUInt());
  1819. char unit[unitSize+1];
  1820. carla_zeroChars(unit, unitSize+1);
  1821. fShmNonRtServerControl.readCustomData(unit, unitSize);
  1822. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1823. if (index < pData->param.count)
  1824. {
  1825. fParams[index].name = name;
  1826. fParams[index].symbol = symbol;
  1827. fParams[index].unit = unit;
  1828. }
  1829. } break;
  1830. case kPluginBridgeNonRtServerParameterRanges: {
  1831. // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
  1832. const uint32_t index = fShmNonRtServerControl.readUInt();
  1833. const float def = fShmNonRtServerControl.readFloat();
  1834. const float min = fShmNonRtServerControl.readFloat();
  1835. const float max = fShmNonRtServerControl.readFloat();
  1836. const float step = fShmNonRtServerControl.readFloat();
  1837. const float stepSmall = fShmNonRtServerControl.readFloat();
  1838. const float stepLarge = fShmNonRtServerControl.readFloat();
  1839. CARLA_SAFE_ASSERT_BREAK(min < max);
  1840. CARLA_SAFE_ASSERT_BREAK(def >= min);
  1841. CARLA_SAFE_ASSERT_BREAK(def <= max);
  1842. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1843. if (index < pData->param.count)
  1844. {
  1845. pData->param.ranges[index].def = def;
  1846. pData->param.ranges[index].min = min;
  1847. pData->param.ranges[index].max = max;
  1848. pData->param.ranges[index].step = step;
  1849. pData->param.ranges[index].stepSmall = stepSmall;
  1850. pData->param.ranges[index].stepLarge = stepLarge;
  1851. }
  1852. } break;
  1853. case kPluginBridgeNonRtServerParameterValue: {
  1854. // uint/index, float/value
  1855. const uint32_t index = fShmNonRtServerControl.readUInt();
  1856. const float value = fShmNonRtServerControl.readFloat();
  1857. if (index < pData->param.count)
  1858. {
  1859. const float fixedValue(pData->param.getFixedValue(index, value));
  1860. if (carla_isNotEqual(fParams[index].value, fixedValue))
  1861. {
  1862. fParams[index].value = fixedValue;
  1863. CarlaPlugin::setParameterValue(index, fixedValue, false, true, true);
  1864. }
  1865. }
  1866. } break;
  1867. case kPluginBridgeNonRtServerParameterValue2: {
  1868. // uint/index, float/value
  1869. const uint32_t index = fShmNonRtServerControl.readUInt();
  1870. const float value = fShmNonRtServerControl.readFloat();
  1871. if (index < pData->param.count)
  1872. {
  1873. const float fixedValue(pData->param.getFixedValue(index, value));
  1874. fParams[index].value = fixedValue;
  1875. }
  1876. } break;
  1877. case kPluginBridgeNonRtServerParameterTouch: {
  1878. // uint/index, bool/touch
  1879. const uint32_t index = fShmNonRtServerControl.readUInt();
  1880. const bool touch = fShmNonRtServerControl.readBool();
  1881. pData->engine->touchPluginParameter(pData->id, index, touch);
  1882. } break;
  1883. case kPluginBridgeNonRtServerDefaultValue: {
  1884. // uint/index, float/value
  1885. const uint32_t index = fShmNonRtServerControl.readUInt();
  1886. const float value = fShmNonRtServerControl.readFloat();
  1887. if (index < pData->param.count)
  1888. pData->param.ranges[index].def = value;
  1889. } break;
  1890. case kPluginBridgeNonRtServerCurrentProgram: {
  1891. // int/index
  1892. const int32_t index = fShmNonRtServerControl.readInt();
  1893. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1894. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1895. CarlaPlugin::setProgram(index, false, true, true);
  1896. } break;
  1897. case kPluginBridgeNonRtServerCurrentMidiProgram: {
  1898. // int/index
  1899. const int32_t index = fShmNonRtServerControl.readInt();
  1900. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1901. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1902. CarlaPlugin::setMidiProgram(index, false, true, true);
  1903. } break;
  1904. case kPluginBridgeNonRtServerProgramName: {
  1905. // uint/index, uint/size, str[] (name)
  1906. const uint32_t index = fShmNonRtServerControl.readUInt();
  1907. // name
  1908. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1909. char name[nameSize+1];
  1910. carla_zeroChars(name, nameSize+1);
  1911. fShmNonRtServerControl.readCustomData(name, nameSize);
  1912. CARLA_SAFE_ASSERT_INT2(index < pData->prog.count, index, pData->prog.count);
  1913. if (index < pData->prog.count)
  1914. {
  1915. if (pData->prog.names[index] != nullptr)
  1916. delete[] pData->prog.names[index];
  1917. pData->prog.names[index] = carla_strdup(name);
  1918. }
  1919. } break;
  1920. case kPluginBridgeNonRtServerMidiProgramData: {
  1921. // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  1922. const uint32_t index = fShmNonRtServerControl.readUInt();
  1923. const uint32_t bank = fShmNonRtServerControl.readUInt();
  1924. const uint32_t program = fShmNonRtServerControl.readUInt();
  1925. // name
  1926. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1927. char name[nameSize+1];
  1928. carla_zeroChars(name, nameSize+1);
  1929. fShmNonRtServerControl.readCustomData(name, nameSize);
  1930. CARLA_SAFE_ASSERT_INT2(index < pData->midiprog.count, index, pData->midiprog.count);
  1931. if (index < pData->midiprog.count)
  1932. {
  1933. if (pData->midiprog.data[index].name != nullptr)
  1934. delete[] pData->midiprog.data[index].name;
  1935. pData->midiprog.data[index].bank = bank;
  1936. pData->midiprog.data[index].program = program;
  1937. pData->midiprog.data[index].name = carla_strdup(name);
  1938. }
  1939. } break;
  1940. case kPluginBridgeNonRtServerSetCustomData: {
  1941. // uint/size, str[], uint/size, str[], uint/size, str[]
  1942. // type
  1943. const uint32_t typeSize(fShmNonRtServerControl.readUInt());
  1944. char type[typeSize+1];
  1945. carla_zeroChars(type, typeSize+1);
  1946. fShmNonRtServerControl.readCustomData(type, typeSize);
  1947. // key
  1948. const uint32_t keySize(fShmNonRtServerControl.readUInt());
  1949. char key[keySize+1];
  1950. carla_zeroChars(key, keySize+1);
  1951. fShmNonRtServerControl.readCustomData(key, keySize);
  1952. // value
  1953. const uint32_t valueSize(fShmNonRtServerControl.readUInt());
  1954. char value[valueSize+1];
  1955. carla_zeroChars(value, valueSize+1);
  1956. if (valueSize > 0)
  1957. fShmNonRtServerControl.readCustomData(value, valueSize);
  1958. CarlaPlugin::setCustomData(type, key, value, false);
  1959. } break;
  1960. case kPluginBridgeNonRtServerSetChunkDataFile: {
  1961. // uint/size, str[] (filename)
  1962. // chunkFilePath
  1963. const uint32_t chunkFilePathSize(fShmNonRtServerControl.readUInt());
  1964. char chunkFilePath[chunkFilePathSize+1];
  1965. carla_zeroChars(chunkFilePath, chunkFilePathSize+1);
  1966. fShmNonRtServerControl.readCustomData(chunkFilePath, chunkFilePathSize);
  1967. String realChunkFilePath(chunkFilePath);
  1968. #ifndef CARLA_OS_WIN
  1969. // Using Wine, fix temp dir
  1970. if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
  1971. {
  1972. const StringArray driveLetterSplit(StringArray::fromTokens(realChunkFilePath, ":/", ""));
  1973. carla_stdout("chunk save path BEFORE => %s", realChunkFilePath.toRawUTF8());
  1974. realChunkFilePath = fWinePrefix;
  1975. realChunkFilePath += "/drive_";
  1976. realChunkFilePath += driveLetterSplit[0].toLowerCase();
  1977. realChunkFilePath += driveLetterSplit[1];
  1978. realChunkFilePath = realChunkFilePath.replace("\\", "/");
  1979. carla_stdout("chunk save path AFTER => %s", realChunkFilePath.toRawUTF8());
  1980. }
  1981. #endif
  1982. File chunkFile(realChunkFilePath);
  1983. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  1984. fInfo.chunk = carla_getChunkFromBase64String(chunkFile.loadFileAsString().toRawUTF8());
  1985. chunkFile.deleteFile();
  1986. } break;
  1987. case kPluginBridgeNonRtServerSetLatency:
  1988. // uint
  1989. fLatency = fShmNonRtServerControl.readUInt();
  1990. #ifndef BUILD_BRIDGE
  1991. if (! fInitiated)
  1992. pData->latency.recreateBuffers(std::max(fInfo.aIns, fInfo.aOuts), fLatency);
  1993. #endif
  1994. break;
  1995. case kPluginBridgeNonRtServerSetParameterText: {
  1996. const int32_t index = fShmNonRtServerControl.readInt();
  1997. const uint32_t textSize(fShmNonRtServerControl.readUInt());
  1998. char text[textSize+1];
  1999. carla_zeroChars(text, textSize+1);
  2000. fShmNonRtServerControl.readCustomData(text, textSize);
  2001. fReceivingParamText.setReceivedData(index, text, textSize);
  2002. } break;
  2003. case kPluginBridgeNonRtServerReady:
  2004. fInitiated = true;
  2005. break;
  2006. case kPluginBridgeNonRtServerSaved:
  2007. fSaved = true;
  2008. break;
  2009. case kPluginBridgeNonRtServerUiClosed:
  2010. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2011. pData->transientTryCounter = 0;
  2012. #endif
  2013. pData->engine->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr);
  2014. break;
  2015. case kPluginBridgeNonRtServerError: {
  2016. // error
  2017. const uint32_t errorSize(fShmNonRtServerControl.readUInt());
  2018. char error[errorSize+1];
  2019. carla_zeroChars(error, errorSize+1);
  2020. fShmNonRtServerControl.readCustomData(error, errorSize);
  2021. if (fInitiated)
  2022. {
  2023. pData->engine->callback(true, true, ENGINE_CALLBACK_ERROR, pData->id, 0, 0, 0, 0.0f, error);
  2024. // just in case
  2025. pData->engine->setLastError(error);
  2026. fInitError = true;
  2027. }
  2028. else
  2029. {
  2030. pData->engine->setLastError(error);
  2031. fInitError = true;
  2032. fInitiated = true;
  2033. }
  2034. } break;
  2035. }
  2036. }
  2037. }
  2038. // -------------------------------------------------------------------
  2039. uintptr_t getUiBridgeProcessId() const noexcept override
  2040. {
  2041. return fBridgeThread.getProcessPID();
  2042. }
  2043. const void* getExtraStuff() const noexcept override
  2044. {
  2045. return fBridgeBinary.isNotEmpty() ? fBridgeBinary.buffer() : nullptr;
  2046. }
  2047. // -------------------------------------------------------------------
  2048. bool init(CarlaPluginPtr plugin,
  2049. const char* const filename,
  2050. const char* const name,
  2051. const char* const label,
  2052. const int64_t uniqueId,
  2053. const uint options,
  2054. const char* const binaryArchName,
  2055. const char* const bridgeBinary)
  2056. {
  2057. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  2058. // ---------------------------------------------------------------
  2059. // first checks
  2060. if (pData->client != nullptr)
  2061. {
  2062. pData->engine->setLastError("Plugin client is already registered");
  2063. return false;
  2064. }
  2065. if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
  2066. {
  2067. pData->engine->setLastError("null bridge binary");
  2068. return false;
  2069. }
  2070. // ---------------------------------------------------------------
  2071. // set info
  2072. if (name != nullptr && name[0] != '\0')
  2073. pData->name = pData->engine->getUniquePluginName(name);
  2074. if (filename != nullptr && filename[0] != '\0')
  2075. pData->filename = carla_strdup(filename);
  2076. else
  2077. pData->filename = carla_strdup("");
  2078. fUniqueId = uniqueId;
  2079. fBridgeBinary = bridgeBinary;
  2080. std::srand(static_cast<uint>(std::time(nullptr)));
  2081. // ---------------------------------------------------------------
  2082. // init sem/shm
  2083. if (! fShmAudioPool.initializeServer())
  2084. {
  2085. carla_stderr("Failed to initialize shared memory audio pool");
  2086. return false;
  2087. }
  2088. if (! fShmRtClientControl.initializeServer())
  2089. {
  2090. carla_stderr("Failed to initialize RT client control");
  2091. fShmAudioPool.clear();
  2092. return false;
  2093. }
  2094. if (! fShmNonRtClientControl.initializeServer())
  2095. {
  2096. carla_stderr("Failed to initialize Non-RT client control");
  2097. fShmRtClientControl.clear();
  2098. fShmAudioPool.clear();
  2099. return false;
  2100. }
  2101. if (! fShmNonRtServerControl.initializeServer())
  2102. {
  2103. carla_stderr("Failed to initialize Non-RT server control");
  2104. fShmNonRtClientControl.clear();
  2105. fShmRtClientControl.clear();
  2106. fShmAudioPool.clear();
  2107. return false;
  2108. }
  2109. #ifndef CARLA_OS_WIN
  2110. // ---------------------------------------------------------------
  2111. // set wine prefix
  2112. if (fBridgeBinary.contains(".exe", true))
  2113. {
  2114. const EngineOptions& engineOptions(pData->engine->getOptions());
  2115. if (engineOptions.wine.autoPrefix)
  2116. fWinePrefix = findWinePrefix(pData->filename);
  2117. if (fWinePrefix.isEmpty())
  2118. {
  2119. const char* const envWinePrefix(std::getenv("WINEPREFIX"));
  2120. if (envWinePrefix != nullptr && envWinePrefix[0] != '\0')
  2121. fWinePrefix = envWinePrefix;
  2122. else if (engineOptions.wine.fallbackPrefix != nullptr && engineOptions.wine.fallbackPrefix[0] != '\0')
  2123. fWinePrefix = engineOptions.wine.fallbackPrefix;
  2124. else
  2125. fWinePrefix = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine";
  2126. }
  2127. }
  2128. #endif
  2129. // ---------------------------------------------------------------
  2130. // init bridge thread
  2131. {
  2132. char shmIdsStr[6*4+1];
  2133. carla_zeroChars(shmIdsStr, 6*4+1);
  2134. std::strncpy(shmIdsStr+6*0, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  2135. std::strncpy(shmIdsStr+6*1, &fShmRtClientControl.filename[fShmRtClientControl.filename.length()-6], 6);
  2136. std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6);
  2137. std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6);
  2138. fBridgeThread.setData(
  2139. #ifndef CARLA_OS_WIN
  2140. fWinePrefix.toRawUTF8(),
  2141. #endif
  2142. binaryArchName, bridgeBinary, label, shmIdsStr);
  2143. }
  2144. if (! restartBridgeThread())
  2145. return false;
  2146. // ---------------------------------------------------------------
  2147. // register client
  2148. if (pData->name == nullptr)
  2149. {
  2150. if (label != nullptr && label[0] != '\0')
  2151. pData->name = pData->engine->getUniquePluginName(label);
  2152. else
  2153. pData->name = pData->engine->getUniquePluginName("unknown");
  2154. }
  2155. pData->client = pData->engine->addClient(plugin);
  2156. if (pData->client == nullptr || ! pData->client->isOk())
  2157. {
  2158. pData->engine->setLastError("Failed to register plugin client");
  2159. return false;
  2160. }
  2161. // ---------------------------------------------------------------
  2162. // set options
  2163. pData->options = 0x0;
  2164. if ((fInfo.optionsAvailable & PLUGIN_OPTION_FIXED_BUFFERS) == 0x0)
  2165. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  2166. else if (isPluginOptionEnabled(options, PLUGIN_OPTION_FIXED_BUFFERS))
  2167. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  2168. if (pData->engine->getOptions().forceStereo)
  2169. {
  2170. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  2171. }
  2172. else if (fInfo.optionsAvailable & PLUGIN_OPTION_FORCE_STEREO)
  2173. {
  2174. if (options & PLUGIN_OPTION_FORCE_STEREO)
  2175. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  2176. }
  2177. if (fInfo.optionsAvailable & PLUGIN_OPTION_USE_CHUNKS)
  2178. if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS))
  2179. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  2180. if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_CONTROL_CHANGES)
  2181. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
  2182. pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  2183. if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)
  2184. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
  2185. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  2186. if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)
  2187. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
  2188. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  2189. if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_PITCHBEND)
  2190. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
  2191. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  2192. if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  2193. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
  2194. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  2195. if (fInfo.optionsAvailable & PLUGIN_OPTION_SKIP_SENDING_NOTES)
  2196. if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
  2197. pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
  2198. if (fInfo.optionsAvailable & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
  2199. {
  2200. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES))
  2201. pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES;
  2202. }
  2203. else if (fInfo.optionsAvailable & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  2204. {
  2205. if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
  2206. pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  2207. }
  2208. // kPluginBridgeNonRtClientSetOptions was added in API 7
  2209. if (fBridgeVersion >= 7)
  2210. {
  2211. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  2212. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOptions);
  2213. fShmNonRtClientControl.writeUInt(pData->options);
  2214. fShmNonRtClientControl.commitWrite();
  2215. }
  2216. return true;
  2217. }
  2218. private:
  2219. const BinaryType fBinaryType;
  2220. const PluginType fPluginType;
  2221. uint fBridgeVersion;
  2222. bool fInitiated;
  2223. bool fInitError;
  2224. bool fSaved;
  2225. bool fTimedOut;
  2226. bool fTimedError;
  2227. uint fBufferSize;
  2228. uint fProcWaitTime;
  2229. CarlaString fBridgeBinary;
  2230. CarlaPluginBridgeThread fBridgeThread;
  2231. BridgeAudioPool fShmAudioPool;
  2232. BridgeRtClientControl fShmRtClientControl;
  2233. BridgeNonRtClientControl fShmNonRtClientControl;
  2234. BridgeNonRtServerControl fShmNonRtServerControl;
  2235. #ifndef CARLA_OS_WIN
  2236. String fWinePrefix;
  2237. #endif
  2238. class ReceivingParamText {
  2239. public:
  2240. ReceivingParamText() noexcept
  2241. : dataRecv(false),
  2242. dataOk(false),
  2243. index(-1),
  2244. strBuf(nullptr),
  2245. mutex() {}
  2246. bool isCurrentlyWaitingData() const noexcept
  2247. {
  2248. return index >= 0;
  2249. }
  2250. bool wasDataReceived(bool* const success) const noexcept
  2251. {
  2252. *success = dataOk;
  2253. return dataRecv;
  2254. }
  2255. void setTargetData(const int32_t i, char* const b) noexcept
  2256. {
  2257. const CarlaMutexLocker cml(mutex);
  2258. dataOk = false;
  2259. dataRecv = false;
  2260. index = i;
  2261. strBuf = b;
  2262. }
  2263. void setReceivedData(const int32_t i, const char* const b, const uint blen) noexcept
  2264. {
  2265. CarlaScopedValueSetter<bool> svs(dataRecv, false, true);
  2266. const CarlaMutexLocker cml(mutex);
  2267. // make backup and reset data
  2268. const int32_t indexCopy = index;
  2269. char* const strBufCopy = strBuf;
  2270. index = -1;
  2271. strBuf = nullptr;
  2272. CARLA_SAFE_ASSERT_RETURN(indexCopy == i,);
  2273. CARLA_SAFE_ASSERT_RETURN(strBufCopy != nullptr,);
  2274. std::strncpy(strBufCopy, b, std::min(blen, STR_MAX-1U));
  2275. dataOk = true;
  2276. }
  2277. private:
  2278. bool dataRecv;
  2279. bool dataOk;
  2280. int32_t index;
  2281. char* strBuf;
  2282. CarlaMutex mutex;
  2283. CARLA_DECLARE_NON_COPY_CLASS(ReceivingParamText)
  2284. } fReceivingParamText;
  2285. struct Info {
  2286. uint32_t aIns, aOuts;
  2287. uint32_t cvIns, cvOuts;
  2288. uint32_t mIns, mOuts;
  2289. PluginCategory category;
  2290. uint optionsAvailable;
  2291. CarlaString name;
  2292. CarlaString label;
  2293. CarlaString maker;
  2294. CarlaString copyright;
  2295. const char** aInNames;
  2296. const char** aOutNames;
  2297. const char** cvInNames;
  2298. const char** cvOutNames;
  2299. std::vector<uint8_t> chunk;
  2300. Info()
  2301. : aIns(0),
  2302. aOuts(0),
  2303. cvIns(0),
  2304. cvOuts(0),
  2305. mIns(0),
  2306. mOuts(0),
  2307. category(PLUGIN_CATEGORY_NONE),
  2308. optionsAvailable(0),
  2309. name(),
  2310. label(),
  2311. maker(),
  2312. copyright(),
  2313. aInNames(nullptr),
  2314. aOutNames(nullptr),
  2315. cvInNames(nullptr),
  2316. cvOutNames(nullptr),
  2317. chunk() {}
  2318. ~Info()
  2319. {
  2320. clear();
  2321. }
  2322. void clear()
  2323. {
  2324. if (aInNames != nullptr)
  2325. {
  2326. CARLA_SAFE_ASSERT_INT(aIns > 0, aIns);
  2327. for (uint32_t i=0; i<aIns; ++i)
  2328. delete[] aInNames[i];
  2329. delete[] aInNames;
  2330. aInNames = nullptr;
  2331. }
  2332. if (aOutNames != nullptr)
  2333. {
  2334. CARLA_SAFE_ASSERT_INT(aOuts > 0, aOuts);
  2335. for (uint32_t i=0; i<aOuts; ++i)
  2336. delete[] aOutNames[i];
  2337. delete[] aOutNames;
  2338. aOutNames = nullptr;
  2339. }
  2340. if (cvInNames != nullptr)
  2341. {
  2342. CARLA_SAFE_ASSERT_INT(cvIns > 0, cvIns);
  2343. for (uint32_t i=0; i<cvIns; ++i)
  2344. delete[] cvInNames[i];
  2345. delete[] cvInNames;
  2346. cvInNames = nullptr;
  2347. }
  2348. if (cvOutNames != nullptr)
  2349. {
  2350. CARLA_SAFE_ASSERT_INT(cvOuts > 0, cvOuts);
  2351. for (uint32_t i=0; i<cvOuts; ++i)
  2352. delete[] cvOutNames[i];
  2353. delete[] cvOutNames;
  2354. cvOutNames = nullptr;
  2355. }
  2356. aIns = aOuts = cvIns = cvOuts = 0;
  2357. }
  2358. CARLA_DECLARE_NON_COPY_STRUCT(Info)
  2359. } fInfo;
  2360. int64_t fUniqueId;
  2361. uint32_t fLatency;
  2362. BridgeParamInfo* fParams;
  2363. void handleProcessStopped() noexcept
  2364. {
  2365. const bool wasActive = pData->active;
  2366. pData->active = false;
  2367. if (wasActive)
  2368. {
  2369. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2370. pData->engine->callback(true, true,
  2371. ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED,
  2372. pData->id,
  2373. PARAMETER_ACTIVE,
  2374. 0, 0,
  2375. 0.0f,
  2376. nullptr);
  2377. #endif
  2378. }
  2379. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  2380. {
  2381. pData->engine->callback(true, true,
  2382. ENGINE_CALLBACK_UI_STATE_CHANGED,
  2383. pData->id,
  2384. 0,
  2385. 0, 0, 0.0f, nullptr);
  2386. }
  2387. }
  2388. void resizeAudioPool(const uint32_t bufferSize)
  2389. {
  2390. fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);
  2391. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
  2392. fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
  2393. fShmRtClientControl.commitWrite();
  2394. waitForClient("resize-pool", 5000);
  2395. }
  2396. void waitForClient(const char* const action, const uint msecs)
  2397. {
  2398. CARLA_SAFE_ASSERT_RETURN(! fTimedOut,);
  2399. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  2400. if (fShmRtClientControl.waitForClient(msecs))
  2401. return;
  2402. fTimedOut = true;
  2403. carla_stderr2("waitForClient(%s) timed out", action);
  2404. }
  2405. bool restartBridgeThread()
  2406. {
  2407. fInitiated = false;
  2408. fInitError = false;
  2409. fTimedError = false;
  2410. // reset memory
  2411. fShmRtClientControl.data->procFlags = 0;
  2412. carla_zeroStruct(fShmRtClientControl.data->timeInfo);
  2413. carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);
  2414. fShmRtClientControl.clearData();
  2415. fShmNonRtClientControl.clearData();
  2416. fShmNonRtServerControl.clearData();
  2417. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion);
  2418. fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT);
  2419. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
  2420. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
  2421. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));
  2422. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup);
  2423. fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
  2424. fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());
  2425. fShmNonRtClientControl.commitWrite();
  2426. if (fShmAudioPool.dataSize != 0)
  2427. {
  2428. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
  2429. fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
  2430. fShmRtClientControl.commitWrite();
  2431. }
  2432. else
  2433. {
  2434. // testing dummy message
  2435. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
  2436. fShmRtClientControl.commitWrite();
  2437. }
  2438. fBridgeThread.startThread();
  2439. const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;
  2440. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2441. const bool needsCancelableAction = ! pData->engine->isLoadingProject();
  2442. if (needsCancelableAction)
  2443. {
  2444. pData->engine->setActionCanceled(false);
  2445. pData->engine->callback(true, true,
  2446. ENGINE_CALLBACK_CANCELABLE_ACTION,
  2447. pData->id,
  2448. 1,
  2449. 0, 0, 0.0f,
  2450. "Loading plugin bridge");
  2451. }
  2452. #endif
  2453. for (;fBridgeThread.isThreadRunning();)
  2454. {
  2455. pData->engine->callback(true, true, ENGINE_CALLBACK_IDLE, 0, 0, 0, 0, 0.0f, nullptr);
  2456. if (needsEngineIdle)
  2457. pData->engine->idle();
  2458. idle();
  2459. if (fInitiated)
  2460. break;
  2461. if (pData->engine->isAboutToClose() || pData->engine->wasActionCanceled())
  2462. break;
  2463. carla_msleep(5);
  2464. }
  2465. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2466. if (needsCancelableAction)
  2467. {
  2468. pData->engine->callback(true, true,
  2469. ENGINE_CALLBACK_CANCELABLE_ACTION,
  2470. pData->id,
  2471. 0,
  2472. 0, 0, 0.0f,
  2473. "Loading JACK application");
  2474. }
  2475. #endif
  2476. if (fInitError || ! fInitiated)
  2477. {
  2478. fBridgeThread.stopThread(6000);
  2479. if (! fInitError)
  2480. pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n"
  2481. "(or the plugin crashed on initialization?)");
  2482. return false;
  2483. }
  2484. if (const size_t dataSize = fInfo.chunk.size())
  2485. {
  2486. #ifdef CARLA_PROPER_CPP11_SUPPORT
  2487. void* data = fInfo.chunk.data();
  2488. #else
  2489. void* data = &fInfo.chunk.front();
  2490. #endif
  2491. CarlaString dataBase64(CarlaString::asBase64(data, dataSize));
  2492. CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0, true);
  2493. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  2494. filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
  2495. filePath += fShmAudioPool.getFilenameSuffix();
  2496. if (File(filePath).replaceWithText(dataBase64.buffer()))
  2497. {
  2498. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  2499. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  2500. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile);
  2501. fShmNonRtClientControl.writeUInt(ulength);
  2502. fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength);
  2503. fShmNonRtClientControl.commitWrite();
  2504. }
  2505. }
  2506. return true;
  2507. }
  2508. void _setUiTitleFromName()
  2509. {
  2510. CarlaString uiName(pData->name);
  2511. uiName += " (GUI)";
  2512. const uint32_t size = static_cast<uint32_t>(uiName.length());
  2513. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  2514. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetWindowTitle);
  2515. fShmNonRtClientControl.writeUInt(size);
  2516. fShmNonRtClientControl.writeCustomData(uiName.buffer(), size);
  2517. fShmNonRtClientControl.commitWrite();
  2518. }
  2519. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge)
  2520. };
  2521. CARLA_BACKEND_END_NAMESPACE
  2522. // ---------------------------------------------------------------------------------------------------------------------
  2523. CARLA_BACKEND_START_NAMESPACE
  2524. CarlaPluginPtr CarlaPlugin::newBridge(const Initializer& init,
  2525. const BinaryType btype,
  2526. const PluginType ptype,
  2527. const char* const binaryArchName,
  2528. const char* bridgeBinary)
  2529. {
  2530. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\", \"%s\")",
  2531. init.engine, init.filename, init.name, init.label,
  2532. BinaryType2Str(btype), PluginType2Str(ptype), binaryArchName, bridgeBinary);
  2533. if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
  2534. {
  2535. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  2536. return nullptr;
  2537. }
  2538. #ifndef CARLA_OS_WIN
  2539. // FIXME: somewhere, somehow, we end up with double slashes, wine doesn't like that.
  2540. if (std::strncmp(bridgeBinary, "//", 2) == 0)
  2541. ++bridgeBinary;
  2542. #endif
  2543. std::shared_ptr<CarlaPluginBridge> plugin(new CarlaPluginBridge(init.engine, init.id, btype, ptype));
  2544. if (! plugin->init(plugin, init.filename, init.name, init.label, init.uniqueId, init.options, binaryArchName, bridgeBinary))
  2545. return nullptr;
  2546. return plugin;
  2547. }
  2548. CARLA_BACKEND_END_NAMESPACE
  2549. // ---------------------------------------------------------------------------------------------------------------------
  2550. #ifndef BUILD_BRIDGE
  2551. # include "CarlaBridgeUtils.cpp"
  2552. #endif
  2553. // ---------------------------------------------------------------------------------------------------------------------