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

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