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

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