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.

BridgePlugin.cpp 77KB

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
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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
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
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
11 years ago
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
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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308
  1. /*
  2. * Carla Bridge Plugin
  3. * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #include "CarlaEngine.hpp"
  19. #ifndef BUILD_BRIDGE
  20. #include "CarlaBackendUtils.hpp"
  21. #include "CarlaBase64Utils.hpp"
  22. #include "CarlaBridgeUtils.hpp"
  23. #include "CarlaMathUtils.hpp"
  24. #include "CarlaShmUtils.hpp"
  25. #include "jackbridge/JackBridge.hpp"
  26. #include <cerrno>
  27. #include <cmath>
  28. #include <ctime>
  29. #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
  30. /* check argument count */ \
  31. if (argc != argcToCompare) \
  32. { \
  33. carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \
  34. return 1; \
  35. } \
  36. if (argc > 0) \
  37. { \
  38. /* check for nullness */ \
  39. if (! (types && typesToCompare)) \
  40. { \
  41. carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \
  42. return 1; \
  43. } \
  44. /* check argument types */ \
  45. if (std::strcmp(types, typesToCompare) != 0) \
  46. { \
  47. carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \
  48. return 1; \
  49. } \
  50. }
  51. // -------------------------------------------------------------------------------------------------------------------
  52. using juce::File;
  53. using juce::String;
  54. using juce::StringArray;
  55. CARLA_BACKEND_START_NAMESPACE
  56. // -------------------------------------------------------------------------------------------------------------------
  57. // call carla_shm_create with for a XXXXXX temp filename
  58. static shm_t shm_mkstemp(char* const fileBase)
  59. {
  60. CARLA_SAFE_ASSERT_RETURN(fileBase != nullptr, gNullCarlaShm);
  61. const size_t fileBaseLen(std::strlen(fileBase));
  62. CARLA_SAFE_ASSERT_RETURN(fileBaseLen > 6, gNullCarlaShm);
  63. CARLA_SAFE_ASSERT_RETURN(std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") == 0, gNullCarlaShm);
  64. static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
  65. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  66. "0123456789";
  67. static const int charSetLen = static_cast<int>(std::strlen(charSet) - 1); // -1 to avoid trailing '\0'
  68. // try until getting a valid shm or an error occurs
  69. for (;;)
  70. {
  71. for (size_t c = fileBaseLen - 6; c < fileBaseLen; ++c)
  72. fileBase[c] = charSet[std::rand() % charSetLen];
  73. const shm_t shm = carla_shm_create(fileBase);
  74. if (carla_is_shm_valid(shm))
  75. return shm;
  76. if (errno != EEXIST)
  77. return gNullCarlaShm;
  78. }
  79. }
  80. // -------------------------------------------------------------------------------------------------------------------
  81. struct BridgeAudioPool {
  82. CarlaString filename;
  83. float* data;
  84. size_t size;
  85. shm_t shm;
  86. BridgeAudioPool() noexcept
  87. : filename(),
  88. data(nullptr),
  89. size(0)
  90. #ifdef CARLA_PROPER_CPP11_SUPPORT
  91. , shm(shm_t_INIT) {}
  92. #else
  93. {
  94. carla_shm_init(shm);
  95. }
  96. #endif
  97. ~BridgeAudioPool() noexcept
  98. {
  99. // should be cleared by now
  100. CARLA_SAFE_ASSERT(data == nullptr);
  101. clear();
  102. }
  103. void clear() noexcept
  104. {
  105. filename.clear();
  106. if (! carla_is_shm_valid(shm))
  107. return;
  108. if (data != nullptr)
  109. {
  110. carla_shm_unmap(shm, data, size);
  111. data = nullptr;
  112. }
  113. size = 0;
  114. carla_shm_close(shm);
  115. }
  116. void resize(const uint32_t bufferSize, const uint32_t portCount) noexcept
  117. {
  118. if (data != nullptr)
  119. carla_shm_unmap(shm, data, size);
  120. size = portCount*bufferSize*sizeof(float);
  121. if (size == 0)
  122. size = sizeof(float);
  123. data = (float*)carla_shm_map(shm, size);
  124. }
  125. CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
  126. };
  127. // -------------------------------------------------------------------------------------------------------------------
  128. struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
  129. CarlaString filename;
  130. BridgeRtData* data;
  131. shm_t shm;
  132. BridgeRtControl()
  133. : filename(),
  134. data(nullptr)
  135. #ifdef CARLA_PROPER_CPP11_SUPPORT
  136. , shm(shm_t_INIT) {}
  137. #else
  138. {
  139. carla_shm_init(shm);
  140. }
  141. #endif
  142. ~BridgeRtControl() noexcept override
  143. {
  144. // should be cleared by now
  145. CARLA_SAFE_ASSERT(data == nullptr);
  146. clear();
  147. }
  148. void clear() noexcept
  149. {
  150. filename.clear();
  151. if (! carla_is_shm_valid(shm))
  152. return;
  153. if (data != nullptr)
  154. {
  155. carla_shm_unmap(shm, data, sizeof(BridgeRtData));
  156. data = nullptr;
  157. }
  158. carla_shm_close(shm);
  159. }
  160. bool mapData() noexcept
  161. {
  162. CARLA_SAFE_ASSERT(data == nullptr);
  163. if (carla_shm_map<BridgeRtData>(shm, data))
  164. {
  165. setRingBuffer(&data->ringBuffer, true);
  166. return true;
  167. }
  168. return false;
  169. }
  170. void unmapData() noexcept
  171. {
  172. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  173. carla_shm_unmap(shm, data, sizeof(BridgeRtData));
  174. data = nullptr;
  175. setRingBuffer(nullptr, false);
  176. }
  177. bool waitForServer(const int secs) noexcept
  178. {
  179. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  180. jackbridge_sem_post(&data->sem.server);
  181. return jackbridge_sem_timedwait(&data->sem.client, secs);
  182. }
  183. void writeOpcode(const PluginBridgeRtOpcode opcode) noexcept
  184. {
  185. writeInt(static_cast<int32_t>(opcode));
  186. }
  187. CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtControl)
  188. };
  189. // -------------------------------------------------------------------------------------------------------------------
  190. struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
  191. CarlaMutex mutex;
  192. CarlaString filename;
  193. BridgeNonRtData* data;
  194. shm_t shm;
  195. BridgeNonRtControl() noexcept
  196. : mutex(),
  197. filename(),
  198. data(nullptr)
  199. #ifdef CARLA_PROPER_CPP11_SUPPORT
  200. , shm(shm_t_INIT) {}
  201. #else
  202. {
  203. carla_shm_init(shm);
  204. }
  205. #endif
  206. ~BridgeNonRtControl() noexcept override
  207. {
  208. // should be cleared by now
  209. CARLA_SAFE_ASSERT(data == nullptr);
  210. clear();
  211. }
  212. void clear() noexcept
  213. {
  214. filename.clear();
  215. if (! carla_is_shm_valid(shm))
  216. return;
  217. if (data != nullptr)
  218. {
  219. carla_shm_unmap(shm, data, sizeof(BridgeNonRtData));
  220. data = nullptr;
  221. }
  222. carla_shm_close(shm);
  223. }
  224. bool mapData() noexcept
  225. {
  226. CARLA_SAFE_ASSERT(data == nullptr);
  227. if (carla_shm_map<BridgeNonRtData>(shm, data))
  228. {
  229. setRingBuffer(&data->ringBuffer, true);
  230. return true;
  231. }
  232. return false;
  233. }
  234. void unmapData() noexcept
  235. {
  236. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  237. carla_shm_unmap(shm, data, sizeof(BridgeNonRtData));
  238. data = nullptr;
  239. setRingBuffer(nullptr, false);
  240. }
  241. void writeOpcode(const PluginBridgeNonRtOpcode opcode) noexcept
  242. {
  243. writeInt(static_cast<int32_t>(opcode));
  244. }
  245. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtControl)
  246. };
  247. // -------------------------------------------------------------------------------------------------------------------
  248. struct BridgeParamInfo {
  249. float value;
  250. CarlaString name;
  251. CarlaString unit;
  252. BridgeParamInfo() noexcept
  253. : value(0.0f),
  254. name(),
  255. unit() {}
  256. CARLA_DECLARE_NON_COPY_STRUCT(BridgeParamInfo)
  257. };
  258. // -------------------------------------------------------------------------------------------------------------------
  259. class BridgePlugin : public CarlaPlugin
  260. {
  261. public:
  262. BridgePlugin(CarlaEngine* const engine, const uint id, const BinaryType btype, const PluginType ptype)
  263. : CarlaPlugin(engine, id),
  264. fBinaryType(btype),
  265. fPluginType(ptype),
  266. fInitiated(false),
  267. fInitError(false),
  268. fSaved(false),
  269. fNeedsSemDestroy(false),
  270. fTimedOut(false),
  271. fLastPongCounter(-1),
  272. fBridgeBinary(),
  273. fShmAudioPool(),
  274. fShmCVPool(),
  275. fShmRtControl(),
  276. fShmNonRtControl(),
  277. fInfo(),
  278. fParams(nullptr),
  279. leakDetector_BridgePlugin()
  280. {
  281. carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  282. pData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  283. pData->hints |= PLUGIN_IS_BRIDGE;
  284. }
  285. ~BridgePlugin() override
  286. {
  287. carla_debug("BridgePlugin::~BridgePlugin()");
  288. // close UI
  289. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  290. pData->transientTryCounter = 0;
  291. pData->singleMutex.lock();
  292. pData->masterMutex.lock();
  293. if (pData->client != nullptr && pData->client->isActive())
  294. pData->client->deactivate();
  295. if (pData->active)
  296. {
  297. deactivate();
  298. pData->active = false;
  299. }
  300. if (pData->osc.thread.isThreadRunning())
  301. {
  302. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtQuit);
  303. fShmNonRtControl.commitWrite();
  304. fShmRtControl.writeOpcode(kPluginBridgeRtQuit);
  305. fShmRtControl.commitWrite();
  306. if (! fTimedOut)
  307. fShmRtControl.waitForServer(3);
  308. }
  309. pData->osc.data.clear();
  310. pData->osc.thread.stopThread(3000);
  311. if (fNeedsSemDestroy)
  312. {
  313. jackbridge_sem_destroy(&fShmRtControl.data->sem.server);
  314. jackbridge_sem_destroy(&fShmRtControl.data->sem.client);
  315. }
  316. fShmAudioPool.clear();
  317. fShmRtControl.clear();
  318. fShmNonRtControl.clear();
  319. clearBuffers();
  320. fInfo.chunk.clear();
  321. }
  322. // -------------------------------------------------------------------
  323. // Information (base)
  324. BinaryType getBinaryType() const noexcept
  325. {
  326. return fBinaryType;
  327. }
  328. PluginType getType() const noexcept override
  329. {
  330. return fPluginType;
  331. }
  332. PluginCategory getCategory() const noexcept override
  333. {
  334. return fInfo.category;
  335. }
  336. int64_t getUniqueId() const noexcept override
  337. {
  338. return fInfo.uniqueId;
  339. }
  340. // -------------------------------------------------------------------
  341. // Information (count)
  342. uint32_t getMidiInCount() const noexcept override
  343. {
  344. return fInfo.mIns;
  345. }
  346. uint32_t getMidiOutCount() const noexcept override
  347. {
  348. return fInfo.mOuts;
  349. }
  350. // -------------------------------------------------------------------
  351. // Information (current data)
  352. std::size_t getChunkData(void** const dataPtr) noexcept override
  353. {
  354. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  355. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  356. CARLA_SAFE_ASSERT_RETURN(fInfo.chunk.size() > 0, 0);
  357. *dataPtr = fInfo.chunk.data();
  358. return fInfo.chunk.size();
  359. }
  360. // -------------------------------------------------------------------
  361. // Information (per-plugin data)
  362. uint getOptionsAvailable() const noexcept override
  363. {
  364. return fInfo.optionsAvailable;
  365. }
  366. float getParameterValue(const uint32_t parameterId) const noexcept override
  367. {
  368. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  369. return fParams[parameterId].value;
  370. }
  371. void getLabel(char* const strBuf) const noexcept override
  372. {
  373. std::strncpy(strBuf, fInfo.label, STR_MAX);
  374. }
  375. void getMaker(char* const strBuf) const noexcept override
  376. {
  377. std::strncpy(strBuf, fInfo.maker, STR_MAX);
  378. }
  379. void getCopyright(char* const strBuf) const noexcept override
  380. {
  381. std::strncpy(strBuf, fInfo.copyright, STR_MAX);
  382. }
  383. void getRealName(char* const strBuf) const noexcept override
  384. {
  385. std::strncpy(strBuf, fInfo.name, STR_MAX);
  386. }
  387. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  388. {
  389. CARLA_ASSERT(parameterId < pData->param.count);
  390. std::strncpy(strBuf, fParams[parameterId].name.buffer(), STR_MAX);
  391. }
  392. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  393. {
  394. CARLA_ASSERT(parameterId < pData->param.count);
  395. std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX);
  396. }
  397. // -------------------------------------------------------------------
  398. // Set data (state)
  399. void prepareForSave() override
  400. {
  401. fSaved = false;
  402. {
  403. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  404. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtPrepareForSave);
  405. fShmNonRtControl.commitWrite();
  406. }
  407. carla_stdout("BridgePlugin::prepareForSave() - sent, now waiting...");
  408. for (int i=0; i < 200; ++i)
  409. {
  410. if (fSaved)
  411. break;
  412. carla_msleep(30);
  413. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  414. pData->engine->idle();
  415. }
  416. if (! fSaved)
  417. carla_stderr("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  418. else
  419. carla_stdout("BridgePlugin::prepareForSave() - success!");
  420. }
  421. // -------------------------------------------------------------------
  422. // Set data (internal stuff)
  423. void setOption(const uint option, const bool yesNo, const bool sendCallback) override
  424. {
  425. {
  426. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  427. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetOption);
  428. fShmNonRtControl.writeUInt(option);
  429. fShmNonRtControl.writeBool(yesNo);
  430. fShmNonRtControl.commitWrite();
  431. }
  432. CarlaPlugin::setOption(option, yesNo, sendCallback);
  433. }
  434. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  435. {
  436. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  437. {
  438. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  439. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetCtrlChannel);
  440. fShmNonRtControl.writeShort(channel);
  441. fShmNonRtControl.commitWrite();
  442. }
  443. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  444. }
  445. // -------------------------------------------------------------------
  446. // Set data (plugin-specific stuff)
  447. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  448. {
  449. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  450. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  451. fParams[parameterId].value = fixedValue;
  452. {
  453. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  454. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetParameterValue);
  455. fShmNonRtControl.writeUInt(parameterId);
  456. fShmNonRtControl.writeFloat(value);
  457. fShmNonRtControl.commitWrite();
  458. }
  459. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  460. }
  461. void setParameterMidiChannel(const uint32_t parameterId, const uint8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  462. {
  463. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  464. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  465. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  466. {
  467. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  468. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetParameterMidiChannel);
  469. fShmNonRtControl.writeUInt(parameterId);
  470. fShmNonRtControl.writeByte(channel);
  471. fShmNonRtControl.commitWrite();
  472. }
  473. CarlaPlugin::setParameterMidiChannel(parameterId, channel, sendOsc, sendCallback);
  474. }
  475. void setParameterMidiCC(const uint32_t parameterId, const int16_t cc, const bool sendOsc, const bool sendCallback) noexcept override
  476. {
  477. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  478. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  479. CARLA_SAFE_ASSERT_RETURN(cc >= -1 && cc <= 0x5F,);
  480. {
  481. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  482. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetParameterMidiCC);
  483. fShmNonRtControl.writeUInt(parameterId);
  484. fShmNonRtControl.writeShort(cc);
  485. fShmNonRtControl.commitWrite();
  486. }
  487. CarlaPlugin::setParameterMidiCC(parameterId, cc, sendOsc, sendCallback);
  488. }
  489. void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  490. {
  491. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
  492. {
  493. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  494. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetProgram);
  495. fShmNonRtControl.writeInt(index);
  496. fShmNonRtControl.commitWrite();
  497. }
  498. CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback);
  499. }
  500. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  501. {
  502. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  503. {
  504. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  505. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetMidiProgram);
  506. fShmNonRtControl.writeInt(index);
  507. fShmNonRtControl.commitWrite();
  508. }
  509. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  510. }
  511. #if 0
  512. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  513. {
  514. CARLA_ASSERT(type);
  515. CARLA_ASSERT(key);
  516. CARLA_ASSERT(value);
  517. if (sendGui)
  518. {
  519. // TODO - if type is chunk|binary, store it in a file and send path instead
  520. QString cData;
  521. cData = type;
  522. cData += "·";
  523. cData += key;
  524. cData += "·";
  525. cData += value;
  526. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  527. }
  528. CarlaPlugin::setCustomData(type, key, value, sendGui);
  529. }
  530. #endif
  531. void setChunkData(const void* const data, const std::size_t dataSize) override
  532. {
  533. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  534. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  535. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  536. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  537. CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0,);
  538. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  539. filePath += CARLA_OS_SEP_STR;
  540. filePath += ".CarlaChunk_";
  541. filePath += fShmAudioPool.filename.buffer() + 18;
  542. if (File(filePath).replaceWithText(dataBase64.buffer()))
  543. {
  544. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  545. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  546. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetChunkDataFile);
  547. fShmNonRtControl.writeUInt(ulength);
  548. fShmNonRtControl.writeCustomData(filePath.toRawUTF8(), ulength);
  549. fShmNonRtControl.commitWrite();
  550. }
  551. }
  552. // -------------------------------------------------------------------
  553. // Set ui stuff
  554. void showCustomUI(const bool yesNo) override
  555. {
  556. {
  557. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  558. fShmNonRtControl.writeOpcode(yesNo ? kPluginBridgeNonRtShowUI : kPluginBridgeNonRtHideUI);
  559. fShmNonRtControl.commitWrite();
  560. }
  561. if (yesNo)
  562. {
  563. pData->tryTransient();
  564. }
  565. else
  566. {
  567. pData->transientTryCounter = 0;
  568. }
  569. }
  570. void idle() override
  571. {
  572. if (pData->osc.thread.isThreadRunning())
  573. {
  574. if (fTimedOut && pData->active)
  575. setActive(false, true, true);
  576. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  577. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtPing);
  578. fShmNonRtControl.commitWrite();
  579. }
  580. else
  581. carla_stderr2("TESTING: Bridge has closed!");
  582. CarlaPlugin::idle();
  583. }
  584. // -------------------------------------------------------------------
  585. // Plugin state
  586. void reload() override
  587. {
  588. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  589. carla_debug("BridgePlugin::reload() - start");
  590. const EngineProcessMode processMode(pData->engine->getProccessMode());
  591. // Safely disable plugin for reload
  592. const ScopedDisabler sd(this);
  593. bool needsCtrlIn, needsCtrlOut;
  594. needsCtrlIn = needsCtrlOut = false;
  595. if (fInfo.aIns > 0)
  596. {
  597. pData->audioIn.createNew(fInfo.aIns);
  598. }
  599. if (fInfo.aOuts > 0)
  600. {
  601. pData->audioOut.createNew(fInfo.aOuts);
  602. needsCtrlIn = true;
  603. }
  604. if (fInfo.mIns > 0)
  605. needsCtrlIn = true;
  606. if (fInfo.mOuts > 0)
  607. needsCtrlOut = true;
  608. const uint portNameSize(pData->engine->getMaxPortNameSize());
  609. CarlaString portName;
  610. // Audio Ins
  611. for (uint32_t j=0; j < fInfo.aIns; ++j)
  612. {
  613. portName.clear();
  614. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  615. {
  616. portName = pData->name;
  617. portName += ":";
  618. }
  619. if (fInfo.aIns > 1)
  620. {
  621. portName += "input_";
  622. portName += CarlaString(j+1);
  623. }
  624. else
  625. portName += "input";
  626. portName.truncate(portNameSize);
  627. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  628. pData->audioIn.ports[j].rindex = j;
  629. }
  630. // Audio Outs
  631. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  632. {
  633. portName.clear();
  634. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  635. {
  636. portName = pData->name;
  637. portName += ":";
  638. }
  639. if (fInfo.aOuts > 1)
  640. {
  641. portName += "output_";
  642. portName += CarlaString(j+1);
  643. }
  644. else
  645. portName += "output";
  646. portName.truncate(portNameSize);
  647. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  648. pData->audioOut.ports[j].rindex = j;
  649. }
  650. if (needsCtrlIn)
  651. {
  652. portName.clear();
  653. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  654. {
  655. portName = pData->name;
  656. portName += ":";
  657. }
  658. portName += "event-in";
  659. portName.truncate(portNameSize);
  660. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  661. }
  662. if (needsCtrlOut)
  663. {
  664. portName.clear();
  665. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  666. {
  667. portName = pData->name;
  668. portName += ":";
  669. }
  670. portName += "event-out";
  671. portName.truncate(portNameSize);
  672. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  673. }
  674. // extra plugin hints
  675. pData->extraHints = 0x0;
  676. if (fInfo.mIns > 0)
  677. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  678. if (fInfo.mOuts > 0)
  679. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  680. if (fInfo.aIns <= 2 && fInfo.aOuts <= 2 && (fInfo.aIns == fInfo.aOuts || fInfo.aIns == 0 || fInfo.aOuts == 0))
  681. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  682. bufferSizeChanged(pData->engine->getBufferSize());
  683. reloadPrograms(true);
  684. carla_debug("BridgePlugin::reload() - end");
  685. }
  686. // -------------------------------------------------------------------
  687. // Plugin processing
  688. void activate() noexcept override
  689. {
  690. {
  691. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  692. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtActivate);
  693. fShmNonRtControl.commitWrite();
  694. }
  695. bool timedOut = true;
  696. try {
  697. timedOut = waitForServer(1);
  698. } catch(...) {}
  699. if (! timedOut)
  700. fTimedOut = false;
  701. }
  702. void deactivate() noexcept override
  703. {
  704. {
  705. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  706. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtDeactivate);
  707. fShmNonRtControl.commitWrite();
  708. }
  709. bool timedOut = true;
  710. try {
  711. timedOut = waitForServer(1);
  712. } catch(...) {}
  713. if (! timedOut)
  714. fTimedOut = false;
  715. }
  716. void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
  717. {
  718. // --------------------------------------------------------------------------------------------------------
  719. // Check if active
  720. if (fTimedOut || ! pData->active)
  721. {
  722. // disable any output sound
  723. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  724. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  725. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  726. FloatVectorOperations::clear(cvOut[i], static_cast<int>(frames));
  727. return;
  728. }
  729. // --------------------------------------------------------------------------------------------------------
  730. // Check if needs reset
  731. if (pData->needsReset)
  732. {
  733. // TODO
  734. pData->needsReset = false;
  735. }
  736. // --------------------------------------------------------------------------------------------------------
  737. // Event Input
  738. if (pData->event.portIn != nullptr)
  739. {
  740. // ----------------------------------------------------------------------------------------------------
  741. // MIDI Input (External)
  742. if (pData->extNotes.mutex.tryLock())
  743. {
  744. for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin(); it.valid(); it.next())
  745. {
  746. const ExternalMidiNote& note(it.getValue());
  747. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  748. uint8_t data1, data2, data3;
  749. data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  750. data2 = note.note;
  751. data3 = note.velo;
  752. fShmRtControl.writeOpcode(kPluginBridgeRtMidiEvent);
  753. fShmRtControl.writeUInt(0); // time
  754. fShmRtControl.writeByte(0); // port
  755. fShmRtControl.writeByte(3); // size
  756. fShmRtControl.writeByte(data1);
  757. fShmRtControl.writeByte(data2);
  758. fShmRtControl.writeByte(data3);
  759. fShmRtControl.commitWrite();
  760. }
  761. pData->extNotes.data.clear();
  762. pData->extNotes.mutex.unlock();
  763. } // End of MIDI Input (External)
  764. // ----------------------------------------------------------------------------------------------------
  765. // Event Input (System)
  766. bool allNotesOffSent = false;
  767. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  768. {
  769. const EngineEvent& event(pData->event.portIn->getEvent(i));
  770. // Control change
  771. switch (event.type)
  772. {
  773. case kEngineEventTypeNull:
  774. break;
  775. case kEngineEventTypeControl: {
  776. const EngineControlEvent& ctrlEvent = event.ctrl;
  777. switch (ctrlEvent.type)
  778. {
  779. case kEngineControlEventTypeNull:
  780. break;
  781. case kEngineControlEventTypeParameter:
  782. // Control backend stuff
  783. if (event.channel == pData->ctrlChannel)
  784. {
  785. float value;
  786. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  787. {
  788. value = ctrlEvent.value;
  789. setDryWet(value, false, false);
  790. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  791. break;
  792. }
  793. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  794. {
  795. value = ctrlEvent.value*127.0f/100.0f;
  796. setVolume(value, false, false);
  797. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  798. break;
  799. }
  800. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  801. {
  802. float left, right;
  803. value = ctrlEvent.value/0.5f - 1.0f;
  804. if (value < 0.0f)
  805. {
  806. left = -1.0f;
  807. right = (value*2.0f)+1.0f;
  808. }
  809. else if (value > 0.0f)
  810. {
  811. left = (value*2.0f)-1.0f;
  812. right = 1.0f;
  813. }
  814. else
  815. {
  816. left = -1.0f;
  817. right = 1.0f;
  818. }
  819. setBalanceLeft(left, false, false);
  820. setBalanceRight(right, false, false);
  821. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  822. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  823. break;
  824. }
  825. }
  826. fShmRtControl.writeOpcode(kPluginBridgeRtControlEventParameter);
  827. fShmRtControl.writeUInt(event.time);
  828. fShmRtControl.writeByte(event.channel);
  829. fShmRtControl.writeUShort(event.ctrl.param);
  830. fShmRtControl.writeFloat(event.ctrl.value);
  831. fShmRtControl.commitWrite();
  832. break;
  833. case kEngineControlEventTypeMidiBank:
  834. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  835. {
  836. fShmRtControl.writeOpcode(kPluginBridgeRtControlEventMidiBank);
  837. fShmRtControl.writeUInt(event.time);
  838. fShmRtControl.writeByte(event.channel);
  839. fShmRtControl.writeUShort(event.ctrl.param);
  840. fShmRtControl.commitWrite();
  841. }
  842. break;
  843. case kEngineControlEventTypeMidiProgram:
  844. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  845. {
  846. fShmRtControl.writeOpcode(kPluginBridgeRtControlEventMidiProgram);
  847. fShmRtControl.writeUInt(event.time);
  848. fShmRtControl.writeByte(event.channel);
  849. fShmRtControl.writeUShort(event.ctrl.param);
  850. fShmRtControl.commitWrite();
  851. }
  852. break;
  853. case kEngineControlEventTypeAllSoundOff:
  854. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  855. {
  856. fShmRtControl.writeOpcode(kPluginBridgeRtControlEventAllSoundOff);
  857. fShmRtControl.writeUInt(event.time);
  858. fShmRtControl.writeByte(event.channel);
  859. fShmRtControl.commitWrite();
  860. }
  861. break;
  862. case kEngineControlEventTypeAllNotesOff:
  863. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  864. {
  865. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  866. {
  867. allNotesOffSent = true;
  868. sendMidiAllNotesOffToCallback();
  869. }
  870. fShmRtControl.writeOpcode(kPluginBridgeRtControlEventAllNotesOff);
  871. fShmRtControl.writeUInt(event.time);
  872. fShmRtControl.writeByte(event.channel);
  873. fShmRtControl.commitWrite();
  874. }
  875. break;
  876. } // switch (ctrlEvent.type)
  877. break;
  878. } // case kEngineEventTypeControl
  879. case kEngineEventTypeMidi: {
  880. const EngineMidiEvent& midiEvent(event.midi);
  881. if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE)
  882. continue;
  883. const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
  884. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
  885. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  886. continue;
  887. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  888. continue;
  889. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  890. continue;
  891. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  892. continue;
  893. // Fix bad note-off
  894. if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
  895. status = MIDI_STATUS_NOTE_OFF;
  896. fShmRtControl.writeOpcode(kPluginBridgeRtMidiEvent);
  897. fShmRtControl.writeUInt(event.time);
  898. fShmRtControl.writeByte(midiEvent.port);
  899. fShmRtControl.writeByte(midiEvent.size);
  900. fShmRtControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT)));
  901. for (uint8_t j=1; j < midiEvent.size; ++j)
  902. fShmRtControl.writeByte(midiData[j]);
  903. fShmRtControl.commitWrite();
  904. if (status == MIDI_STATUS_NOTE_ON)
  905. pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]);
  906. else if (status == MIDI_STATUS_NOTE_OFF)
  907. pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f);
  908. } break;
  909. }
  910. }
  911. pData->postRtEvents.trySplice();
  912. } // End of Event Input
  913. processSingle(audioIn, audioOut, cvIn, cvOut, frames);
  914. }
  915. bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames)
  916. {
  917. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  918. if (pData->audioIn.count > 0)
  919. {
  920. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  921. }
  922. if (pData->audioOut.count > 0)
  923. {
  924. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  925. }
  926. if (pData->cvIn.count > 0)
  927. {
  928. CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
  929. }
  930. if (pData->cvOut.count > 0)
  931. {
  932. CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
  933. }
  934. // --------------------------------------------------------------------------------------------------------
  935. // Try lock, silence otherwise
  936. if (pData->engine->isOffline())
  937. {
  938. pData->singleMutex.lock();
  939. }
  940. else if (! pData->singleMutex.tryLock())
  941. {
  942. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  943. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  944. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  945. FloatVectorOperations::clear(cvOut[i], static_cast<int>(frames));
  946. return false;
  947. }
  948. // --------------------------------------------------------------------------------------------------------
  949. // Reset audio buffers
  950. for (uint32_t i=0; i < fInfo.aIns; ++i)
  951. FloatVectorOperations::copy(fShmAudioPool.data + (i * frames), audioIn[i], static_cast<int>(frames));
  952. for (uint32_t i=0; i < fInfo.cvIns; ++i)
  953. FloatVectorOperations::copy(fShmCVPool.data + (i * frames), cvIn[i], static_cast<int>(frames));
  954. // --------------------------------------------------------------------------------------------------------
  955. // TimeInfo
  956. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  957. BridgeTimeInfo& bridgeTimeInfo(fShmRtControl.data->timeInfo);
  958. bridgeTimeInfo.playing = timeInfo.playing;
  959. bridgeTimeInfo.frame = timeInfo.frame;
  960. bridgeTimeInfo.usecs = timeInfo.usecs;
  961. bridgeTimeInfo.valid = timeInfo.valid;
  962. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  963. {
  964. bridgeTimeInfo.bar = timeInfo.bbt.bar;
  965. bridgeTimeInfo.beat = timeInfo.bbt.beat;
  966. bridgeTimeInfo.tick = timeInfo.bbt.tick;
  967. bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar;
  968. bridgeTimeInfo.beatType = timeInfo.bbt.beatType;
  969. bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  970. bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  971. bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick;
  972. }
  973. // --------------------------------------------------------------------------------------------------------
  974. // Run plugin
  975. {
  976. fShmRtControl.writeOpcode(kPluginBridgeRtProcess);
  977. fShmRtControl.commitWrite();
  978. }
  979. if (! waitForServer(2))
  980. {
  981. pData->singleMutex.unlock();
  982. return true;
  983. }
  984. for (uint32_t i=0; i < fInfo.aOuts; ++i)
  985. FloatVectorOperations::copy(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), static_cast<int>(frames));
  986. for (uint32_t i=0; i < fInfo.cvOuts; ++i)
  987. FloatVectorOperations::copy(cvOut[i], fShmCVPool.data + ((i + fInfo.cvIns) * frames), static_cast<int>(frames));
  988. // --------------------------------------------------------------------------------------------------------
  989. // Post-processing (dry/wet, volume and balance)
  990. {
  991. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && ! carla_compareFloats(pData->postProc.volume, 1.0f);
  992. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && ! carla_compareFloats(pData->postProc.dryWet, 1.0f);
  993. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_compareFloats(pData->postProc.balanceLeft, -1.0f) && carla_compareFloats(pData->postProc.balanceRight, 1.0f));
  994. bool isPair;
  995. float bufValue, oldBufLeft[doBalance ? frames : 1];
  996. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  997. {
  998. // Dry/Wet
  999. if (doDryWet)
  1000. {
  1001. for (uint32_t k=0; k < frames; ++k)
  1002. {
  1003. bufValue = audioIn[(pData->audioIn.count == 1) ? 0 : i][k];
  1004. audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1005. }
  1006. }
  1007. // Balance
  1008. if (doBalance)
  1009. {
  1010. isPair = (i % 2 == 0);
  1011. if (isPair)
  1012. {
  1013. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1014. FloatVectorOperations::copy(oldBufLeft, audioOut[i], static_cast<int>(frames));
  1015. }
  1016. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1017. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1018. for (uint32_t k=0; k < frames; ++k)
  1019. {
  1020. if (isPair)
  1021. {
  1022. // left
  1023. audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1024. audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR);
  1025. }
  1026. else
  1027. {
  1028. // right
  1029. audioOut[i][k] = audioOut[i][k] * balRangeR;
  1030. audioOut[i][k] += oldBufLeft[k] * balRangeL;
  1031. }
  1032. }
  1033. }
  1034. // Volume (and buffer copy)
  1035. if (doVolume)
  1036. {
  1037. for (uint32_t k=0; k < frames; ++k)
  1038. audioOut[i][k] *= pData->postProc.volume;
  1039. }
  1040. }
  1041. } // End of Post-processing
  1042. // --------------------------------------------------------------------------------------------------------
  1043. pData->singleMutex.unlock();
  1044. return true;
  1045. }
  1046. void bufferSizeChanged(const uint32_t newBufferSize) override
  1047. {
  1048. resizeAudioAndCVPool(newBufferSize);
  1049. {
  1050. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1051. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetBufferSize);
  1052. fShmNonRtControl.writeUInt(newBufferSize);
  1053. fShmNonRtControl.commitWrite();
  1054. }
  1055. fShmRtControl.waitForServer(1);
  1056. }
  1057. void sampleRateChanged(const double newSampleRate) override
  1058. {
  1059. {
  1060. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1061. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetSampleRate);
  1062. fShmNonRtControl.writeDouble(newSampleRate);
  1063. fShmNonRtControl.commitWrite();
  1064. }
  1065. fShmRtControl.waitForServer(1);
  1066. }
  1067. void offlineModeChanged(const bool isOffline) override
  1068. {
  1069. {
  1070. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1071. fShmNonRtControl.writeOpcode(isOffline ? kPluginBridgeNonRtSetOffline : kPluginBridgeNonRtSetOnline);
  1072. fShmNonRtControl.commitWrite();
  1073. }
  1074. fShmRtControl.waitForServer(1);
  1075. }
  1076. // -------------------------------------------------------------------
  1077. // Plugin buffers
  1078. void clearBuffers() noexcept override
  1079. {
  1080. if (fParams != nullptr)
  1081. {
  1082. delete[] fParams;
  1083. fParams = nullptr;
  1084. }
  1085. CarlaPlugin::clearBuffers();
  1086. }
  1087. // -------------------------------------------------------------------
  1088. // OSC stuff
  1089. void updateOscURL() override
  1090. {
  1091. const String newURL(String(pData->engine->getOscServerPathUDP()) + String("/") + String(pData->id));
  1092. const uint32_t ulength(static_cast<uint32_t>(newURL.length()));
  1093. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1094. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetOscURL);
  1095. fShmNonRtControl.writeUInt(ulength);
  1096. fShmNonRtControl.writeCustomData(newURL.toRawUTF8(), ulength);
  1097. fShmNonRtControl.commitWrite();
  1098. }
  1099. // -------------------------------------------------------------------
  1100. // Post-poned UI Stuff
  1101. void uiParameterChange(const uint32_t index, const float value) noexcept override
  1102. {
  1103. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  1104. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1105. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtUiParameterChange);
  1106. fShmNonRtControl.writeUInt(index);
  1107. fShmNonRtControl.writeFloat(value);
  1108. fShmNonRtControl.commitWrite();
  1109. }
  1110. void uiProgramChange(const uint32_t index) noexcept override
  1111. {
  1112. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1113. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1114. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtUiProgramChange);
  1115. fShmNonRtControl.writeUInt(index);
  1116. fShmNonRtControl.commitWrite();
  1117. }
  1118. void uiMidiProgramChange(const uint32_t index) noexcept override
  1119. {
  1120. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1121. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1122. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtUiMidiProgramChange);
  1123. fShmNonRtControl.writeUInt(index);
  1124. fShmNonRtControl.commitWrite();
  1125. }
  1126. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  1127. {
  1128. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1129. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1130. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1131. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1132. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtUiNoteOn);
  1133. fShmNonRtControl.writeByte(channel);
  1134. fShmNonRtControl.writeByte(note);
  1135. fShmNonRtControl.writeByte(velo);
  1136. fShmNonRtControl.commitWrite();
  1137. }
  1138. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  1139. {
  1140. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1141. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1142. const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
  1143. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtUiNoteOff);
  1144. fShmNonRtControl.writeByte(channel);
  1145. fShmNonRtControl.writeByte(note);
  1146. fShmNonRtControl.commitWrite();
  1147. }
  1148. // -------------------------------------------------------------------
  1149. int setOscPluginBridgeInfo(const PluginBridgeOscInfoType infoType, const int argc, const lo_arg* const* const argv, const char* const types)
  1150. {
  1151. #ifdef DEBUG
  1152. if (infoType != kPluginBridgeOscPong) {
  1153. carla_debug("BridgePlugin::setOscPluginBridgeInfo(%s, %i, %p, \"%s\")", PluginBridgeOscInfoType2str(infoType), argc, argv, types);
  1154. }
  1155. #endif
  1156. switch (infoType)
  1157. {
  1158. case kPluginBridgeOscNull:
  1159. break;
  1160. case kPluginBridgeOscPong:
  1161. if (fLastPongCounter > 0)
  1162. fLastPongCounter = 0;
  1163. break;
  1164. case kPluginBridgeOscPluginInfo1: {
  1165. CARLA_BRIDGE_CHECK_OSC_TYPES(5, "iiiih");
  1166. const int32_t category = argv[0]->i;
  1167. const int32_t hints = argv[1]->i;
  1168. const int32_t optionAv = argv[2]->i;
  1169. const int32_t optionEn = argv[3]->i;
  1170. const int64_t uniqueId = argv[4]->h;
  1171. CARLA_SAFE_ASSERT_BREAK(category >= 0);
  1172. CARLA_SAFE_ASSERT_BREAK(hints >= 0);
  1173. CARLA_SAFE_ASSERT_BREAK(optionAv >= 0);
  1174. CARLA_SAFE_ASSERT_BREAK(optionEn >= 0);
  1175. pData->hints = static_cast<uint>(hints);
  1176. pData->hints |= PLUGIN_IS_BRIDGE;
  1177. pData->options = static_cast<uint>(optionEn);
  1178. fInfo.category = static_cast<PluginCategory>(category);
  1179. fInfo.uniqueId = uniqueId;
  1180. fInfo.optionsAvailable = static_cast<uint>(optionAv);
  1181. break;
  1182. }
  1183. case kPluginBridgeOscPluginInfo2: {
  1184. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "ssss");
  1185. const char* const realName = (const char*)&argv[0]->s;
  1186. const char* const label = (const char*)&argv[1]->s;
  1187. const char* const maker = (const char*)&argv[2]->s;
  1188. const char* const copyright = (const char*)&argv[3]->s;
  1189. CARLA_SAFE_ASSERT_BREAK(realName != nullptr);
  1190. CARLA_SAFE_ASSERT_BREAK(label != nullptr);
  1191. CARLA_SAFE_ASSERT_BREAK(maker != nullptr);
  1192. CARLA_SAFE_ASSERT_BREAK(copyright != nullptr);
  1193. fInfo.name = realName;
  1194. fInfo.label = label;
  1195. fInfo.maker = maker;
  1196. fInfo.copyright = copyright;
  1197. if (pData->name == nullptr)
  1198. pData->name = pData->engine->getUniquePluginName(realName);
  1199. break;
  1200. }
  1201. case kPluginBridgeOscAudioCount: {
  1202. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ii");
  1203. const int32_t ins = argv[0]->i;
  1204. const int32_t outs = argv[1]->i;
  1205. CARLA_SAFE_ASSERT_BREAK(ins >= 0);
  1206. CARLA_SAFE_ASSERT_BREAK(outs >= 0);
  1207. fInfo.aIns = static_cast<uint32_t>(ins);
  1208. fInfo.aOuts = static_cast<uint32_t>(outs);
  1209. break;
  1210. }
  1211. case kPluginBridgeOscMidiCount: {
  1212. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ii");
  1213. const int32_t ins = argv[0]->i;
  1214. const int32_t outs = argv[1]->i;
  1215. CARLA_SAFE_ASSERT_BREAK(ins >= 0);
  1216. CARLA_SAFE_ASSERT_BREAK(outs >= 0);
  1217. fInfo.mIns = static_cast<uint32_t>(ins);
  1218. fInfo.mOuts = static_cast<uint32_t>(outs);
  1219. break;
  1220. }
  1221. case kPluginBridgeOscParameterCount: {
  1222. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ii");
  1223. const int32_t ins = argv[0]->i;
  1224. const int32_t outs = argv[1]->i;
  1225. CARLA_SAFE_ASSERT_BREAK(ins >= 0);
  1226. CARLA_SAFE_ASSERT_BREAK(outs >= 0);
  1227. // delete old data
  1228. pData->param.clear();
  1229. if (fParams != nullptr)
  1230. {
  1231. delete[] fParams;
  1232. fParams = nullptr;
  1233. }
  1234. if (int32_t count = ins+outs)
  1235. {
  1236. const int32_t maxParams(static_cast<int32_t>(pData->engine->getOptions().maxParameters));
  1237. if (count > maxParams)
  1238. {
  1239. count = maxParams;
  1240. carla_safe_assert_int2("count <= pData->engine->getOptions().maxParameters", __FILE__, __LINE__, count, maxParams);
  1241. }
  1242. const uint32_t ucount(static_cast<uint32_t>(count));
  1243. pData->param.createNew(ucount, false);
  1244. fParams = new BridgeParamInfo[ucount];
  1245. }
  1246. break;
  1247. }
  1248. case kPluginBridgeOscProgramCount: {
  1249. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1250. const int32_t count = argv[0]->i;
  1251. CARLA_SAFE_ASSERT_BREAK(count >= 0);
  1252. pData->prog.clear();
  1253. if (count > 0)
  1254. pData->prog.createNew(static_cast<uint32_t>(count));
  1255. break;
  1256. }
  1257. case kPluginBridgeOscMidiProgramCount: {
  1258. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1259. const int32_t count = argv[0]->i;
  1260. CARLA_SAFE_ASSERT_BREAK(count >= 0);
  1261. pData->midiprog.clear();
  1262. if (count > 0)
  1263. pData->midiprog.createNew(static_cast<uint32_t>(count));
  1264. break;
  1265. }
  1266. case kPluginBridgeOscParameterData1: {
  1267. CARLA_BRIDGE_CHECK_OSC_TYPES(5, "iiiii");
  1268. const int32_t index = argv[0]->i;
  1269. const int32_t rindex = argv[1]->i;
  1270. const int32_t type = argv[2]->i;
  1271. const int32_t hints = argv[3]->i;
  1272. const int32_t midiCC = argv[4]->i;
  1273. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1274. CARLA_SAFE_ASSERT_BREAK(rindex >= 0);
  1275. CARLA_SAFE_ASSERT_BREAK(type >= 0);
  1276. CARLA_SAFE_ASSERT_BREAK(hints >= 0);
  1277. CARLA_SAFE_ASSERT_BREAK(midiCC >= -1 && midiCC < 0x5F);
  1278. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1279. if (index < static_cast<int32_t>(pData->param.count))
  1280. {
  1281. pData->param.data[index].type = static_cast<ParameterType>(type);
  1282. pData->param.data[index].index = index;
  1283. pData->param.data[index].rindex = rindex;
  1284. pData->param.data[index].hints = static_cast<uint>(hints);
  1285. pData->param.data[index].midiCC = static_cast<int16_t>(midiCC);
  1286. }
  1287. break;
  1288. }
  1289. case kPluginBridgeOscParameterData2: {
  1290. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
  1291. const int32_t index = argv[0]->i;
  1292. const char* const name = (const char*)&argv[1]->s;
  1293. const char* const unit = (const char*)&argv[2]->s;
  1294. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1295. CARLA_SAFE_ASSERT_BREAK(name != nullptr);
  1296. CARLA_SAFE_ASSERT_BREAK(unit != nullptr);
  1297. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1298. if (index < static_cast<int32_t>(pData->param.count))
  1299. {
  1300. fParams[index].name = name;
  1301. fParams[index].unit = unit;
  1302. }
  1303. break;
  1304. }
  1305. case kPluginBridgeOscParameterRanges1: {
  1306. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "ifff");
  1307. const int32_t index = argv[0]->i;
  1308. const float def = argv[1]->f;
  1309. const float min = argv[2]->f;
  1310. const float max = argv[3]->f;
  1311. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1312. CARLA_SAFE_ASSERT_BREAK(min < max);
  1313. CARLA_SAFE_ASSERT_BREAK(def >= min);
  1314. CARLA_SAFE_ASSERT_BREAK(def <= max);
  1315. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1316. if (index < static_cast<int32_t>(pData->param.count))
  1317. {
  1318. pData->param.ranges[index].def = def;
  1319. pData->param.ranges[index].min = min;
  1320. pData->param.ranges[index].max = max;
  1321. }
  1322. break;
  1323. }
  1324. case kPluginBridgeOscParameterRanges2: {
  1325. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "ifff");
  1326. const int32_t index = argv[0]->i;
  1327. const float step = argv[1]->f;
  1328. const float stepSmall = argv[2]->f;
  1329. const float stepLarge = argv[3]->f;
  1330. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1331. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1332. if (index < static_cast<int32_t>(pData->param.count))
  1333. {
  1334. pData->param.ranges[index].step = step;
  1335. pData->param.ranges[index].stepSmall = stepSmall;
  1336. pData->param.ranges[index].stepLarge = stepLarge;
  1337. }
  1338. break;
  1339. }
  1340. case kPluginBridgeOscParameterValue: {
  1341. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "if");
  1342. const int32_t index = argv[0]->i;
  1343. const float value = argv[1]->f;
  1344. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1345. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1346. if (index < static_cast<int32_t>(pData->param.count))
  1347. {
  1348. const uint32_t uindex(static_cast<uint32_t>(index));
  1349. const float fixedValue(pData->param.getFixedValue(uindex, value));
  1350. fParams[uindex].value = fixedValue;
  1351. CarlaPlugin::setParameterValue(uindex, fixedValue, false, true, true);
  1352. }
  1353. break;
  1354. }
  1355. case kPluginBridgeOscDefaultValue: {
  1356. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "if");
  1357. const int32_t index = argv[0]->i;
  1358. const float value = argv[1]->f;
  1359. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1360. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1361. if (index < static_cast<int32_t>(pData->param.count))
  1362. pData->param.ranges[index].def = value;
  1363. break;
  1364. }
  1365. case kPluginBridgeOscCurrentProgram: {
  1366. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1367. const int32_t index = argv[0]->i;
  1368. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1369. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1370. CarlaPlugin::setProgram(index, false, true, true);
  1371. break;
  1372. }
  1373. case kPluginBridgeOscCurrentMidiProgram: {
  1374. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1375. const int32_t index = argv[0]->i;
  1376. CARLA_SAFE_ASSERT_BREAK(index >= -1);
  1377. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1378. CarlaPlugin::setMidiProgram(index, false, true, true);
  1379. break;
  1380. }
  1381. case kPluginBridgeOscProgramName: {
  1382. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "is");
  1383. const int32_t index = argv[0]->i;
  1384. const char* const name = (const char*)&argv[1]->s;
  1385. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1386. CARLA_SAFE_ASSERT_BREAK(name != nullptr);
  1387. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1388. if (index < static_cast<int32_t>(pData->prog.count))
  1389. {
  1390. if (pData->prog.names[index] != nullptr)
  1391. delete[] pData->prog.names[index];
  1392. pData->prog.names[index] = carla_strdup(name);
  1393. }
  1394. break;
  1395. }
  1396. case kPluginBridgeOscMidiProgramData: {
  1397. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "iiis");
  1398. const int32_t index = argv[0]->i;
  1399. const int32_t bank = argv[1]->i;
  1400. const int32_t program = argv[2]->i;
  1401. const char* const name = (const char*)&argv[3]->s;
  1402. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  1403. CARLA_SAFE_ASSERT_BREAK(bank >= 0);
  1404. CARLA_SAFE_ASSERT_BREAK(program >= 0);
  1405. CARLA_SAFE_ASSERT_BREAK(name != nullptr);
  1406. CARLA_SAFE_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1407. if (index < static_cast<int32_t>(pData->midiprog.count))
  1408. {
  1409. if (pData->midiprog.data[index].name != nullptr)
  1410. delete[] pData->midiprog.data[index].name;
  1411. pData->midiprog.data[index].bank = static_cast<uint32_t>(bank);
  1412. pData->midiprog.data[index].program = static_cast<uint32_t>(program);
  1413. pData->midiprog.data[index].name = carla_strdup(name);
  1414. }
  1415. break;
  1416. }
  1417. case kPluginBridgeOscConfigure: {
  1418. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");
  1419. const char* const key = (const char*)&argv[0]->s;
  1420. const char* const value = (const char*)&argv[1]->s;
  1421. CARLA_SAFE_ASSERT_BREAK(key != nullptr);
  1422. CARLA_SAFE_ASSERT_BREAK(value != nullptr);
  1423. if (std::strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
  1424. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  1425. else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
  1426. fSaved = true;
  1427. break;
  1428. }
  1429. case kPluginBridgeOscSetCustomData: {
  1430. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");
  1431. const char* const type = (const char*)&argv[0]->s;
  1432. const char* const key = (const char*)&argv[1]->s;
  1433. const char* const value = (const char*)&argv[2]->s;
  1434. CARLA_SAFE_ASSERT_BREAK(type != nullptr);
  1435. CARLA_SAFE_ASSERT_BREAK(key != nullptr);
  1436. CARLA_SAFE_ASSERT_BREAK(value != nullptr);
  1437. CarlaPlugin::setCustomData(type, key, value, false);
  1438. break;
  1439. }
  1440. case kPluginBridgeOscSetChunkDataFile: {
  1441. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  1442. const char* const chunkFilePath = (const char*)&argv[0]->s;
  1443. CARLA_SAFE_ASSERT_BREAK(chunkFilePath != nullptr);
  1444. String realChunkFilePath(chunkFilePath);
  1445. carla_stdout("chunk save path BEFORE => %s", realChunkFilePath.toRawUTF8());
  1446. #ifndef CARLA_OS_WIN
  1447. // Using Wine, fix temp dir
  1448. if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
  1449. {
  1450. // Get WINEPREFIX
  1451. String wineDir;
  1452. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  1453. wineDir = String(WINEPREFIX);
  1454. else
  1455. wineDir = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine";
  1456. const StringArray driveLetterSplit(StringArray::fromTokens(realChunkFilePath, ":/", ""));
  1457. realChunkFilePath = wineDir;
  1458. realChunkFilePath += "/drive_";
  1459. realChunkFilePath += driveLetterSplit[0].toLowerCase();
  1460. realChunkFilePath += "/";
  1461. realChunkFilePath += driveLetterSplit[1];
  1462. realChunkFilePath = realChunkFilePath.replace("\\", "/");
  1463. carla_stdout("chunk save path AFTER => %s", realChunkFilePath.toRawUTF8());
  1464. }
  1465. #endif
  1466. File chunkFile(realChunkFilePath);
  1467. if (chunkFile.existsAsFile())
  1468. {
  1469. fInfo.chunk = carla_getChunkFromBase64String(chunkFile.loadFileAsString().toRawUTF8());
  1470. chunkFile.deleteFile();
  1471. carla_stderr("chunk data final");
  1472. }
  1473. break;
  1474. }
  1475. case kPluginBridgeOscLatency:
  1476. // TODO
  1477. break;
  1478. case kPluginBridgeOscReady:
  1479. fInitiated = true;
  1480. break;
  1481. case kPluginBridgeOscError: {
  1482. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  1483. const char* const error = (const char*)&argv[0]->s;
  1484. CARLA_ASSERT(error != nullptr);
  1485. pData->engine->setLastError(error);
  1486. fInitError = true;
  1487. fInitiated = true;
  1488. break;
  1489. }
  1490. }
  1491. return 0;
  1492. }
  1493. // -------------------------------------------------------------------
  1494. const void* getExtraStuff() const noexcept override
  1495. {
  1496. return fBridgeBinary.isNotEmpty() ? fBridgeBinary.buffer() : nullptr;
  1497. }
  1498. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  1499. {
  1500. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  1501. // ---------------------------------------------------------------
  1502. // first checks
  1503. if (pData->client != nullptr)
  1504. {
  1505. pData->engine->setLastError("Plugin client is already registered");
  1506. return false;
  1507. }
  1508. // ---------------------------------------------------------------
  1509. // set info
  1510. if (name != nullptr && name[0] != '\0')
  1511. pData->name = pData->engine->getUniquePluginName(name);
  1512. pData->filename = carla_strdup(filename);
  1513. if (bridgeBinary != nullptr)
  1514. fBridgeBinary = bridgeBinary;
  1515. std::srand(static_cast<uint>(std::time(nullptr)));
  1516. // ---------------------------------------------------------------
  1517. // SHM Audio Pool
  1518. {
  1519. char tmpFileBase[64];
  1520. std::sprintf(tmpFileBase, "/carla-bridge_shm_ap_XXXXXX");
  1521. fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
  1522. if (! carla_is_shm_valid(fShmAudioPool.shm))
  1523. {
  1524. carla_stdout("Failed to open or create shared memory file #1");
  1525. return false;
  1526. }
  1527. fShmAudioPool.filename = tmpFileBase;
  1528. }
  1529. // ---------------------------------------------------------------
  1530. // SHM RT Control
  1531. {
  1532. char tmpFileBase[64];
  1533. std::sprintf(tmpFileBase, "/carla-bridge_shm_rt_XXXXXX");
  1534. fShmRtControl.shm = shm_mkstemp(tmpFileBase);
  1535. if (! carla_is_shm_valid(fShmRtControl.shm))
  1536. {
  1537. carla_stdout("Failed to open or create shared memory file #2");
  1538. // clear
  1539. carla_shm_close(fShmAudioPool.shm);
  1540. return false;
  1541. }
  1542. fShmRtControl.filename = tmpFileBase;
  1543. if (! fShmRtControl.mapData())
  1544. {
  1545. carla_stdout("Failed to map shared memory file #2");
  1546. // clear
  1547. carla_shm_close(fShmRtControl.shm);
  1548. carla_shm_close(fShmAudioPool.shm);
  1549. return false;
  1550. }
  1551. CARLA_SAFE_ASSERT(fShmRtControl.data != nullptr);
  1552. if (! jackbridge_sem_init(&fShmRtControl.data->sem.server))
  1553. {
  1554. carla_stdout("Failed to initialize shared memory semaphore #1");
  1555. // clear
  1556. fShmRtControl.unmapData();
  1557. carla_shm_close(fShmRtControl.shm);
  1558. carla_shm_close(fShmAudioPool.shm);
  1559. return false;
  1560. }
  1561. if (! jackbridge_sem_init(&fShmRtControl.data->sem.client))
  1562. {
  1563. carla_stdout("Failed to initialize shared memory semaphore #2");
  1564. // clear
  1565. jackbridge_sem_destroy(&fShmRtControl.data->sem.server);
  1566. fShmRtControl.unmapData();
  1567. carla_shm_close(fShmRtControl.shm);
  1568. carla_shm_close(fShmAudioPool.shm);
  1569. return false;
  1570. }
  1571. fNeedsSemDestroy = true;
  1572. }
  1573. // ---------------------------------------------------------------
  1574. // SHM Non-RT Control
  1575. {
  1576. char tmpFileBase[64];
  1577. std::sprintf(tmpFileBase, "/carla-bridge_shm_nonrt_XXXXXX");
  1578. fShmNonRtControl.shm = shm_mkstemp(tmpFileBase);
  1579. if (! carla_is_shm_valid(fShmNonRtControl.shm))
  1580. {
  1581. carla_stdout("Failed to open or create shared memory file #3");
  1582. return false;
  1583. }
  1584. fShmNonRtControl.filename = tmpFileBase;
  1585. if (! fShmNonRtControl.mapData())
  1586. {
  1587. carla_stdout("Failed to map shared memory file #3");
  1588. // clear
  1589. fShmNonRtControl.unmapData();
  1590. carla_shm_close(fShmNonRtControl.shm);
  1591. carla_shm_close(fShmRtControl.shm);
  1592. carla_shm_close(fShmAudioPool.shm);
  1593. return false;
  1594. }
  1595. }
  1596. carla_stdout("Carla Server Info:");
  1597. carla_stdout(" sizeof(BridgeRtData): " P_SIZE, sizeof(BridgeRtData));
  1598. carla_stdout(" sizeof(BridgeNonRtData): " P_SIZE, sizeof(BridgeNonRtData));
  1599. // initial values
  1600. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtNull);
  1601. fShmNonRtControl.writeInt(static_cast<int32_t>(sizeof(BridgeRtData)));
  1602. fShmNonRtControl.writeInt(static_cast<int32_t>(sizeof(BridgeNonRtData)));
  1603. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetBufferSize);
  1604. fShmNonRtControl.writeInt(static_cast<int32_t>(pData->engine->getBufferSize()));
  1605. fShmNonRtControl.writeOpcode(kPluginBridgeNonRtSetSampleRate);
  1606. fShmNonRtControl.writeDouble(pData->engine->getSampleRate());
  1607. fShmNonRtControl.commitWrite();
  1608. // register plugin now so we can receive OSC (and wait for it)
  1609. pData->hints |= PLUGIN_IS_BRIDGE;
  1610. pData->engine->registerEnginePlugin(pData->id, this);
  1611. // init OSC
  1612. {
  1613. char shmIdStr[18+1] = { 0 };
  1614. std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  1615. std::strncat(shmIdStr, &fShmRtControl.filename[fShmRtControl.filename.length()-6], 6);
  1616. std::strncat(shmIdStr, &fShmNonRtControl.filename[fShmNonRtControl.filename.length()-6], 6);
  1617. pData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
  1618. pData->osc.thread.startThread();
  1619. }
  1620. fInitiated = false;
  1621. fLastPongCounter = 0;
  1622. for (; fLastPongCounter++ < 500;)
  1623. {
  1624. if (fInitiated || ! pData->osc.thread.isThreadRunning())
  1625. break;
  1626. carla_msleep(25);
  1627. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  1628. pData->engine->idle();
  1629. }
  1630. fLastPongCounter = -1;
  1631. if (fInitError || ! fInitiated)
  1632. {
  1633. pData->osc.thread.stopThread(6000);
  1634. if (! fInitError)
  1635. pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  1636. return false;
  1637. }
  1638. // ---------------------------------------------------------------
  1639. // register client
  1640. if (pData->name == nullptr)
  1641. {
  1642. if (name != nullptr && name[0] != '\0')
  1643. pData->name = pData->engine->getUniquePluginName(name);
  1644. else if (label != nullptr && label[0] != '\0')
  1645. pData->name = pData->engine->getUniquePluginName(label);
  1646. else
  1647. pData->name = pData->engine->getUniquePluginName("unknown");
  1648. }
  1649. pData->client = pData->engine->addClient(this);
  1650. if (pData->client == nullptr || ! pData->client->isOk())
  1651. {
  1652. pData->engine->setLastError("Failed to register plugin client");
  1653. return false;
  1654. }
  1655. return true;
  1656. }
  1657. private:
  1658. const BinaryType fBinaryType;
  1659. const PluginType fPluginType;
  1660. bool fInitiated;
  1661. bool fInitError;
  1662. bool fSaved;
  1663. bool fNeedsSemDestroy;
  1664. bool fTimedOut;
  1665. volatile int32_t fLastPongCounter;
  1666. CarlaString fBridgeBinary;
  1667. BridgeAudioPool fShmAudioPool;
  1668. BridgeAudioPool fShmCVPool;
  1669. BridgeRtControl fShmRtControl;
  1670. BridgeNonRtControl fShmNonRtControl;
  1671. struct Info {
  1672. uint32_t aIns, aOuts;
  1673. uint32_t cvIns, cvOuts;
  1674. uint32_t mIns, mOuts;
  1675. PluginCategory category;
  1676. uint optionsAvailable;
  1677. int64_t uniqueId;
  1678. CarlaString name;
  1679. CarlaString label;
  1680. CarlaString maker;
  1681. CarlaString copyright;
  1682. std::vector<uint8_t> chunk;
  1683. Info()
  1684. : aIns(0),
  1685. aOuts(0),
  1686. cvIns(0),
  1687. cvOuts(0),
  1688. mIns(0),
  1689. mOuts(0),
  1690. category(PLUGIN_CATEGORY_NONE),
  1691. optionsAvailable(0),
  1692. uniqueId(0),
  1693. name(),
  1694. label(),
  1695. maker(),
  1696. copyright(),
  1697. chunk() {}
  1698. } fInfo;
  1699. BridgeParamInfo* fParams;
  1700. void resizeAudioAndCVPool(const uint32_t bufferSize)
  1701. {
  1702. fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts);
  1703. fShmCVPool.resize(bufferSize, fInfo.cvIns+fInfo.cvOuts);
  1704. fShmRtControl.writeOpcode(kPluginBridgeRtSetAudioPool);
  1705. fShmRtControl.writeLong(static_cast<int64_t>(fShmAudioPool.size));
  1706. fShmRtControl.writeOpcode(kPluginBridgeRtSetCVPool);
  1707. fShmRtControl.writeLong(static_cast<int64_t>(fShmCVPool.size));
  1708. fShmRtControl.commitWrite();
  1709. waitForServer();
  1710. }
  1711. bool waitForServer(const int secs = 5)
  1712. {
  1713. CARLA_SAFE_ASSERT_RETURN(! fTimedOut, false);
  1714. if (! fShmRtControl.waitForServer(secs))
  1715. {
  1716. carla_stderr("waitForServer() timeout here");
  1717. fTimedOut = true;
  1718. return false;
  1719. }
  1720. return true;
  1721. }
  1722. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
  1723. };
  1724. CARLA_BACKEND_END_NAMESPACE
  1725. #endif // ! BUILD_BRIDGE
  1726. // -------------------------------------------------------------------------------------------------------------------
  1727. CARLA_BACKEND_START_NAMESPACE
  1728. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
  1729. {
  1730. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1731. #ifndef BUILD_BRIDGE
  1732. if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
  1733. {
  1734. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1735. return nullptr;
  1736. }
  1737. BridgePlugin* const plugin(new BridgePlugin(init.engine, init.id, btype, ptype));
  1738. if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
  1739. {
  1740. init.engine->registerEnginePlugin(init.id, nullptr);
  1741. delete plugin;
  1742. return nullptr;
  1743. }
  1744. plugin->reload();
  1745. bool canRun = true;
  1746. if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  1747. {
  1748. if (! plugin->canRunInRack())
  1749. {
  1750. init.engine->setLastError("Carla's rack mode can only work with Stereo Bridged plugins, sorry!");
  1751. canRun = false;
  1752. }
  1753. else if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0)
  1754. {
  1755. init.engine->setLastError("Carla's rack mode cannot work with plugins that have CV ports, sorry!");
  1756. canRun = false;
  1757. }
  1758. }
  1759. else if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_PATCHBAY && (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0))
  1760. {
  1761. init.engine->setLastError("CV ports in patchbay mode is still TODO");
  1762. canRun = false;
  1763. }
  1764. if (! canRun)
  1765. {
  1766. delete plugin;
  1767. return nullptr;
  1768. }
  1769. return plugin;
  1770. #else
  1771. init.engine->setLastError("Plugin bridge support not available");
  1772. return nullptr;
  1773. // unused
  1774. (void)bridgeBinary;
  1775. #endif
  1776. }
  1777. #ifndef BUILD_BRIDGE
  1778. // -------------------------------------------------------------------------------------------------------------------
  1779. // Bridge Helper
  1780. #define bridgePlugin ((BridgePlugin*)plugin)
  1781. extern int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeOscInfoType type,
  1782. const int argc, const lo_arg* const* const argv, const char* const types);
  1783. int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeOscInfoType type,
  1784. const int argc, const lo_arg* const* const argv, const char* const types)
  1785. {
  1786. CARLA_SAFE_ASSERT(plugin != nullptr && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0);
  1787. return bridgePlugin->setOscPluginBridgeInfo(type, argc, argv, types);
  1788. }
  1789. #undef bridgePlugin
  1790. #endif
  1791. CARLA_BACKEND_END_NAMESPACE
  1792. // -------------------------------------------------------------------------------------------------------------------