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

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