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

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
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
9 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
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
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
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471
  1. /*
  2. * Carla Plugin Bridge
  3. * Copyright (C) 2011-2017 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 "CarlaShmUtils.hpp"
  25. #include "CarlaThread.hpp"
  26. #include "jackbridge/JackBridge.hpp"
  27. #include <ctime>
  28. #include "water/files/File.h"
  29. #include "water/misc/Time.h"
  30. #include "water/threads/ChildProcess.h"
  31. // ---------------------------------------------------------------------------------------------------------------------
  32. using water::ChildProcess;
  33. using water::File;
  34. using water::String;
  35. using water::StringArray;
  36. using water::Time;
  37. CARLA_BACKEND_START_NAMESPACE
  38. // ---------------------------------------------------------------------------------------------------------------------
  39. // Fallback data
  40. static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
  41. // ---------------------------------------------------------------------------------------------------------------------
  42. static String findWinePrefix(const String filename, const int recursionLimit = 10)
  43. {
  44. if (recursionLimit == 0 || filename.length() < 5 || ! filename.contains("/"))
  45. return "";
  46. const String path(filename.upToLastOccurrenceOf("/", false, false));
  47. if (File(path + "/dosdevices").isDirectory())
  48. return path;
  49. return findWinePrefix(path, recursionLimit-1);
  50. }
  51. // ---------------------------------------------------------------------------------------------------------------------
  52. struct BridgeParamInfo {
  53. float value;
  54. CarlaString name;
  55. CarlaString symbol;
  56. CarlaString unit;
  57. BridgeParamInfo() noexcept
  58. : value(0.0f),
  59. name(),
  60. symbol(),
  61. unit() {}
  62. CARLA_DECLARE_NON_COPY_STRUCT(BridgeParamInfo)
  63. };
  64. // ---------------------------------------------------------------------------------------------------------------------
  65. class CarlaPluginBridgeThread : public CarlaThread
  66. {
  67. public:
  68. CarlaPluginBridgeThread(CarlaEngine* const engine, CarlaPlugin* const plugin) noexcept
  69. : CarlaThread("CarlaPluginBridgeThread"),
  70. kEngine(engine),
  71. kPlugin(plugin),
  72. fBinary(),
  73. fLabel(),
  74. fShmIds(),
  75. fWinePrefix(),
  76. fProcess() {}
  77. void setData(const char* const winePrefix,
  78. const char* const binary,
  79. const char* const label,
  80. const char* const shmIds) noexcept
  81. {
  82. CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',);
  83. CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',);
  84. CARLA_SAFE_ASSERT(! isThreadRunning());
  85. fWinePrefix = winePrefix;
  86. fBinary = binary;
  87. fShmIds = shmIds;
  88. if (label != nullptr)
  89. fLabel = label;
  90. if (fLabel.isEmpty())
  91. fLabel = "\"\"";
  92. }
  93. uintptr_t getProcessPID() const noexcept
  94. {
  95. CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0);
  96. return (uintptr_t)fProcess->getPID();
  97. }
  98. protected:
  99. void run()
  100. {
  101. if (fProcess == nullptr)
  102. {
  103. fProcess = new ChildProcess();
  104. }
  105. else if (fProcess->isRunning())
  106. {
  107. carla_stderr("CarlaPluginBridgeThread::run() - already running");
  108. }
  109. char strBuf[STR_MAX+1];
  110. strBuf[STR_MAX] = '\0';
  111. const EngineOptions& options(kEngine->getOptions());
  112. String name(kPlugin->getName());
  113. String filename(kPlugin->getFilename());
  114. if (name.isEmpty())
  115. name = "(none)";
  116. if (filename.isEmpty())
  117. filename = "\"\"";
  118. StringArray arguments;
  119. #ifndef CARLA_OS_WIN
  120. // start with "wine" if needed
  121. if (fBinary.endsWithIgnoreCase(".exe"))
  122. {
  123. if (options.wine.executable != nullptr && options.wine.executable[0] != '\0')
  124. arguments.add(options.wine.executable);
  125. else
  126. arguments.add("wine");
  127. }
  128. #endif
  129. // binary
  130. arguments.add(fBinary);
  131. // plugin type
  132. arguments.add(getPluginTypeAsString(kPlugin->getType()));
  133. // filename
  134. arguments.add(filename);
  135. // label
  136. arguments.add(fLabel);
  137. // uniqueId
  138. arguments.add(String(static_cast<water::int64>(kPlugin->getUniqueId())));
  139. bool started;
  140. {
  141. const ScopedEngineEnvironmentLocker _seel(kEngine);
  142. #ifdef CARLA_OS_LINUX
  143. const ScopedEnvVar sev1("LD_LIBRARY_PATH", nullptr);
  144. const ScopedEnvVar sev2("LD_PRELOAD", nullptr);
  145. #endif
  146. carla_setenv("ENGINE_OPTION_FORCE_STEREO", bool2str(options.forceStereo));
  147. carla_setenv("ENGINE_OPTION_PREFER_PLUGIN_BRIDGES", bool2str(options.preferPluginBridges));
  148. carla_setenv("ENGINE_OPTION_PREFER_UI_BRIDGES", bool2str(options.preferUiBridges));
  149. carla_setenv("ENGINE_OPTION_UIS_ALWAYS_ON_TOP", bool2str(options.uisAlwaysOnTop));
  150. std::snprintf(strBuf, STR_MAX, "%u", options.maxParameters);
  151. carla_setenv("ENGINE_OPTION_MAX_PARAMETERS", strBuf);
  152. std::snprintf(strBuf, STR_MAX, "%u", options.uiBridgesTimeout);
  153. carla_setenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT",strBuf);
  154. if (options.pathLADSPA != nullptr)
  155. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA", options.pathLADSPA);
  156. else
  157. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA", "");
  158. if (options.pathDSSI != nullptr)
  159. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_DSSI", options.pathDSSI);
  160. else
  161. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_DSSI", "");
  162. if (options.pathLV2 != nullptr)
  163. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LV2", options.pathLV2);
  164. else
  165. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_LV2", "");
  166. if (options.pathVST2 != nullptr)
  167. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST2", options.pathVST2);
  168. else
  169. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_VST2", "");
  170. if (options.pathGIG != nullptr)
  171. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_GIG", options.pathGIG);
  172. else
  173. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_GIG", "");
  174. if (options.pathSF2 != nullptr)
  175. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SF2", options.pathSF2);
  176. else
  177. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SF2", "");
  178. if (options.pathSFZ != nullptr)
  179. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SFZ", options.pathSFZ);
  180. else
  181. carla_setenv("ENGINE_OPTION_PLUGIN_PATH_SFZ", "");
  182. if (options.binaryDir != nullptr)
  183. carla_setenv("ENGINE_OPTION_PATH_BINARIES", options.binaryDir);
  184. else
  185. carla_setenv("ENGINE_OPTION_PATH_BINARIES", "");
  186. if (options.resourceDir != nullptr)
  187. carla_setenv("ENGINE_OPTION_PATH_RESOURCES", options.resourceDir);
  188. else
  189. carla_setenv("ENGINE_OPTION_PATH_RESOURCES", "");
  190. carla_setenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR", bool2str(options.preventBadBehaviour));
  191. std::snprintf(strBuf, STR_MAX, P_UINTPTR, options.frontendWinId);
  192. carla_setenv("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf);
  193. carla_setenv("ENGINE_BRIDGE_SHM_IDS", fShmIds.toRawUTF8());
  194. #ifndef CARLA_OS_WIN
  195. if (fWinePrefix.isNotEmpty())
  196. {
  197. carla_setenv("WINEDEBUG", "-all");
  198. carla_setenv("WINEPREFIX", fWinePrefix.toRawUTF8());
  199. if (options.wine.rtPrio)
  200. {
  201. carla_setenv("STAGING_SHARED_MEMORY", "1");
  202. std::snprintf(strBuf, STR_MAX, "%i", options.wine.baseRtPrio);
  203. carla_setenv("STAGING_RT_PRIORITY_BASE", strBuf);
  204. carla_setenv("WINE_RT", strBuf);
  205. std::snprintf(strBuf, STR_MAX, "%i", options.wine.serverRtPrio);
  206. carla_setenv("STAGING_RT_PRIORITY_SERVER", strBuf);
  207. carla_setenv("WINE_SVR_RT", strBuf);
  208. }
  209. else
  210. {
  211. carla_unsetenv("STAGING_SHARED_MEMORY");
  212. carla_unsetenv("STAGING_RT_PRIORITY_BASE");
  213. carla_unsetenv("STAGING_RT_PRIORITY_SERVER");
  214. carla_unsetenv("WINE_RT");
  215. carla_unsetenv("WINE_SVR_RT");
  216. }
  217. carla_stdout("Using WINEPREFIX '%s'", fWinePrefix.toRawUTF8());
  218. }
  219. #endif
  220. carla_stdout("starting plugin bridge, command is:\n%s \"%s\" \"%s\" \"%s\" " P_INT64,
  221. fBinary.toRawUTF8(), getPluginTypeAsString(kPlugin->getType()), filename.toRawUTF8(), fLabel.toRawUTF8(), kPlugin->getUniqueId());
  222. started = fProcess->start(arguments);
  223. }
  224. if (! started)
  225. {
  226. carla_stdout("failed!");
  227. fProcess = nullptr;
  228. return;
  229. }
  230. for (; fProcess->isRunning() && ! shouldThreadExit();)
  231. carla_sleep(1);
  232. // we only get here if bridge crashed or thread asked to exit
  233. if (fProcess->isRunning() && shouldThreadExit())
  234. {
  235. fProcess->waitForProcessToFinish(2000);
  236. if (fProcess->isRunning())
  237. {
  238. carla_stdout("CarlaPluginBridgeThread::run() - bridge refused to close, force kill now");
  239. fProcess->kill();
  240. }
  241. else
  242. {
  243. carla_stdout("CarlaPluginBridgeThread::run() - bridge auto-closed successfully");
  244. }
  245. }
  246. else
  247. {
  248. // forced quit, may have crashed
  249. if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/)
  250. {
  251. carla_stderr("CarlaPluginBridgeThread::run() - bridge crashed");
  252. CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n"
  253. "Saving now will lose its current settings.\n"
  254. "Please remove this plugin, and not rely on it from this point.");
  255. kEngine->callback(CarlaBackend::ENGINE_CALLBACK_ERROR, kPlugin->getId(), 0, 0, 0.0f, errorString);
  256. }
  257. }
  258. fProcess = nullptr;
  259. }
  260. private:
  261. CarlaEngine* const kEngine;
  262. CarlaPlugin* const kPlugin;
  263. String fBinary;
  264. String fLabel;
  265. String fShmIds;
  266. String fWinePrefix;
  267. ScopedPointer<ChildProcess> fProcess;
  268. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridgeThread)
  269. };
  270. // ---------------------------------------------------------------------------------------------------------------------
  271. class CarlaPluginBridge : public CarlaPlugin
  272. {
  273. public:
  274. CarlaPluginBridge(CarlaEngine* const engine, const uint id, const BinaryType btype, const PluginType ptype)
  275. : CarlaPlugin(engine, id),
  276. fBinaryType(btype),
  277. fPluginType(ptype),
  278. fInitiated(false),
  279. fInitError(false),
  280. fSaved(true),
  281. fTimedOut(false),
  282. fTimedError(false),
  283. fProcWaitTime(0),
  284. fLastPongTime(-1),
  285. fBridgeBinary(),
  286. fBridgeThread(engine, this),
  287. fShmAudioPool(),
  288. fShmRtClientControl(),
  289. fShmNonRtClientControl(),
  290. fShmNonRtServerControl(),
  291. fWinePrefix(),
  292. fInfo(),
  293. fUniqueId(0),
  294. fLatency(0),
  295. fParams(nullptr)
  296. {
  297. carla_debug("CarlaPluginBridge::CarlaPluginBridge(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  298. pData->hints |= PLUGIN_IS_BRIDGE;
  299. }
  300. ~CarlaPluginBridge() override
  301. {
  302. carla_debug("CarlaPluginBridge::~CarlaPluginBridge()");
  303. // close UI
  304. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  305. pData->transientTryCounter = 0;
  306. pData->singleMutex.lock();
  307. pData->masterMutex.lock();
  308. if (pData->client != nullptr && pData->client->isActive())
  309. pData->client->deactivate();
  310. if (pData->active)
  311. {
  312. deactivate();
  313. pData->active = false;
  314. }
  315. if (fBridgeThread.isThreadRunning())
  316. {
  317. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientQuit);
  318. fShmNonRtClientControl.commitWrite();
  319. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientQuit);
  320. fShmRtClientControl.commitWrite();
  321. if (! fTimedOut)
  322. waitForClient("stopping", 3000);
  323. }
  324. fBridgeThread.stopThread(3000);
  325. fShmNonRtServerControl.clear();
  326. fShmNonRtClientControl.clear();
  327. fShmRtClientControl.clear();
  328. fShmAudioPool.clear();
  329. clearBuffers();
  330. fInfo.chunk.clear();
  331. }
  332. // -------------------------------------------------------------------
  333. // Information (base)
  334. BinaryType getBinaryType() const noexcept override
  335. {
  336. return fBinaryType;
  337. }
  338. PluginType getType() const noexcept override
  339. {
  340. return fPluginType;
  341. }
  342. PluginCategory getCategory() const noexcept override
  343. {
  344. return fInfo.category;
  345. }
  346. int64_t getUniqueId() const noexcept override
  347. {
  348. return fUniqueId;
  349. }
  350. uint32_t getLatencyInFrames() const noexcept override
  351. {
  352. return fLatency;
  353. }
  354. // -------------------------------------------------------------------
  355. // Information (count)
  356. uint32_t getMidiInCount() const noexcept override
  357. {
  358. return fInfo.mIns;
  359. }
  360. uint32_t getMidiOutCount() const noexcept override
  361. {
  362. return fInfo.mOuts;
  363. }
  364. // -------------------------------------------------------------------
  365. // Information (current data)
  366. // TODO - missing getCustomData
  367. std::size_t getChunkData(void** const dataPtr) noexcept override
  368. {
  369. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  370. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  371. waitForSaved();
  372. CARLA_SAFE_ASSERT_RETURN(fInfo.chunk.size() > 0, 0);
  373. #ifdef CARLA_PROPER_CPP11_SUPPORT
  374. *dataPtr = fInfo.chunk.data();
  375. #else
  376. *dataPtr = &fInfo.chunk.front();
  377. #endif
  378. return fInfo.chunk.size();
  379. }
  380. // -------------------------------------------------------------------
  381. // Information (per-plugin data)
  382. uint getOptionsAvailable() const noexcept override
  383. {
  384. return fInfo.optionsAvailable;
  385. }
  386. float getParameterValue(const uint32_t parameterId) const noexcept override
  387. {
  388. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  389. return fParams[parameterId].value;
  390. }
  391. void getLabel(char* const strBuf) const noexcept override
  392. {
  393. std::strncpy(strBuf, fInfo.label, STR_MAX);
  394. }
  395. void getMaker(char* const strBuf) const noexcept override
  396. {
  397. std::strncpy(strBuf, fInfo.maker, STR_MAX);
  398. }
  399. void getCopyright(char* const strBuf) const noexcept override
  400. {
  401. std::strncpy(strBuf, fInfo.copyright, STR_MAX);
  402. }
  403. void getRealName(char* const strBuf) const noexcept override
  404. {
  405. std::strncpy(strBuf, fInfo.name, STR_MAX);
  406. }
  407. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  408. {
  409. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf));
  410. std::strncpy(strBuf, fParams[parameterId].name.buffer(), STR_MAX);
  411. }
  412. void getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
  413. {
  414. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf));
  415. std::strncpy(strBuf, fParams[parameterId].symbol.buffer(), STR_MAX);
  416. }
  417. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  418. {
  419. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, nullStrBuf(strBuf));
  420. std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX);
  421. }
  422. // -------------------------------------------------------------------
  423. // Set data (state)
  424. void prepareForSave() noexcept override
  425. {
  426. fSaved = false;
  427. {
  428. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  429. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPrepareForSave);
  430. fShmNonRtClientControl.commitWrite();
  431. }
  432. }
  433. void waitForSaved()
  434. {
  435. if (fSaved)
  436. return;
  437. // TODO: only wait 1 minute for NI plugins
  438. const uint32_t timeoutEnd(Time::getMillisecondCounter() + 60*1000); // 60 secs, 1 minute
  439. const bool needsEngineIdle(pData->engine->getType() != kEngineTypePlugin);
  440. for (; Time::getMillisecondCounter() < timeoutEnd && fBridgeThread.isThreadRunning();)
  441. {
  442. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  443. if (needsEngineIdle)
  444. pData->engine->idle();
  445. if (fSaved)
  446. break;
  447. carla_msleep(20);
  448. }
  449. if (! fSaved)
  450. carla_stderr("CarlaPluginBridge::waitForSaved() - Timeout while requesting save state");
  451. }
  452. // -------------------------------------------------------------------
  453. // Set data (internal stuff)
  454. void setOption(const uint option, const bool yesNo, const bool sendCallback) override
  455. {
  456. {
  457. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  458. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOption);
  459. fShmNonRtClientControl.writeUInt(option);
  460. fShmNonRtClientControl.writeBool(yesNo);
  461. fShmNonRtClientControl.commitWrite();
  462. }
  463. CarlaPlugin::setOption(option, yesNo, sendCallback);
  464. }
  465. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  466. {
  467. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  468. {
  469. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  470. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCtrlChannel);
  471. fShmNonRtClientControl.writeShort(channel);
  472. fShmNonRtClientControl.commitWrite();
  473. }
  474. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  475. }
  476. // -------------------------------------------------------------------
  477. // Set data (plugin-specific stuff)
  478. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  479. {
  480. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  481. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  482. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  483. fParams[parameterId].value = fixedValue;
  484. {
  485. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  486. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterValue);
  487. fShmNonRtClientControl.writeUInt(parameterId);
  488. fShmNonRtClientControl.writeFloat(value);
  489. fShmNonRtClientControl.commitWrite();
  490. fShmNonRtClientControl.waitIfDataIsReachingLimit();
  491. }
  492. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  493. }
  494. void setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  495. {
  496. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  497. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  498. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  499. {
  500. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  501. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiChannel);
  502. fShmNonRtClientControl.writeUInt(parameterId);
  503. fShmNonRtClientControl.writeByte(channel);
  504. fShmNonRtClientControl.commitWrite();
  505. }
  506. CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback);
  507. }
  508. void setParameterMidiCC(const uint32_t parameterId, const int16_t cc, const bool sendOsc, const bool sendCallback) noexcept override
  509. {
  510. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  511. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  512. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc < MAX_MIDI_CONTROL,);
  513. {
  514. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  515. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetParameterMidiCC);
  516. fShmNonRtClientControl.writeUInt(parameterId);
  517. fShmNonRtClientControl.writeShort(cc);
  518. fShmNonRtClientControl.commitWrite();
  519. }
  520. CarlaPlugin::setParameterMidiCC(parameterId, cc, sendOsc, sendCallback);
  521. }
  522. void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  523. {
  524. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  525. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  526. {
  527. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  528. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetProgram);
  529. fShmNonRtClientControl.writeInt(index);
  530. fShmNonRtClientControl.commitWrite();
  531. }
  532. CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback);
  533. }
  534. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  535. {
  536. CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,); // never call this from RT
  537. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  538. {
  539. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  540. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetMidiProgram);
  541. fShmNonRtClientControl.writeInt(index);
  542. fShmNonRtClientControl.commitWrite();
  543. }
  544. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  545. }
  546. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  547. {
  548. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  549. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  550. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  551. if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
  552. return CarlaPlugin::setCustomData(type, key, value, sendGui);
  553. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(key, "__CarlaPingOnOff__") == 0)
  554. {
  555. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  556. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPingOnOff);
  557. fShmNonRtClientControl.writeBool(std::strcmp(value, "true") == 0);
  558. fShmNonRtClientControl.commitWrite();
  559. return;
  560. }
  561. const uint32_t typeLen(static_cast<uint32_t>(std::strlen(type)));
  562. const uint32_t keyLen(static_cast<uint32_t>(std::strlen(key)));
  563. const uint32_t valueLen(static_cast<uint32_t>(std::strlen(value)));
  564. {
  565. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  566. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCustomData);
  567. fShmNonRtClientControl.writeUInt(typeLen);
  568. fShmNonRtClientControl.writeCustomData(type, typeLen);
  569. fShmNonRtClientControl.writeUInt(keyLen);
  570. fShmNonRtClientControl.writeCustomData(key, keyLen);
  571. fShmNonRtClientControl.writeUInt(valueLen);
  572. fShmNonRtClientControl.writeCustomData(value, valueLen);
  573. fShmNonRtClientControl.commitWrite();
  574. }
  575. CarlaPlugin::setCustomData(type, key, value, sendGui);
  576. }
  577. void setChunkData(const void* const data, const std::size_t dataSize) override
  578. {
  579. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  580. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  581. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  582. CarlaString dataBase64(CarlaString::asBase64(data, dataSize));
  583. CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0,);
  584. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  585. filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
  586. filePath += fShmAudioPool.filename.buffer() + 18;
  587. if (File(filePath).replaceWithText(dataBase64.buffer()))
  588. {
  589. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  590. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  591. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile);
  592. fShmNonRtClientControl.writeUInt(ulength);
  593. fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength);
  594. fShmNonRtClientControl.commitWrite();
  595. }
  596. // save data internally as well
  597. fInfo.chunk.resize(dataSize);
  598. #ifdef CARLA_PROPER_CPP11_SUPPORT
  599. std::memcpy(fInfo.chunk.data(), data, dataSize);
  600. #else
  601. std::memcpy(&fInfo.chunk.front(), data, dataSize);
  602. #endif
  603. }
  604. // -------------------------------------------------------------------
  605. // Set ui stuff
  606. void showCustomUI(const bool yesNo) override
  607. {
  608. {
  609. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  610. fShmNonRtClientControl.writeOpcode(yesNo ? kPluginBridgeNonRtClientShowUI : kPluginBridgeNonRtClientHideUI);
  611. fShmNonRtClientControl.commitWrite();
  612. }
  613. #ifndef BUILD_BRIDGE
  614. if (yesNo)
  615. {
  616. pData->tryTransient();
  617. }
  618. else
  619. {
  620. pData->transientTryCounter = 0;
  621. }
  622. #endif
  623. }
  624. void idle() override
  625. {
  626. if (fBridgeThread.isThreadRunning())
  627. {
  628. if (fInitiated && fTimedOut && pData->active)
  629. setActive(false, true, true);
  630. {
  631. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  632. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPing);
  633. fShmNonRtClientControl.commitWrite();
  634. }
  635. try {
  636. handleNonRtData();
  637. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  638. }
  639. else if (fInitiated)
  640. {
  641. fTimedOut = true;
  642. fTimedError = true;
  643. fInitiated = false;
  644. pData->engine->callback(ENGINE_CALLBACK_PLUGIN_UNAVAILABLE, pData->id, 0, 0, 0.0f,
  645. "Plugin bridge has been stopped or crashed");
  646. }
  647. CarlaPlugin::idle();
  648. }
  649. // -------------------------------------------------------------------
  650. // Plugin state
  651. void reload() override
  652. {
  653. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  654. carla_debug("CarlaPluginBridge::reload() - start");
  655. const EngineProcessMode processMode(pData->engine->getProccessMode());
  656. // Safely disable plugin for reload
  657. const ScopedDisabler sd(this);
  658. // cleanup of previous data
  659. pData->audioIn.clear();
  660. pData->audioOut.clear();
  661. pData->cvIn.clear();
  662. pData->cvOut.clear();
  663. pData->event.clear();
  664. bool needsCtrlIn, needsCtrlOut;
  665. needsCtrlIn = needsCtrlOut = false;
  666. if (fInfo.aIns > 0)
  667. {
  668. pData->audioIn.createNew(fInfo.aIns);
  669. }
  670. if (fInfo.aOuts > 0)
  671. {
  672. pData->audioOut.createNew(fInfo.aOuts);
  673. needsCtrlIn = true;
  674. }
  675. if (fInfo.cvIns > 0)
  676. {
  677. pData->cvIn.createNew(fInfo.cvIns);
  678. }
  679. if (fInfo.cvOuts > 0)
  680. {
  681. pData->cvOut.createNew(fInfo.cvOuts);
  682. }
  683. if (fInfo.mIns > 0)
  684. needsCtrlIn = true;
  685. if (fInfo.mOuts > 0)
  686. needsCtrlOut = true;
  687. const uint portNameSize(pData->engine->getMaxPortNameSize());
  688. CarlaString portName;
  689. // Audio Ins
  690. for (uint32_t j=0; j < fInfo.aIns; ++j)
  691. {
  692. portName.clear();
  693. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  694. {
  695. portName = pData->name;
  696. portName += ":";
  697. }
  698. if (fInfo.aInNames != nullptr && fInfo.aInNames[j] != nullptr)
  699. {
  700. portName += fInfo.aInNames[j];
  701. }
  702. else if (fInfo.aIns > 1)
  703. {
  704. portName += "input_";
  705. portName += CarlaString(j+1);
  706. }
  707. else
  708. portName += "input";
  709. portName.truncate(portNameSize);
  710. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
  711. pData->audioIn.ports[j].rindex = j;
  712. }
  713. // Audio Outs
  714. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  715. {
  716. portName.clear();
  717. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  718. {
  719. portName = pData->name;
  720. portName += ":";
  721. }
  722. if (fInfo.aOutNames != nullptr && fInfo.aOutNames[j] != nullptr)
  723. {
  724. portName += fInfo.aOutNames[j];
  725. }
  726. else if (fInfo.aOuts > 1)
  727. {
  728. portName += "output_";
  729. portName += CarlaString(j+1);
  730. }
  731. else
  732. portName += "output";
  733. portName.truncate(portNameSize);
  734. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
  735. pData->audioOut.ports[j].rindex = j;
  736. }
  737. // TODO - MIDI
  738. // TODO - CV
  739. if (needsCtrlIn)
  740. {
  741. portName.clear();
  742. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  743. {
  744. portName = pData->name;
  745. portName += ":";
  746. }
  747. portName += "event-in";
  748. portName.truncate(portNameSize);
  749. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
  750. }
  751. if (needsCtrlOut)
  752. {
  753. portName.clear();
  754. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  755. {
  756. portName = pData->name;
  757. portName += ":";
  758. }
  759. portName += "event-out";
  760. portName.truncate(portNameSize);
  761. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
  762. }
  763. // extra plugin hints
  764. pData->extraHints = 0x0;
  765. if (fInfo.mIns > 0)
  766. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  767. if (fInfo.mOuts > 0)
  768. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  769. if (fInfo.aIns <= 2 && fInfo.aOuts <= 2 && (fInfo.aIns == fInfo.aOuts || fInfo.aIns == 0 || fInfo.aOuts == 0))
  770. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  771. bufferSizeChanged(pData->engine->getBufferSize());
  772. reloadPrograms(true);
  773. carla_debug("CarlaPluginBridge::reload() - end");
  774. }
  775. // -------------------------------------------------------------------
  776. // Plugin processing
  777. void activate() noexcept override
  778. {
  779. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  780. {
  781. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  782. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate);
  783. fShmNonRtClientControl.commitWrite();
  784. }
  785. fTimedOut = false;
  786. try {
  787. waitForClient("activate", 2000);
  788. } CARLA_SAFE_EXCEPTION("activate - waitForClient");
  789. }
  790. void deactivate() noexcept override
  791. {
  792. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  793. {
  794. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  795. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate);
  796. fShmNonRtClientControl.commitWrite();
  797. }
  798. fTimedOut = false;
  799. try {
  800. waitForClient("deactivate", 2000);
  801. } CARLA_SAFE_EXCEPTION("deactivate - waitForClient");
  802. }
  803. void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
  804. {
  805. // --------------------------------------------------------------------------------------------------------
  806. // Check if active
  807. if (fTimedOut || fTimedError || ! pData->active)
  808. {
  809. // disable any output sound
  810. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  811. carla_zeroFloats(audioOut[i], frames);
  812. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  813. carla_zeroFloats(cvOut[i], frames);
  814. return;
  815. }
  816. // --------------------------------------------------------------------------------------------------------
  817. // Check if needs reset
  818. if (pData->needsReset)
  819. {
  820. // TODO
  821. pData->needsReset = false;
  822. }
  823. // --------------------------------------------------------------------------------------------------------
  824. // Event Input
  825. if (pData->event.portIn != nullptr)
  826. {
  827. // ----------------------------------------------------------------------------------------------------
  828. // MIDI Input (External)
  829. if (pData->extNotes.mutex.tryLock())
  830. {
  831. for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next())
  832. {
  833. const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback));
  834. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  835. uint8_t data1, data2, data3;
  836. data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  837. data2 = note.note;
  838. data3 = note.velo;
  839. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  840. fShmRtClientControl.writeUInt(0); // time
  841. fShmRtClientControl.writeByte(0); // port
  842. fShmRtClientControl.writeByte(3); // size
  843. fShmRtClientControl.writeByte(data1);
  844. fShmRtClientControl.writeByte(data2);
  845. fShmRtClientControl.writeByte(data3);
  846. fShmRtClientControl.commitWrite();
  847. }
  848. pData->extNotes.data.clear();
  849. pData->extNotes.mutex.unlock();
  850. } // End of MIDI Input (External)
  851. // ----------------------------------------------------------------------------------------------------
  852. // Event Input (System)
  853. #ifndef BUILD_BRIDGE
  854. bool allNotesOffSent = false;
  855. #endif
  856. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  857. {
  858. const EngineEvent& event(pData->event.portIn->getEvent(i));
  859. // Control change
  860. switch (event.type)
  861. {
  862. case kEngineEventTypeNull:
  863. break;
  864. case kEngineEventTypeControl: {
  865. const EngineControlEvent& ctrlEvent = event.ctrl;
  866. switch (ctrlEvent.type)
  867. {
  868. case kEngineControlEventTypeNull:
  869. break;
  870. case kEngineControlEventTypeParameter:
  871. #ifndef BUILD_BRIDGE
  872. // Control backend stuff
  873. if (event.channel == pData->ctrlChannel)
  874. {
  875. float value;
  876. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  877. {
  878. value = ctrlEvent.value;
  879. setDryWet(value, false, false);
  880. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  881. }
  882. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  883. {
  884. value = ctrlEvent.value*127.0f/100.0f;
  885. setVolume(value, false, false);
  886. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  887. }
  888. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  889. {
  890. float left, right;
  891. value = ctrlEvent.value/0.5f - 1.0f;
  892. if (value < 0.0f)
  893. {
  894. left = -1.0f;
  895. right = (value*2.0f)+1.0f;
  896. }
  897. else if (value > 0.0f)
  898. {
  899. left = (value*2.0f)-1.0f;
  900. right = 1.0f;
  901. }
  902. else
  903. {
  904. left = -1.0f;
  905. right = 1.0f;
  906. }
  907. setBalanceLeft(left, false, false);
  908. setBalanceRight(right, false, false);
  909. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  910. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  911. }
  912. }
  913. #endif
  914. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventParameter);
  915. fShmRtClientControl.writeUInt(event.time);
  916. fShmRtClientControl.writeByte(event.channel);
  917. fShmRtClientControl.writeUShort(event.ctrl.param);
  918. fShmRtClientControl.writeFloat(event.ctrl.value);
  919. fShmRtClientControl.commitWrite();
  920. break;
  921. case kEngineControlEventTypeMidiBank:
  922. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  923. {
  924. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiBank);
  925. fShmRtClientControl.writeUInt(event.time);
  926. fShmRtClientControl.writeByte(event.channel);
  927. fShmRtClientControl.writeUShort(event.ctrl.param);
  928. fShmRtClientControl.commitWrite();
  929. }
  930. break;
  931. case kEngineControlEventTypeMidiProgram:
  932. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  933. {
  934. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiProgram);
  935. fShmRtClientControl.writeUInt(event.time);
  936. fShmRtClientControl.writeByte(event.channel);
  937. fShmRtClientControl.writeUShort(event.ctrl.param);
  938. fShmRtClientControl.commitWrite();
  939. }
  940. break;
  941. case kEngineControlEventTypeAllSoundOff:
  942. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  943. {
  944. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllSoundOff);
  945. fShmRtClientControl.writeUInt(event.time);
  946. fShmRtClientControl.writeByte(event.channel);
  947. fShmRtClientControl.commitWrite();
  948. }
  949. break;
  950. case kEngineControlEventTypeAllNotesOff:
  951. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  952. {
  953. #ifndef BUILD_BRIDGE
  954. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  955. {
  956. allNotesOffSent = true;
  957. sendMidiAllNotesOffToCallback();
  958. }
  959. #endif
  960. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllNotesOff);
  961. fShmRtClientControl.writeUInt(event.time);
  962. fShmRtClientControl.writeByte(event.channel);
  963. fShmRtClientControl.commitWrite();
  964. }
  965. break;
  966. } // switch (ctrlEvent.type)
  967. break;
  968. } // case kEngineEventTypeControl
  969. case kEngineEventTypeMidi: {
  970. const EngineMidiEvent& midiEvent(event.midi);
  971. if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE)
  972. continue;
  973. const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
  974. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
  975. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  976. continue;
  977. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  978. continue;
  979. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  980. continue;
  981. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  982. continue;
  983. // Fix bad note-off
  984. if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
  985. status = MIDI_STATUS_NOTE_OFF;
  986. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  987. fShmRtClientControl.writeUInt(event.time);
  988. fShmRtClientControl.writeByte(midiEvent.port);
  989. fShmRtClientControl.writeByte(midiEvent.size);
  990. fShmRtClientControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT)));
  991. for (uint8_t j=1; j < midiEvent.size; ++j)
  992. fShmRtClientControl.writeByte(midiData[j]);
  993. fShmRtClientControl.commitWrite();
  994. if (status == MIDI_STATUS_NOTE_ON)
  995. pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]);
  996. else if (status == MIDI_STATUS_NOTE_OFF)
  997. pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f);
  998. } break;
  999. }
  1000. }
  1001. pData->postRtEvents.trySplice();
  1002. } // End of Event Input
  1003. if (! processSingle(audioIn, audioOut, cvIn, cvOut, frames))
  1004. return;
  1005. // --------------------------------------------------------------------------------------------------------
  1006. // Control and MIDI Output
  1007. if (pData->event.portOut != nullptr)
  1008. {
  1009. float value;
  1010. for (uint32_t k=0; k < pData->param.count; ++k)
  1011. {
  1012. if (pData->param.data[k].type != PARAMETER_OUTPUT)
  1013. continue;
  1014. if (pData->param.data[k].midiCC > 0)
  1015. {
  1016. value = pData->param.ranges[k].getNormalizedValue(fParams[k].value);
  1017. pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast<uint16_t>(pData->param.data[k].midiCC), value);
  1018. }
  1019. }
  1020. uint32_t time;
  1021. uint8_t port, size;
  1022. const uint8_t* midiData(fShmRtClientControl.data->midiOut);
  1023. for (std::size_t read=0; read<kBridgeRtClientDataMidiOutSize-kBridgeBaseMidiOutHeaderSize;)
  1024. {
  1025. // get time
  1026. time = *(const uint32_t*)midiData;
  1027. midiData += 4;
  1028. // get port and size
  1029. port = *midiData++;
  1030. size = *midiData++;
  1031. if (size == 0)
  1032. break;
  1033. // store midi data advancing as needed
  1034. uint8_t data[size];
  1035. for (uint8_t j=0; j<size; ++j)
  1036. data[j] = *midiData++;
  1037. pData->event.portOut->writeMidiEvent(time, size, data);
  1038. read += kBridgeBaseMidiOutHeaderSize + size;
  1039. }
  1040. // TODO
  1041. (void)port;
  1042. } // End of Control and MIDI Output
  1043. }
  1044. bool processSingle(const float** const audioIn, float** const audioOut,
  1045. const float** const cvIn, float** const cvOut, const uint32_t frames)
  1046. {
  1047. CARLA_SAFE_ASSERT_RETURN(! fTimedError, false);
  1048. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  1049. if (pData->audioIn.count > 0)
  1050. {
  1051. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  1052. }
  1053. if (pData->audioOut.count > 0)
  1054. {
  1055. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  1056. }
  1057. if (pData->cvIn.count > 0)
  1058. {
  1059. CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
  1060. }
  1061. if (pData->cvOut.count > 0)
  1062. {
  1063. CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
  1064. }
  1065. // --------------------------------------------------------------------------------------------------------
  1066. // Try lock, silence otherwise
  1067. if (pData->engine->isOffline())
  1068. {
  1069. pData->singleMutex.lock();
  1070. }
  1071. else if (! pData->singleMutex.tryLock())
  1072. {
  1073. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1074. carla_zeroFloats(audioOut[i], frames);
  1075. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1076. carla_zeroFloats(cvOut[i], frames);
  1077. return false;
  1078. }
  1079. // --------------------------------------------------------------------------------------------------------
  1080. // Reset audio buffers
  1081. for (uint32_t i=0; i < fInfo.aIns; ++i)
  1082. carla_copyFloats(fShmAudioPool.data + (i * frames), audioIn[i], frames);
  1083. // --------------------------------------------------------------------------------------------------------
  1084. // TimeInfo
  1085. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  1086. BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  1087. bridgeTimeInfo.playing = timeInfo.playing;
  1088. bridgeTimeInfo.frame = timeInfo.frame;
  1089. bridgeTimeInfo.usecs = timeInfo.usecs;
  1090. bridgeTimeInfo.valid = timeInfo.valid;
  1091. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  1092. {
  1093. bridgeTimeInfo.bar = timeInfo.bbt.bar;
  1094. bridgeTimeInfo.beat = timeInfo.bbt.beat;
  1095. bridgeTimeInfo.tick = timeInfo.bbt.tick;
  1096. bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar;
  1097. bridgeTimeInfo.beatType = timeInfo.bbt.beatType;
  1098. bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  1099. bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  1100. bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick;
  1101. }
  1102. // --------------------------------------------------------------------------------------------------------
  1103. // Run plugin
  1104. {
  1105. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientProcess);
  1106. fShmRtClientControl.commitWrite();
  1107. }
  1108. waitForClient("process", fProcWaitTime);
  1109. if (fTimedOut)
  1110. {
  1111. pData->singleMutex.unlock();
  1112. return false;
  1113. }
  1114. for (uint32_t i=0; i < fInfo.aOuts; ++i)
  1115. carla_copyFloats(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), frames);
  1116. #ifndef BUILD_BRIDGE
  1117. // --------------------------------------------------------------------------------------------------------
  1118. // Post-processing (dry/wet, volume and balance)
  1119. {
  1120. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f);
  1121. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
  1122. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
  1123. const bool isMono = (pData->audioIn.count == 1);
  1124. bool isPair;
  1125. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1126. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1127. {
  1128. // Dry/Wet
  1129. if (doDryWet)
  1130. {
  1131. const uint32_t c = isMono ? 0 : i;
  1132. for (uint32_t k=0; k < frames; ++k)
  1133. {
  1134. if (k < pData->latency.frames)
  1135. bufValue = pData->latency.buffers[c][k];
  1136. else if (pData->latency.frames < frames)
  1137. bufValue = audioIn[c][k-pData->latency.frames];
  1138. else
  1139. bufValue = audioIn[c][k];
  1140. audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1141. }
  1142. }
  1143. // Balance
  1144. if (doBalance)
  1145. {
  1146. isPair = (i % 2 == 0);
  1147. if (isPair)
  1148. {
  1149. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1150. carla_copyFloats(oldBufLeft, audioOut[i], frames);
  1151. }
  1152. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1153. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1154. for (uint32_t k=0; k < frames; ++k)
  1155. {
  1156. if (isPair)
  1157. {
  1158. // left
  1159. audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1160. audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR);
  1161. }
  1162. else
  1163. {
  1164. // right
  1165. audioOut[i][k] = audioOut[i][k] * balRangeR;
  1166. audioOut[i][k] += oldBufLeft[k] * balRangeL;
  1167. }
  1168. }
  1169. }
  1170. // Volume (and buffer copy)
  1171. if (doVolume)
  1172. {
  1173. for (uint32_t k=0; k < frames; ++k)
  1174. audioOut[i][k] *= pData->postProc.volume;
  1175. }
  1176. }
  1177. } // End of Post-processing
  1178. // --------------------------------------------------------------------------------------------------------
  1179. // Save latency values for next callback
  1180. if (const uint32_t latframes = pData->latency.frames)
  1181. {
  1182. if (latframes <= frames)
  1183. {
  1184. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1185. carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
  1186. }
  1187. else
  1188. {
  1189. const uint32_t diff = pData->latency.frames-frames;
  1190. for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
  1191. {
  1192. // push back buffer by 'frames'
  1193. for (k=0; k < diff; ++k)
  1194. pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
  1195. // put current input at the end
  1196. for (uint32_t j=0; k < latframes; ++j, ++k)
  1197. pData->latency.buffers[i][k] = audioIn[i][j];
  1198. }
  1199. }
  1200. }
  1201. #endif // BUILD_BRIDGE
  1202. // --------------------------------------------------------------------------------------------------------
  1203. pData->singleMutex.unlock();
  1204. return true;
  1205. }
  1206. void bufferSizeChanged(const uint32_t newBufferSize) override
  1207. {
  1208. resizeAudioPool(newBufferSize);
  1209. {
  1210. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetBufferSize);
  1211. fShmRtClientControl.writeUInt(newBufferSize);
  1212. fShmRtClientControl.commitWrite();
  1213. }
  1214. //fProcWaitTime = newBufferSize*1000/pData->engine->getSampleRate();
  1215. fProcWaitTime = 1000;
  1216. waitForClient("buffersize", 1000);
  1217. }
  1218. void sampleRateChanged(const double newSampleRate) override
  1219. {
  1220. {
  1221. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetSampleRate);
  1222. fShmRtClientControl.writeDouble(newSampleRate);
  1223. fShmRtClientControl.commitWrite();
  1224. }
  1225. //fProcWaitTime = pData->engine->getBufferSize()*1000/newSampleRate;
  1226. fProcWaitTime = 1000;
  1227. waitForClient("samplerate", 1000);
  1228. }
  1229. void offlineModeChanged(const bool isOffline) override
  1230. {
  1231. {
  1232. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetOnline);
  1233. fShmRtClientControl.writeBool(isOffline);
  1234. fShmRtClientControl.commitWrite();
  1235. }
  1236. waitForClient("offline", 1000);
  1237. }
  1238. // -------------------------------------------------------------------
  1239. // Plugin buffers
  1240. void clearBuffers() noexcept override
  1241. {
  1242. if (fParams != nullptr)
  1243. {
  1244. delete[] fParams;
  1245. fParams = nullptr;
  1246. }
  1247. CarlaPlugin::clearBuffers();
  1248. }
  1249. // -------------------------------------------------------------------
  1250. // Post-poned UI Stuff
  1251. void uiParameterChange(const uint32_t index, const float value) noexcept override
  1252. {
  1253. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  1254. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1255. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiParameterChange);
  1256. fShmNonRtClientControl.writeUInt(index);
  1257. fShmNonRtClientControl.writeFloat(value);
  1258. fShmNonRtClientControl.commitWrite();
  1259. }
  1260. void uiProgramChange(const uint32_t index) noexcept override
  1261. {
  1262. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1263. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1264. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiProgramChange);
  1265. fShmNonRtClientControl.writeUInt(index);
  1266. fShmNonRtClientControl.commitWrite();
  1267. }
  1268. void uiMidiProgramChange(const uint32_t index) noexcept override
  1269. {
  1270. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1271. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1272. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiMidiProgramChange);
  1273. fShmNonRtClientControl.writeUInt(index);
  1274. fShmNonRtClientControl.commitWrite();
  1275. }
  1276. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  1277. {
  1278. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1279. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1280. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1281. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1282. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOn);
  1283. fShmNonRtClientControl.writeByte(channel);
  1284. fShmNonRtClientControl.writeByte(note);
  1285. fShmNonRtClientControl.writeByte(velo);
  1286. fShmNonRtClientControl.commitWrite();
  1287. }
  1288. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  1289. {
  1290. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1291. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1292. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  1293. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientUiNoteOff);
  1294. fShmNonRtClientControl.writeByte(channel);
  1295. fShmNonRtClientControl.writeByte(note);
  1296. fShmNonRtClientControl.commitWrite();
  1297. }
  1298. // -------------------------------------------------------------------
  1299. void handleNonRtData()
  1300. {
  1301. for (; fShmNonRtServerControl.isDataAvailableForReading();)
  1302. {
  1303. const PluginBridgeNonRtServerOpcode opcode(fShmNonRtServerControl.readOpcode());
  1304. #ifdef DEBUG
  1305. if (opcode != kPluginBridgeNonRtServerPong) {
  1306. carla_debug("CarlaPluginBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode));
  1307. }
  1308. #endif
  1309. if (opcode != kPluginBridgeNonRtServerNull && fLastPongTime > 0)
  1310. fLastPongTime = Time::currentTimeMillis();
  1311. switch (opcode)
  1312. {
  1313. case kPluginBridgeNonRtServerNull:
  1314. case kPluginBridgeNonRtServerPong:
  1315. break;
  1316. case kPluginBridgeNonRtServerPluginInfo1: {
  1317. // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  1318. const uint32_t category = fShmNonRtServerControl.readUInt();
  1319. const uint32_t hints = fShmNonRtServerControl.readUInt();
  1320. const uint32_t optionAv = fShmNonRtServerControl.readUInt();
  1321. const uint32_t optionEn = fShmNonRtServerControl.readUInt();
  1322. const int64_t uniqueId = fShmNonRtServerControl.readLong();
  1323. if (fUniqueId != 0) {
  1324. CARLA_SAFE_ASSERT_INT2(fUniqueId == uniqueId, fUniqueId, uniqueId);
  1325. }
  1326. pData->hints = hints | PLUGIN_IS_BRIDGE;
  1327. pData->options = optionEn;
  1328. fInfo.category = static_cast<PluginCategory>(category);
  1329. fInfo.optionsAvailable = optionAv;
  1330. } break;
  1331. case kPluginBridgeNonRtServerPluginInfo2: {
  1332. // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  1333. // realName
  1334. const uint32_t realNameSize(fShmNonRtServerControl.readUInt());
  1335. char realName[realNameSize+1];
  1336. carla_zeroChars(realName, realNameSize+1);
  1337. fShmNonRtServerControl.readCustomData(realName, realNameSize);
  1338. // label
  1339. const uint32_t labelSize(fShmNonRtServerControl.readUInt());
  1340. char label[labelSize+1];
  1341. carla_zeroChars(label, labelSize+1);
  1342. fShmNonRtServerControl.readCustomData(label, labelSize);
  1343. // maker
  1344. const uint32_t makerSize(fShmNonRtServerControl.readUInt());
  1345. char maker[makerSize+1];
  1346. carla_zeroChars(maker, makerSize+1);
  1347. fShmNonRtServerControl.readCustomData(maker, makerSize);
  1348. // copyright
  1349. const uint32_t copyrightSize(fShmNonRtServerControl.readUInt());
  1350. char copyright[copyrightSize+1];
  1351. carla_zeroChars(copyright, copyrightSize+1);
  1352. fShmNonRtServerControl.readCustomData(copyright, copyrightSize);
  1353. fInfo.name = realName;
  1354. fInfo.label = label;
  1355. fInfo.maker = maker;
  1356. fInfo.copyright = copyright;
  1357. if (pData->name == nullptr)
  1358. pData->name = pData->engine->getUniquePluginName(realName);
  1359. } break;
  1360. case kPluginBridgeNonRtServerAudioCount: {
  1361. // uint/ins, uint/outs
  1362. fInfo.aIns = fShmNonRtServerControl.readUInt();
  1363. fInfo.aOuts = fShmNonRtServerControl.readUInt();
  1364. CARLA_SAFE_ASSERT(fInfo.aInNames == nullptr);
  1365. CARLA_SAFE_ASSERT(fInfo.aOutNames == nullptr);
  1366. if (fInfo.aIns > 0)
  1367. {
  1368. fInfo.aInNames = new const char*[fInfo.aIns];
  1369. carla_zeroPointers(fInfo.aInNames, fInfo.aIns);
  1370. }
  1371. if (fInfo.aOuts > 0)
  1372. {
  1373. fInfo.aOutNames = new const char*[fInfo.aOuts];
  1374. carla_zeroPointers(fInfo.aOutNames, fInfo.aOuts);
  1375. }
  1376. } break;
  1377. case kPluginBridgeNonRtServerMidiCount: {
  1378. // uint/ins, uint/outs
  1379. fInfo.mIns = fShmNonRtServerControl.readUInt();
  1380. fInfo.mOuts = fShmNonRtServerControl.readUInt();
  1381. } break;
  1382. case kPluginBridgeNonRtServerCvCount: {
  1383. // uint/ins, uint/outs
  1384. fInfo.cvIns = fShmNonRtServerControl.readUInt();
  1385. fInfo.cvOuts = fShmNonRtServerControl.readUInt();
  1386. } break;
  1387. case kPluginBridgeNonRtServerParameterCount: {
  1388. // uint/count
  1389. const uint32_t count = fShmNonRtServerControl.readUInt();
  1390. // delete old data
  1391. pData->param.clear();
  1392. if (fParams != nullptr)
  1393. {
  1394. delete[] fParams;
  1395. fParams = nullptr;
  1396. }
  1397. if (count > 0)
  1398. {
  1399. pData->param.createNew(count, false);
  1400. fParams = new BridgeParamInfo[count];
  1401. // we might not receive all parameter data, so ensure range max is not 0
  1402. for (uint32_t i=0; i<count; ++i)
  1403. {
  1404. pData->param.ranges[i].def = 0.0f;
  1405. pData->param.ranges[i].min = 0.0f;
  1406. pData->param.ranges[i].max = 1.0f;
  1407. pData->param.ranges[i].step = 0.001f;
  1408. pData->param.ranges[i].stepSmall = 0.0001f;
  1409. pData->param.ranges[i].stepLarge = 0.1f;
  1410. }
  1411. }
  1412. } break;
  1413. case kPluginBridgeNonRtServerProgramCount: {
  1414. // uint/count
  1415. pData->prog.clear();
  1416. if (const uint32_t count = fShmNonRtServerControl.readUInt())
  1417. pData->prog.createNew(static_cast<uint32_t>(count));
  1418. } break;
  1419. case kPluginBridgeNonRtServerMidiProgramCount: {
  1420. // uint/count
  1421. pData->midiprog.clear();
  1422. if (const uint32_t count = fShmNonRtServerControl.readUInt())
  1423. pData->midiprog.createNew(static_cast<uint32_t>(count));
  1424. } break;
  1425. case kPluginBridgeNonRtServerPortName: {
  1426. // byte/type, uint/index, uint/size, str[] (name)
  1427. const uint8_t portType = fShmNonRtServerControl.readByte();
  1428. const uint32_t index = fShmNonRtServerControl.readUInt();
  1429. // name
  1430. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1431. char* const name = new char[nameSize+1];
  1432. carla_zeroChars(name, nameSize+1);
  1433. fShmNonRtServerControl.readCustomData(name, nameSize);
  1434. CARLA_SAFE_ASSERT_BREAK(portType > kPluginBridgePortNull && portType < kPluginBridgePortTypeCount);
  1435. switch (portType)
  1436. {
  1437. case kPluginBridgePortAudioInput:
  1438. CARLA_SAFE_ASSERT_BREAK(index < fInfo.aIns);
  1439. fInfo.aInNames[index] = name;
  1440. break;
  1441. case kPluginBridgePortAudioOutput:
  1442. CARLA_SAFE_ASSERT_BREAK(index < fInfo.aOuts);
  1443. fInfo.aOutNames[index] = name;
  1444. break;
  1445. }
  1446. } break;
  1447. case kPluginBridgeNonRtServerParameterData1: {
  1448. // uint/index, int/rindex, uint/type, uint/hints, int/cc
  1449. const uint32_t index = fShmNonRtServerControl.readUInt();
  1450. const int32_t rindex = fShmNonRtServerControl.readInt();
  1451. const uint32_t type = fShmNonRtServerControl.readUInt();
  1452. const uint32_t hints = fShmNonRtServerControl.readUInt();
  1453. const int16_t midiCC = fShmNonRtServerControl.readShort();
  1454. CARLA_SAFE_ASSERT_BREAK(midiCC >= -1 && midiCC < MAX_MIDI_CONTROL);
  1455. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1456. if (index < pData->param.count)
  1457. {
  1458. pData->param.data[index].type = static_cast<ParameterType>(type);
  1459. pData->param.data[index].index = static_cast<int32_t>(index);
  1460. pData->param.data[index].rindex = rindex;
  1461. pData->param.data[index].hints = hints;
  1462. pData->param.data[index].midiCC = midiCC;
  1463. }
  1464. } break;
  1465. case kPluginBridgeNonRtServerParameterData2: {
  1466. // uint/index, uint/size, str[] (name), uint/size, str[] (unit)
  1467. const uint32_t index = fShmNonRtServerControl.readUInt();
  1468. // name
  1469. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1470. char name[nameSize+1];
  1471. carla_zeroChars(name, nameSize+1);
  1472. fShmNonRtServerControl.readCustomData(name, nameSize);
  1473. // symbol
  1474. const uint32_t symbolSize(fShmNonRtServerControl.readUInt());
  1475. char symbol[symbolSize+1];
  1476. carla_zeroChars(symbol, symbolSize+1);
  1477. fShmNonRtServerControl.readCustomData(symbol, symbolSize);
  1478. // unit
  1479. const uint32_t unitSize(fShmNonRtServerControl.readUInt());
  1480. char unit[unitSize+1];
  1481. carla_zeroChars(unit, unitSize+1);
  1482. fShmNonRtServerControl.readCustomData(unit, unitSize);
  1483. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1484. if (index < pData->param.count)
  1485. {
  1486. fParams[index].name = name;
  1487. fParams[index].symbol = symbol;
  1488. fParams[index].unit = unit;
  1489. }
  1490. } break;
  1491. case kPluginBridgeNonRtServerParameterRanges: {
  1492. // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
  1493. const uint32_t index = fShmNonRtServerControl.readUInt();
  1494. const float def = fShmNonRtServerControl.readFloat();
  1495. const float min = fShmNonRtServerControl.readFloat();
  1496. const float max = fShmNonRtServerControl.readFloat();
  1497. const float step = fShmNonRtServerControl.readFloat();
  1498. const float stepSmall = fShmNonRtServerControl.readFloat();
  1499. const float stepLarge = fShmNonRtServerControl.readFloat();
  1500. CARLA_SAFE_ASSERT_BREAK(min < max);
  1501. CARLA_SAFE_ASSERT_BREAK(def >= min);
  1502. CARLA_SAFE_ASSERT_BREAK(def <= max);
  1503. CARLA_SAFE_ASSERT_INT2(index < pData->param.count, index, pData->param.count);
  1504. if (index < pData->param.count)
  1505. {
  1506. pData->param.ranges[index].def = def;
  1507. pData->param.ranges[index].min = min;
  1508. pData->param.ranges[index].max = max;
  1509. pData->param.ranges[index].step = step;
  1510. pData->param.ranges[index].stepSmall = stepSmall;
  1511. pData->param.ranges[index].stepLarge = stepLarge;
  1512. }
  1513. } break;
  1514. case kPluginBridgeNonRtServerParameterValue: {
  1515. // uint/index, float/value
  1516. const uint32_t index = fShmNonRtServerControl.readUInt();
  1517. const float value = fShmNonRtServerControl.readFloat();
  1518. if (index < pData->param.count)
  1519. {
  1520. const float fixedValue(pData->param.getFixedValue(index, value));
  1521. fParams[index].value = fixedValue;
  1522. CarlaPlugin::setParameterValue(index, fixedValue, false, true, true);
  1523. }
  1524. } break;
  1525. case kPluginBridgeNonRtServerParameterValue2: {
  1526. // uint/index, float/value
  1527. const uint32_t index = fShmNonRtServerControl.readUInt();
  1528. const float value = fShmNonRtServerControl.readFloat();
  1529. if (index < pData->param.count)
  1530. {
  1531. const float fixedValue(pData->param.getFixedValue(index, value));
  1532. fParams[index].value = fixedValue;
  1533. }
  1534. } break;
  1535. case kPluginBridgeNonRtServerDefaultValue: {
  1536. // uint/index, float/value
  1537. const uint32_t index = fShmNonRtServerControl.readUInt();
  1538. const float value = fShmNonRtServerControl.readFloat();
  1539. if (index < pData->param.count)
  1540. pData->param.ranges[index].def = value;
  1541. } break;
  1542. case kPluginBridgeNonRtServerCurrentProgram: {
  1543. // int/index
  1544. const int32_t index = fShmNonRtServerControl.readInt();
  1545. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1546. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1547. CarlaPlugin::setProgram(index, false, true, true);
  1548. } break;
  1549. case kPluginBridgeNonRtServerCurrentMidiProgram: {
  1550. // int/index
  1551. const int32_t index = fShmNonRtServerControl.readInt();
  1552. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1553. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1554. CarlaPlugin::setMidiProgram(index, false, true, true);
  1555. } break;
  1556. case kPluginBridgeNonRtServerProgramName: {
  1557. // uint/index, uint/size, str[] (name)
  1558. const uint32_t index = fShmNonRtServerControl.readUInt();
  1559. // name
  1560. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1561. char name[nameSize+1];
  1562. carla_zeroChars(name, nameSize+1);
  1563. fShmNonRtServerControl.readCustomData(name, nameSize);
  1564. CARLA_SAFE_ASSERT_INT2(index < pData->prog.count, index, pData->prog.count);
  1565. if (index < pData->prog.count)
  1566. {
  1567. if (pData->prog.names[index] != nullptr)
  1568. delete[] pData->prog.names[index];
  1569. pData->prog.names[index] = carla_strdup(name);
  1570. }
  1571. } break;
  1572. case kPluginBridgeNonRtServerMidiProgramData: {
  1573. // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  1574. const uint32_t index = fShmNonRtServerControl.readUInt();
  1575. const uint32_t bank = fShmNonRtServerControl.readUInt();
  1576. const uint32_t program = fShmNonRtServerControl.readUInt();
  1577. // name
  1578. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1579. char name[nameSize+1];
  1580. carla_zeroChars(name, nameSize+1);
  1581. fShmNonRtServerControl.readCustomData(name, nameSize);
  1582. CARLA_SAFE_ASSERT_INT2(index < pData->midiprog.count, index, pData->midiprog.count);
  1583. if (index < pData->midiprog.count)
  1584. {
  1585. if (pData->midiprog.data[index].name != nullptr)
  1586. delete[] pData->midiprog.data[index].name;
  1587. pData->midiprog.data[index].bank = bank;
  1588. pData->midiprog.data[index].program = program;
  1589. pData->midiprog.data[index].name = carla_strdup(name);
  1590. }
  1591. } break;
  1592. case kPluginBridgeNonRtServerSetCustomData: {
  1593. // uint/size, str[], uint/size, str[], uint/size, str[]
  1594. // type
  1595. const uint32_t typeSize(fShmNonRtServerControl.readUInt());
  1596. char type[typeSize+1];
  1597. carla_zeroChars(type, typeSize+1);
  1598. fShmNonRtServerControl.readCustomData(type, typeSize);
  1599. // key
  1600. const uint32_t keySize(fShmNonRtServerControl.readUInt());
  1601. char key[keySize+1];
  1602. carla_zeroChars(key, keySize+1);
  1603. fShmNonRtServerControl.readCustomData(key, keySize);
  1604. // value
  1605. const uint32_t valueSize(fShmNonRtServerControl.readUInt());
  1606. char value[valueSize+1];
  1607. carla_zeroChars(value, valueSize+1);
  1608. fShmNonRtServerControl.readCustomData(value, valueSize);
  1609. CarlaPlugin::setCustomData(type, key, value, false);
  1610. } break;
  1611. case kPluginBridgeNonRtServerSetChunkDataFile: {
  1612. // uint/size, str[] (filename)
  1613. // chunkFilePath
  1614. const uint32_t chunkFilePathSize(fShmNonRtServerControl.readUInt());
  1615. char chunkFilePath[chunkFilePathSize+1];
  1616. carla_zeroChars(chunkFilePath, chunkFilePathSize+1);
  1617. fShmNonRtServerControl.readCustomData(chunkFilePath, chunkFilePathSize);
  1618. String realChunkFilePath(chunkFilePath);
  1619. #ifndef CARLA_OS_WIN
  1620. // Using Wine, fix temp dir
  1621. if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
  1622. {
  1623. const StringArray driveLetterSplit(StringArray::fromTokens(realChunkFilePath, ":/", ""));
  1624. carla_stdout("chunk save path BEFORE => %s", realChunkFilePath.toRawUTF8());
  1625. realChunkFilePath = fWinePrefix;
  1626. realChunkFilePath += "/drive_";
  1627. realChunkFilePath += driveLetterSplit[0].toLowerCase();
  1628. realChunkFilePath += driveLetterSplit[1];
  1629. realChunkFilePath = realChunkFilePath.replace("\\", "/");
  1630. carla_stdout("chunk save path AFTER => %s", realChunkFilePath.toRawUTF8());
  1631. }
  1632. #endif
  1633. File chunkFile(realChunkFilePath);
  1634. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  1635. fInfo.chunk = carla_getChunkFromBase64String(chunkFile.loadFileAsString().toRawUTF8());
  1636. chunkFile.deleteFile();
  1637. } break;
  1638. case kPluginBridgeNonRtServerSetLatency:
  1639. // uint
  1640. fLatency = fShmNonRtServerControl.readUInt();
  1641. #ifndef BUILD_BRIDGE
  1642. if (! fInitiated)
  1643. pData->latency.recreateBuffers(std::max(fInfo.aIns, fInfo.aOuts), fLatency);
  1644. #endif
  1645. break;
  1646. case kPluginBridgeNonRtServerReady:
  1647. fInitiated = true;
  1648. break;
  1649. case kPluginBridgeNonRtServerSaved:
  1650. fSaved = true;
  1651. break;
  1652. case kPluginBridgeNonRtServerUiClosed:
  1653. pData->transientTryCounter = 0;
  1654. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  1655. break;
  1656. case kPluginBridgeNonRtServerError: {
  1657. // error
  1658. const uint32_t errorSize(fShmNonRtServerControl.readUInt());
  1659. char error[errorSize+1];
  1660. carla_zeroChars(error, errorSize+1);
  1661. fShmNonRtServerControl.readCustomData(error, errorSize);
  1662. if (fInitiated)
  1663. {
  1664. pData->engine->callback(ENGINE_CALLBACK_ERROR, pData->id, 0, 0, 0.0f, error);
  1665. // just in case
  1666. pData->engine->setLastError(error);
  1667. fInitError = true;
  1668. }
  1669. else
  1670. {
  1671. pData->engine->setLastError(error);
  1672. fInitError = true;
  1673. fInitiated = true;
  1674. }
  1675. } break;
  1676. }
  1677. }
  1678. }
  1679. // -------------------------------------------------------------------
  1680. uintptr_t getUiBridgeProcessId() const noexcept override
  1681. {
  1682. return fBridgeThread.getProcessPID();
  1683. }
  1684. const void* getExtraStuff() const noexcept override
  1685. {
  1686. return fBridgeBinary.isNotEmpty() ? fBridgeBinary.buffer() : nullptr;
  1687. }
  1688. // -------------------------------------------------------------------
  1689. bool init(const char* const filename, const char* const name, const char* const label, const int64_t uniqueId, const char* const bridgeBinary)
  1690. {
  1691. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  1692. // ---------------------------------------------------------------
  1693. // first checks
  1694. if (pData->client != nullptr)
  1695. {
  1696. pData->engine->setLastError("Plugin client is already registered");
  1697. return false;
  1698. }
  1699. if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
  1700. {
  1701. pData->engine->setLastError("null bridge binary");
  1702. return false;
  1703. }
  1704. // ---------------------------------------------------------------
  1705. // set info
  1706. if (name != nullptr && name[0] != '\0')
  1707. pData->name = pData->engine->getUniquePluginName(name);
  1708. if (filename != nullptr && filename[0] != '\0')
  1709. pData->filename = carla_strdup(filename);
  1710. else
  1711. pData->filename = carla_strdup("");
  1712. fUniqueId = uniqueId;
  1713. fBridgeBinary = bridgeBinary;
  1714. std::srand(static_cast<uint>(std::time(nullptr)));
  1715. // ---------------------------------------------------------------
  1716. // init sem/shm
  1717. if (! fShmAudioPool.initializeServer())
  1718. {
  1719. carla_stderr("Failed to initialize shared memory audio pool");
  1720. return false;
  1721. }
  1722. if (! fShmRtClientControl.initializeServer())
  1723. {
  1724. carla_stderr("Failed to initialize RT client control");
  1725. fShmAudioPool.clear();
  1726. return false;
  1727. }
  1728. if (! fShmNonRtClientControl.initializeServer())
  1729. {
  1730. carla_stderr("Failed to initialize Non-RT client control");
  1731. fShmRtClientControl.clear();
  1732. fShmAudioPool.clear();
  1733. return false;
  1734. }
  1735. if (! fShmNonRtServerControl.initializeServer())
  1736. {
  1737. carla_stderr("Failed to initialize Non-RT server control");
  1738. fShmNonRtClientControl.clear();
  1739. fShmRtClientControl.clear();
  1740. fShmAudioPool.clear();
  1741. return false;
  1742. }
  1743. // ---------------------------------------------------------------
  1744. // initial values
  1745. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion);
  1746. fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION);
  1747. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
  1748. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
  1749. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));
  1750. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup);
  1751. fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
  1752. fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());
  1753. fShmNonRtClientControl.commitWrite();
  1754. // testing dummy message
  1755. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
  1756. fShmRtClientControl.commitWrite();
  1757. // ---------------------------------------------------------------
  1758. // set wine prefix
  1759. if (fBridgeBinary.contains(".exe", true))
  1760. {
  1761. const EngineOptions& options(pData->engine->getOptions());
  1762. if (options.wine.autoPrefix)
  1763. fWinePrefix = findWinePrefix(pData->filename);
  1764. if (fWinePrefix.isEmpty())
  1765. {
  1766. const char* const envWinePrefix(std::getenv("WINEPREFIX"));
  1767. if (envWinePrefix != nullptr && envWinePrefix[0] != '\0')
  1768. fWinePrefix = envWinePrefix;
  1769. else if (options.wine.fallbackPrefix != nullptr && options.wine.fallbackPrefix[0] != '\0')
  1770. fWinePrefix = options.wine.fallbackPrefix;
  1771. else
  1772. fWinePrefix = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine";
  1773. }
  1774. }
  1775. // ---------------------------------------------------------------
  1776. // init bridge thread
  1777. {
  1778. char shmIdsStr[6*4+1];
  1779. carla_zeroChars(shmIdsStr, 6*4+1);
  1780. std::strncpy(shmIdsStr+6*0, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  1781. std::strncpy(shmIdsStr+6*1, &fShmRtClientControl.filename[fShmRtClientControl.filename.length()-6], 6);
  1782. std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6);
  1783. std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6);
  1784. fBridgeThread.setData(fWinePrefix.toRawUTF8(), bridgeBinary, label, shmIdsStr);
  1785. fBridgeThread.startThread();
  1786. }
  1787. // ---------------------------------------------------------------
  1788. // wait for bridge to start
  1789. fInitiated = false;
  1790. fLastPongTime = Time::currentTimeMillis();
  1791. CARLA_SAFE_ASSERT(fLastPongTime > 0);
  1792. static bool sFirstInit = true;
  1793. int64_t timeoutEnd = 5000;
  1794. if (sFirstInit)
  1795. timeoutEnd *= 2;
  1796. #ifndef CARLA_OS_WIN
  1797. if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
  1798. timeoutEnd *= 2;
  1799. #endif
  1800. sFirstInit = false;
  1801. const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;
  1802. for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
  1803. {
  1804. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  1805. if (needsEngineIdle)
  1806. pData->engine->idle();
  1807. idle();
  1808. if (fInitiated)
  1809. break;
  1810. if (pData->engine->isAboutToClose())
  1811. break;
  1812. carla_msleep(20);
  1813. }
  1814. fLastPongTime = -1;
  1815. if (fInitError || ! fInitiated)
  1816. {
  1817. fBridgeThread.stopThread(6000);
  1818. if (! fInitError)
  1819. pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  1820. return false;
  1821. }
  1822. // ---------------------------------------------------------------
  1823. // register client
  1824. if (pData->name == nullptr)
  1825. {
  1826. if (label != nullptr && label[0] != '\0')
  1827. pData->name = pData->engine->getUniquePluginName(label);
  1828. else
  1829. pData->name = pData->engine->getUniquePluginName("unknown");
  1830. }
  1831. pData->client = pData->engine->addClient(this);
  1832. if (pData->client == nullptr || ! pData->client->isOk())
  1833. {
  1834. pData->engine->setLastError("Failed to register plugin client");
  1835. return false;
  1836. }
  1837. return true;
  1838. }
  1839. private:
  1840. const BinaryType fBinaryType;
  1841. const PluginType fPluginType;
  1842. bool fInitiated;
  1843. bool fInitError;
  1844. bool fSaved;
  1845. bool fTimedOut;
  1846. bool fTimedError;
  1847. uint fProcWaitTime;
  1848. int64_t fLastPongTime;
  1849. CarlaString fBridgeBinary;
  1850. CarlaPluginBridgeThread fBridgeThread;
  1851. BridgeAudioPool fShmAudioPool;
  1852. BridgeRtClientControl fShmRtClientControl;
  1853. BridgeNonRtClientControl fShmNonRtClientControl;
  1854. BridgeNonRtServerControl fShmNonRtServerControl;
  1855. String fWinePrefix;
  1856. struct Info {
  1857. uint32_t aIns, aOuts;
  1858. uint32_t cvIns, cvOuts;
  1859. uint32_t mIns, mOuts;
  1860. PluginCategory category;
  1861. uint optionsAvailable;
  1862. CarlaString name;
  1863. CarlaString label;
  1864. CarlaString maker;
  1865. CarlaString copyright;
  1866. const char** aInNames;
  1867. const char** aOutNames;
  1868. std::vector<uint8_t> chunk;
  1869. Info()
  1870. : aIns(0),
  1871. aOuts(0),
  1872. cvIns(0),
  1873. cvOuts(0),
  1874. mIns(0),
  1875. mOuts(0),
  1876. category(PLUGIN_CATEGORY_NONE),
  1877. optionsAvailable(0),
  1878. name(),
  1879. label(),
  1880. maker(),
  1881. copyright(),
  1882. aInNames(nullptr),
  1883. aOutNames(nullptr),
  1884. chunk() {}
  1885. CARLA_DECLARE_NON_COPY_STRUCT(Info)
  1886. } fInfo;
  1887. int64_t fUniqueId;
  1888. uint32_t fLatency;
  1889. BridgeParamInfo* fParams;
  1890. void resizeAudioPool(const uint32_t bufferSize)
  1891. {
  1892. fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);
  1893. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
  1894. fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
  1895. fShmRtClientControl.commitWrite();
  1896. waitForClient("resize-pool", 5000);
  1897. }
  1898. void waitForClient(const char* const action, const uint msecs)
  1899. {
  1900. CARLA_SAFE_ASSERT_RETURN(! fTimedOut,);
  1901. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  1902. if (fShmRtClientControl.waitForClient(msecs))
  1903. return;
  1904. fTimedOut = true;
  1905. carla_stderr("waitForClient(%s) timed out", action);
  1906. }
  1907. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge)
  1908. };
  1909. CARLA_BACKEND_END_NAMESPACE
  1910. // ---------------------------------------------------------------------------------------------------------------------
  1911. CARLA_BACKEND_START_NAMESPACE
  1912. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* bridgeBinary)
  1913. {
  1914. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1915. if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
  1916. {
  1917. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1918. return nullptr;
  1919. }
  1920. #ifndef CARLA_OS_WIN
  1921. // FIXME: somewhere, somehow, we end up with double slashes, wine doesn't like that.
  1922. if (std::strncmp(bridgeBinary, "//", 2) == 0)
  1923. ++bridgeBinary;
  1924. #endif
  1925. CarlaPluginBridge* const plugin(new CarlaPluginBridge(init.engine, init.id, btype, ptype));
  1926. if (! plugin->init(init.filename, init.name, init.label, init.uniqueId, bridgeBinary))
  1927. {
  1928. delete plugin;
  1929. return nullptr;
  1930. }
  1931. return plugin;
  1932. }
  1933. CARLA_BACKEND_END_NAMESPACE
  1934. // ---------------------------------------------------------------------------------------------------------------------
  1935. #ifndef BUILD_BRIDGE
  1936. # include "CarlaBridgeUtils.cpp"
  1937. #endif
  1938. // ---------------------------------------------------------------------------------------------------------------------