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

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968
  1. /*
  2. * Carla Bridge Plugin
  3. * Copyright (C) 2011-2013 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. #ifndef BUILD_BRIDGE
  19. #include "CarlaBridgeUtils.hpp"
  20. #include "CarlaShmUtils.hpp"
  21. #include "jackbridge/JackBridge.hpp"
  22. #include <cerrno>
  23. #include <cmath>
  24. #include <ctime>
  25. #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
  26. /* check argument count */ \
  27. if (argc != argcToCompare) \
  28. { \
  29. carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \
  30. return 1; \
  31. } \
  32. if (argc > 0) \
  33. { \
  34. /* check for nullness */ \
  35. if (! (types && typesToCompare)) \
  36. { \
  37. carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \
  38. return 1; \
  39. } \
  40. /* check argument types */ \
  41. if (std::strcmp(types, typesToCompare) != 0) \
  42. { \
  43. carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \
  44. return 1; \
  45. } \
  46. }
  47. CARLA_BACKEND_START_NAMESPACE
  48. // -------------------------------------------------------------------------------------------------------------------
  49. shm_t shm_mkstemp(char* const fileBase)
  50. {
  51. static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
  52. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  53. "0123456789";
  54. const size_t fileBaseLen((fileBase != nullptr) ? std::strlen(fileBase) : 0);
  55. shm_t fakeShm;
  56. carla_shm_init(fakeShm);
  57. if (fileBaseLen < 6)
  58. {
  59. errno = EINVAL;
  60. return fakeShm;
  61. }
  62. if (std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") != 0)
  63. {
  64. errno = EINVAL;
  65. return fakeShm;
  66. }
  67. for (;;)
  68. {
  69. for (size_t c = fileBaseLen - 6; c < fileBaseLen; ++c)
  70. {
  71. // Note the -1 to avoid the trailing '\0' in charSet.
  72. fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)];
  73. }
  74. shm_t shm = carla_shm_create(fileBase);
  75. if (carla_is_shm_valid(shm) || errno != EEXIST)
  76. return shm;
  77. }
  78. }
  79. // -------------------------------------------------------------------------------------------------------------------
  80. struct BridgeAudioPool {
  81. CarlaString filename;
  82. float* data;
  83. size_t size;
  84. shm_t shm;
  85. BridgeAudioPool()
  86. : data(nullptr),
  87. size(0)
  88. {
  89. carla_shm_init(shm);
  90. }
  91. ~BridgeAudioPool()
  92. {
  93. // should be cleared by now
  94. CARLA_ASSERT(data == nullptr);
  95. clear();
  96. }
  97. void clear()
  98. {
  99. filename.clear();
  100. if (! carla_is_shm_valid(shm))
  101. return;
  102. if (data != nullptr)
  103. {
  104. carla_shm_unmap(shm, data, size);
  105. data = nullptr;
  106. }
  107. size = 0;
  108. carla_shm_close(shm);
  109. }
  110. void resize(const uint32_t bufferSize, const uint32_t portCount)
  111. {
  112. if (data != nullptr)
  113. carla_shm_unmap(shm, data, size);
  114. size = portCount*bufferSize*sizeof(float);
  115. if (size == 0)
  116. size = sizeof(float);
  117. data = (float*)carla_shm_map(shm, size);
  118. }
  119. };
  120. struct BridgeControl : public RingBufferControl {
  121. CarlaString filename;
  122. BridgeShmControl* data;
  123. shm_t shm;
  124. BridgeControl()
  125. : RingBufferControl(nullptr),
  126. data(nullptr)
  127. {
  128. carla_shm_init(shm);
  129. }
  130. ~BridgeControl()
  131. {
  132. // should be cleared by now
  133. CARLA_ASSERT(data == nullptr);
  134. clear();
  135. }
  136. void clear()
  137. {
  138. filename.clear();
  139. if (! carla_is_shm_valid(shm))
  140. return;
  141. if (data != nullptr)
  142. {
  143. carla_shm_unmap(shm, data, sizeof(BridgeShmControl));
  144. data = nullptr;
  145. }
  146. carla_shm_close(shm);
  147. }
  148. bool mapData()
  149. {
  150. CARLA_ASSERT(data == nullptr);
  151. if (carla_shm_map<BridgeShmControl>(shm, data))
  152. {
  153. setRingBuffer(&data->ringBuffer, true);
  154. return true;
  155. }
  156. return false;
  157. }
  158. void unmapData()
  159. {
  160. CARLA_ASSERT(data != nullptr);
  161. if (data == nullptr)
  162. return;
  163. carla_shm_unmap(shm, data, sizeof(BridgeShmControl));
  164. data = nullptr;
  165. setRingBuffer(nullptr, false);
  166. }
  167. bool waitForServer()
  168. {
  169. CARLA_ASSERT(data != nullptr);
  170. if (data == nullptr)
  171. return false;
  172. jackbridge_sem_post(&data->runServer);
  173. return jackbridge_sem_timedwait(&data->runClient, 5);
  174. }
  175. void writeOpcode(const PluginBridgeOpcode opcode)
  176. {
  177. writeInt(static_cast<int>(opcode));
  178. }
  179. };
  180. struct BridgeParamInfo {
  181. float value;
  182. CarlaString name;
  183. CarlaString unit;
  184. BridgeParamInfo()
  185. : value(0.0f) {}
  186. CARLA_DECLARE_NON_COPY_STRUCT(BridgeParamInfo)
  187. };
  188. // -------------------------------------------------------------------------------------------------------------------
  189. class BridgePlugin : public CarlaPlugin
  190. {
  191. public:
  192. BridgePlugin(CarlaEngine* const engine, const unsigned int id, const BinaryType btype, const PluginType ptype)
  193. : CarlaPlugin(engine, id),
  194. fBinaryType(btype),
  195. fPluginType(ptype),
  196. fInitiated(false),
  197. fInitError(false),
  198. fSaved(false),
  199. fNeedsSemDestroy(false),
  200. fParams(nullptr)
  201. {
  202. carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  203. pData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  204. pData->hints |= PLUGIN_IS_BRIDGE;
  205. }
  206. ~BridgePlugin() override
  207. {
  208. carla_debug("BridgePlugin::~BridgePlugin()");
  209. pData->singleMutex.lock();
  210. pData->masterMutex.lock();
  211. if (pData->client != nullptr && pData->client->isActive())
  212. pData->client->deactivate();
  213. if (pData->active)
  214. {
  215. deactivate();
  216. pData->active = false;
  217. }
  218. if (pData->osc.thread.isRunning())
  219. {
  220. fShmControl.writeOpcode(kPluginBridgeOpcodeQuit);
  221. fShmControl.commitWrite();
  222. fShmControl.waitForServer();
  223. }
  224. if (pData->osc.data.target != nullptr)
  225. {
  226. osc_send_hide(pData->osc.data);
  227. osc_send_quit(pData->osc.data);
  228. }
  229. pData->osc.data.free();
  230. pData->osc.thread.stop(6000);
  231. if (fNeedsSemDestroy)
  232. {
  233. jackbridge_sem_destroy(&fShmControl.data->runServer);
  234. jackbridge_sem_destroy(&fShmControl.data->runClient);
  235. }
  236. fShmAudioPool.clear();
  237. fShmControl.clear();
  238. clearBuffers();
  239. //info.chunk.clear();
  240. }
  241. // -------------------------------------------------------------------
  242. // Information (base)
  243. BinaryType getBinaryType() const noexcept
  244. {
  245. return fBinaryType;
  246. }
  247. PluginType getType() const noexcept override
  248. {
  249. return fPluginType;
  250. }
  251. PluginCategory getCategory() const override
  252. {
  253. return fInfo.category;
  254. }
  255. long getUniqueId() const noexcept override
  256. {
  257. return fInfo.uniqueId;
  258. }
  259. // -------------------------------------------------------------------
  260. // Information (count)
  261. uint32_t getMidiInCount() const noexcept override
  262. {
  263. return fInfo.mIns;
  264. }
  265. uint32_t getMidiOutCount() const noexcept override
  266. {
  267. return fInfo.mOuts;
  268. }
  269. // -------------------------------------------------------------------
  270. // Information (current data)
  271. int32_t getChunkData(void** const dataPtr) const override
  272. {
  273. CARLA_ASSERT(pData->options & PLUGIN_OPTION_USE_CHUNKS);
  274. CARLA_ASSERT(dataPtr != nullptr);
  275. #if 0
  276. if (! info.chunk.isEmpty())
  277. {
  278. *dataPtr = info.chunk.data();
  279. return info.chunk.size();
  280. }
  281. #endif
  282. return 0;
  283. }
  284. // -------------------------------------------------------------------
  285. // Information (per-plugin data)
  286. unsigned int getOptionsAvailable() const override
  287. {
  288. unsigned int options = 0x0;
  289. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  290. options |= PLUGIN_OPTION_USE_CHUNKS;
  291. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  292. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  293. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  294. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  295. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  296. return options;
  297. }
  298. float getParameterValue(const uint32_t parameterId) const override
  299. {
  300. CARLA_ASSERT(parameterId < pData->param.count);
  301. return fParams[parameterId].value;
  302. }
  303. void getLabel(char* const strBuf) const override
  304. {
  305. std::strncpy(strBuf, (const char*)fInfo.label, STR_MAX);
  306. }
  307. void getMaker(char* const strBuf) const override
  308. {
  309. std::strncpy(strBuf, (const char*)fInfo.maker, STR_MAX);
  310. }
  311. void getCopyright(char* const strBuf) const override
  312. {
  313. std::strncpy(strBuf, (const char*)fInfo.copyright, STR_MAX);
  314. }
  315. void getRealName(char* const strBuf) const override
  316. {
  317. std::strncpy(strBuf, (const char*)fInfo.name, STR_MAX);
  318. }
  319. void getParameterName(const uint32_t parameterId, char* const strBuf) const override
  320. {
  321. CARLA_ASSERT(parameterId < pData->param.count);
  322. std::strncpy(strBuf, (const char*)fParams[parameterId].name, STR_MAX);
  323. }
  324. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const override
  325. {
  326. CARLA_ASSERT(parameterId < pData->param.count);
  327. std::strncpy(strBuf, (const char*)fParams[parameterId].unit, STR_MAX);
  328. }
  329. // -------------------------------------------------------------------
  330. // Set data (state)
  331. void prepareForSave() override
  332. {
  333. #if 0
  334. m_saved = false;
  335. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SAVE_NOW, "");
  336. for (int i=0; i < 200; ++i)
  337. {
  338. if (m_saved)
  339. break;
  340. carla_msleep(50);
  341. }
  342. if (! m_saved)
  343. carla_stderr("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  344. else
  345. carla_debug("BridgePlugin::prepareForSave() - success!");
  346. #endif
  347. }
  348. // -------------------------------------------------------------------
  349. // Set data (internal stuff)
  350. // nothing
  351. // -------------------------------------------------------------------
  352. // Set data (plugin-specific stuff)
  353. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  354. {
  355. CARLA_ASSERT(parameterId < pData->param.count);
  356. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  357. fParams[parameterId].value = fixedValue;
  358. const bool doLock(sendGui || sendOsc || sendCallback);
  359. if (doLock)
  360. pData->singleMutex.lock();
  361. fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter);
  362. fShmControl.writeInt(parameterId);
  363. fShmControl.writeFloat(value);
  364. if (doLock)
  365. {
  366. fShmControl.commitWrite();
  367. pData->singleMutex.unlock();
  368. }
  369. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  370. }
  371. void setProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  372. {
  373. CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(pData->prog.count));
  374. if (index < -1)
  375. index = -1;
  376. else if (index > static_cast<int32_t>(pData->prog.count))
  377. return;
  378. const bool doLock(sendGui || sendOsc || sendCallback);
  379. if (doLock)
  380. pData->singleMutex.lock();
  381. fShmControl.writeOpcode(kPluginBridgeOpcodeSetProgram);
  382. fShmControl.writeInt(index);
  383. if (doLock)
  384. {
  385. fShmControl.commitWrite();
  386. pData->singleMutex.unlock();
  387. }
  388. CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback);
  389. }
  390. void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  391. {
  392. CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count));
  393. if (index < -1)
  394. index = -1;
  395. else if (index > static_cast<int32_t>(pData->midiprog.count))
  396. return;
  397. const bool doLock(sendGui || sendOsc || sendCallback);
  398. if (doLock)
  399. pData->singleMutex.lock();
  400. fShmControl.writeOpcode(kPluginBridgeOpcodeSetMidiProgram);
  401. fShmControl.writeInt(index);
  402. if (doLock)
  403. {
  404. fShmControl.commitWrite();
  405. pData->singleMutex.unlock();
  406. }
  407. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  408. }
  409. #if 0
  410. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  411. {
  412. CARLA_ASSERT(type);
  413. CARLA_ASSERT(key);
  414. CARLA_ASSERT(value);
  415. if (sendGui)
  416. {
  417. // TODO - if type is chunk|binary, store it in a file and send path instead
  418. QString cData;
  419. cData = type;
  420. cData += "·";
  421. cData += key;
  422. cData += "·";
  423. cData += value;
  424. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  425. }
  426. CarlaPlugin::setCustomData(type, key, value, sendGui);
  427. }
  428. void setChunkData(const char* const stringData) override
  429. {
  430. CARLA_ASSERT(m_hints & PLUGIN_USES_CHUNKS);
  431. CARLA_ASSERT(stringData);
  432. QString filePath;
  433. filePath = QDir::tempPath();
  434. filePath += "/.CarlaChunk_";
  435. filePath += m_name;
  436. filePath = QDir::toNativeSeparators(filePath);
  437. QFile file(filePath);
  438. if (file.open(QIODevice::WriteOnly | QIODevice::Text))
  439. {
  440. QTextStream out(&file);
  441. out << stringData;
  442. file.close();
  443. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
  444. }
  445. }
  446. #endif
  447. // -------------------------------------------------------------------
  448. // Set gui stuff
  449. void showCustomUI(const bool yesNo) override
  450. {
  451. if (yesNo)
  452. osc_send_show(pData->osc.data);
  453. else
  454. osc_send_hide(pData->osc.data);
  455. }
  456. void idle() override
  457. {
  458. if (! pData->osc.thread.isRunning())
  459. carla_stderr2("TESTING: Bridge has closed!");
  460. CarlaPlugin::idle();
  461. }
  462. // -------------------------------------------------------------------
  463. // Plugin state
  464. void reload() override
  465. {
  466. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  467. carla_debug("BridgePlugin::reload() - start");
  468. const EngineProcessMode processMode(pData->engine->getProccessMode());
  469. // Safely disable plugin for reload
  470. const ScopedDisabler sd(this);
  471. bool needsCtrlIn, needsCtrlOut;
  472. needsCtrlIn = needsCtrlOut = false;
  473. if (fInfo.aIns > 0)
  474. {
  475. pData->audioIn.createNew(fInfo.aIns);
  476. }
  477. if (fInfo.aOuts > 0)
  478. {
  479. pData->audioOut.createNew(fInfo.aOuts);
  480. needsCtrlIn = true;
  481. }
  482. if (fInfo.mIns > 0)
  483. needsCtrlIn = true;
  484. if (fInfo.mOuts > 0)
  485. needsCtrlOut = true;
  486. const uint portNameSize(pData->engine->getMaxPortNameSize());
  487. CarlaString portName;
  488. // Audio Ins
  489. for (uint32_t j=0; j < fInfo.aIns; ++j)
  490. {
  491. portName.clear();
  492. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  493. {
  494. portName = pData->name;
  495. portName += ":";
  496. }
  497. if (fInfo.aIns > 1)
  498. {
  499. portName += "input_";
  500. portName += CarlaString(j+1);
  501. }
  502. else
  503. portName += "input";
  504. portName.truncate(portNameSize);
  505. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  506. pData->audioIn.ports[j].rindex = j;
  507. }
  508. // Audio Outs
  509. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  510. {
  511. portName.clear();
  512. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  513. {
  514. portName = pData->name;
  515. portName += ":";
  516. }
  517. if (fInfo.aOuts > 1)
  518. {
  519. portName += "output_";
  520. portName += CarlaString(j+1);
  521. }
  522. else
  523. portName += "output";
  524. portName.truncate(portNameSize);
  525. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  526. pData->audioOut.ports[j].rindex = j;
  527. }
  528. if (needsCtrlIn)
  529. {
  530. portName.clear();
  531. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  532. {
  533. portName = pData->name;
  534. portName += ":";
  535. }
  536. portName += "event-in";
  537. portName.truncate(portNameSize);
  538. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  539. }
  540. if (needsCtrlOut)
  541. {
  542. portName.clear();
  543. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  544. {
  545. portName = pData->name;
  546. portName += ":";
  547. }
  548. portName += "event-out";
  549. portName.truncate(portNameSize);
  550. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  551. }
  552. bufferSizeChanged(pData->engine->getBufferSize());
  553. reloadPrograms(true);
  554. carla_debug("BridgePlugin::reload() - end");
  555. }
  556. // -------------------------------------------------------------------
  557. // Plugin processing
  558. void activate() override
  559. {
  560. // already locked before
  561. fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter);
  562. fShmControl.writeInt(PARAMETER_ACTIVE);
  563. fShmControl.writeFloat(1.0f);
  564. fShmControl.commitWrite();
  565. waitForServer();
  566. }
  567. void deactivate() override
  568. {
  569. // already locked before
  570. fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter);
  571. fShmControl.writeInt(PARAMETER_ACTIVE);
  572. fShmControl.writeFloat(0.0f);
  573. fShmControl.commitWrite();
  574. waitForServer();
  575. }
  576. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override
  577. {
  578. uint32_t i, k;
  579. // --------------------------------------------------------------------------------------------------------
  580. // Check if active
  581. if (! pData->active)
  582. {
  583. // disable any output sound
  584. for (i=0; i < pData->audioOut.count; ++i)
  585. {
  586. #ifdef HAVE_JUCE
  587. FloatVectorOperations::clear(outBuffer[i], frames);
  588. #else
  589. carla_zeroFloat(outBuffer[i], frames);
  590. #endif
  591. }
  592. return;
  593. }
  594. // --------------------------------------------------------------------------------------------------------
  595. // Check if needs reset
  596. if (pData->needsReset)
  597. {
  598. // TODO
  599. pData->needsReset = false;
  600. }
  601. // --------------------------------------------------------------------------------------------------------
  602. // Event Input
  603. if (pData->event.portIn != nullptr)
  604. {
  605. // ----------------------------------------------------------------------------------------------------
  606. // MIDI Input (External)
  607. if (pData->extNotes.mutex.tryLock())
  608. {
  609. while (! pData->extNotes.data.isEmpty())
  610. {
  611. const ExternalMidiNote& note(pData->extNotes.data.getFirst(true));
  612. CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  613. char data1, data2, data3;
  614. data1 = static_cast<char>(note.channel + (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF);
  615. data2 = note.note;
  616. data3 = note.velo;
  617. fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent);
  618. fShmControl.writeLong(0);
  619. fShmControl.writeInt(3);
  620. fShmControl.writeChar(data1);
  621. fShmControl.writeChar(data2);
  622. fShmControl.writeChar(data3);
  623. }
  624. pData->extNotes.mutex.unlock();
  625. } // End of MIDI Input (External)
  626. // ----------------------------------------------------------------------------------------------------
  627. // Event Input (System)
  628. bool allNotesOffSent = false;
  629. uint32_t nEvents = pData->event.portIn->getEventCount();
  630. uint32_t nextBankId = 0;
  631. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  632. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  633. for (i=0; i < nEvents; ++i)
  634. {
  635. const EngineEvent& event(pData->event.portIn->getEvent(i));
  636. // Control change
  637. switch (event.type)
  638. {
  639. case kEngineEventTypeNull:
  640. break;
  641. case kEngineEventTypeControl:
  642. {
  643. const EngineControlEvent& ctrlEvent = event.ctrl;
  644. switch (ctrlEvent.type)
  645. {
  646. case kEngineControlEventTypeNull:
  647. break;
  648. case kEngineControlEventTypeParameter:
  649. {
  650. // Control backend stuff
  651. if (event.channel == pData->ctrlChannel)
  652. {
  653. float value;
  654. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) > 0)
  655. {
  656. value = ctrlEvent.value;
  657. setDryWet(value, false, false);
  658. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  659. }
  660. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) > 0)
  661. {
  662. value = ctrlEvent.value*127.0f/100.0f;
  663. setVolume(value, false, false);
  664. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  665. }
  666. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) > 0)
  667. {
  668. float left, right;
  669. value = ctrlEvent.value/0.5f - 1.0f;
  670. if (value < 0.0f)
  671. {
  672. left = -1.0f;
  673. right = (value*2.0f)+1.0f;
  674. }
  675. else if (value > 0.0f)
  676. {
  677. left = (value*2.0f)-1.0f;
  678. right = 1.0f;
  679. }
  680. else
  681. {
  682. left = -1.0f;
  683. right = 1.0f;
  684. }
  685. setBalanceLeft(left, false, false);
  686. setBalanceRight(right, false, false);
  687. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  688. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  689. }
  690. }
  691. // Control plugin parameters
  692. for (k=0; k < pData->param.count; ++k)
  693. {
  694. if (pData->param.data[k].midiChannel != event.channel)
  695. continue;
  696. if (pData->param.data[k].midiCC != ctrlEvent.param)
  697. continue;
  698. if (pData->param.data[k].type != PARAMETER_INPUT)
  699. continue;
  700. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  701. continue;
  702. float value;
  703. if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  704. {
  705. value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;
  706. }
  707. else
  708. {
  709. value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value);
  710. if (pData->param.data[k].hints & PARAMETER_IS_INTEGER)
  711. value = std::rint(value);
  712. }
  713. setParameterValue(k, value, false, false, false);
  714. pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  715. }
  716. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F)
  717. {
  718. fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent);
  719. fShmControl.writeLong(event.time);
  720. fShmControl.writeInt(3);
  721. fShmControl.writeChar(static_cast<char>(MIDI_STATUS_CONTROL_CHANGE + event.channel));
  722. fShmControl.writeChar(static_cast<char>(ctrlEvent.param));
  723. fShmControl.writeChar(char(ctrlEvent.value*127.0f));
  724. }
  725. break;
  726. }
  727. case kEngineControlEventTypeMidiBank:
  728. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  729. nextBankId = ctrlEvent.param;
  730. break;
  731. case kEngineControlEventTypeMidiProgram:
  732. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  733. {
  734. const uint32_t nextProgramId(ctrlEvent.param);
  735. if (pData->midiprog.count > 0)
  736. {
  737. for (k=0; k < pData->midiprog.count; ++k)
  738. {
  739. if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
  740. {
  741. setMidiProgram(k, false, false, false);
  742. pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0f);
  743. break;
  744. }
  745. }
  746. }
  747. else
  748. {
  749. }
  750. }
  751. break;
  752. case kEngineControlEventTypeAllSoundOff:
  753. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  754. {
  755. // TODO
  756. }
  757. break;
  758. case kEngineControlEventTypeAllNotesOff:
  759. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  760. {
  761. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  762. {
  763. allNotesOffSent = true;
  764. sendMidiAllNotesOffToCallback();
  765. }
  766. // TODO
  767. }
  768. break;
  769. }
  770. break;
  771. }
  772. case kEngineEventTypeMidi:
  773. {
  774. const EngineMidiEvent& midiEvent(event.midi);
  775. uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  776. uint8_t channel = event.channel;
  777. if (MIDI_IS_STATUS_CHANNEL_PRESSURE(status) && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  778. continue;
  779. if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  780. continue;
  781. if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  782. continue;
  783. if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  784. continue;
  785. // Fix bad note-off
  786. if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
  787. status = MIDI_STATUS_NOTE_OFF;
  788. char data[4];
  789. data[0] = static_cast<char>(status + channel);
  790. data[1] = midiEvent.data[1];
  791. data[2] = midiEvent.data[2];
  792. data[3] = midiEvent.data[3];
  793. fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent);
  794. fShmControl.writeLong(event.time);
  795. fShmControl.writeInt(midiEvent.size);
  796. for (uint8_t j=0; j < midiEvent.size && j < 4; ++j)
  797. fShmControl.writeChar(data[j]);
  798. if (status == MIDI_STATUS_NOTE_ON)
  799. pData->postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]);
  800. else if (status == MIDI_STATUS_NOTE_OFF)
  801. pData->postponeRtEvent(kPluginPostRtEventNoteOff, channel, midiEvent.data[1], 0.0f);
  802. break;
  803. }
  804. }
  805. }
  806. pData->postRtEvents.trySplice();
  807. } // End of Event Input
  808. processSingle(inBuffer, outBuffer, frames);
  809. }
  810. bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames)
  811. {
  812. CARLA_ASSERT(frames > 0);
  813. if (frames == 0)
  814. return false;
  815. if (pData->audioIn.count > 0)
  816. {
  817. CARLA_ASSERT(inBuffer != nullptr);
  818. if (inBuffer == nullptr)
  819. return false;
  820. }
  821. if (pData->audioOut.count > 0)
  822. {
  823. CARLA_ASSERT(outBuffer != nullptr);
  824. if (outBuffer == nullptr)
  825. return false;
  826. }
  827. uint32_t i, k;
  828. // --------------------------------------------------------------------------------------------------------
  829. // Try lock, silence otherwise
  830. if (pData->engine->isOffline())
  831. {
  832. pData->singleMutex.lock();
  833. }
  834. else if (! pData->singleMutex.tryLock())
  835. {
  836. for (i=0; i < pData->audioOut.count; ++i)
  837. {
  838. #ifdef HAVE_JUCE
  839. FloatVectorOperations::clear(outBuffer[i], frames);
  840. #else
  841. #endif
  842. }
  843. return false;
  844. }
  845. // --------------------------------------------------------------------------------------------------------
  846. // Reset audio buffers
  847. for (i=0; i < fInfo.aIns; ++i)
  848. {
  849. #ifdef HAVE_JUCE
  850. FloatVectorOperations::copy(fShmAudioPool.data + (i * frames), inBuffer[i], frames);
  851. #else
  852. #endif
  853. }
  854. // --------------------------------------------------------------------------------------------------------
  855. // Run plugin
  856. fShmControl.writeOpcode(kPluginBridgeOpcodeProcess);
  857. fShmControl.commitWrite();
  858. if (! waitForServer())
  859. {
  860. pData->singleMutex.unlock();
  861. return true;
  862. }
  863. for (i=0; i < fInfo.aOuts; ++i)
  864. {
  865. #ifdef HAVE_JUCE
  866. FloatVectorOperations::copy(outBuffer[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), frames);
  867. #else
  868. #endif
  869. }
  870. // --------------------------------------------------------------------------------------------------------
  871. // Post-processing (dry/wet, volume and balance)
  872. {
  873. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && pData->postProc.volume != 1.0f;
  874. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f;
  875. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f);
  876. bool isPair;
  877. float bufValue, oldBufLeft[doBalance ? frames : 1];
  878. for (i=0; i < pData->audioOut.count; ++i)
  879. {
  880. // Dry/Wet
  881. if (doDryWet)
  882. {
  883. for (k=0; k < frames; ++k)
  884. {
  885. bufValue = inBuffer[(pData->audioIn.count == 1) ? 0 : i][k];
  886. outBuffer[i][k] = (outBuffer[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  887. }
  888. }
  889. // Balance
  890. if (doBalance)
  891. {
  892. isPair = (i % 2 == 0);
  893. if (isPair)
  894. {
  895. CARLA_ASSERT(i+1 < pData->audioOut.count);
  896. #ifdef HAVE_JUCE
  897. FloatVectorOperations::copy(oldBufLeft, outBuffer[i], frames);
  898. #else
  899. #endif
  900. }
  901. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  902. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  903. for (k=0; k < frames; ++k)
  904. {
  905. if (isPair)
  906. {
  907. // left
  908. outBuffer[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  909. outBuffer[i][k] += outBuffer[i+1][k] * (1.0f - balRangeR);
  910. }
  911. else
  912. {
  913. // right
  914. outBuffer[i][k] = outBuffer[i][k] * balRangeR;
  915. outBuffer[i][k] += oldBufLeft[k] * balRangeL;
  916. }
  917. }
  918. }
  919. // Volume
  920. if (doVolume)
  921. {
  922. for (k=0; k < frames; ++k)
  923. outBuffer[i][k] *= pData->postProc.volume;
  924. }
  925. }
  926. } // End of Post-processing
  927. // --------------------------------------------------------------------------------------------------------
  928. pData->singleMutex.unlock();
  929. return true;
  930. }
  931. void bufferSizeChanged(const uint32_t newBufferSize) override
  932. {
  933. resizeAudioPool(newBufferSize);
  934. fShmControl.writeOpcode(kPluginBridgeOpcodeSetBufferSize);
  935. fShmControl.writeInt(newBufferSize);
  936. fShmControl.commitWrite();
  937. }
  938. void sampleRateChanged(const double newSampleRate) override
  939. {
  940. fShmControl.writeOpcode(kPluginBridgeOpcodeSetSampleRate);
  941. fShmControl.writeFloat(float(newSampleRate));
  942. fShmControl.commitWrite();
  943. }
  944. // -------------------------------------------------------------------
  945. // Plugin buffers
  946. void clearBuffers() override
  947. {
  948. if (fParams != nullptr)
  949. {
  950. delete[] fParams;
  951. fParams = nullptr;
  952. }
  953. CarlaPlugin::clearBuffers();
  954. }
  955. // -------------------------------------------------------------------
  956. // Post-poned UI Stuff
  957. // nothing
  958. // -------------------------------------------------------------------
  959. int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types)
  960. {
  961. carla_debug("setOscPluginBridgeInfo(%s, %i, %p, \"%s\")", PluginBridgeInfoType2str(type), argc, argv, types);
  962. switch (type)
  963. {
  964. case kPluginBridgeAudioCount:
  965. {
  966. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  967. const int32_t aIns = argv[0]->i;
  968. const int32_t aOuts = argv[1]->i;
  969. const int32_t aTotal = argv[2]->i;
  970. CARLA_ASSERT(aIns >= 0);
  971. CARLA_ASSERT(aOuts >= 0);
  972. CARLA_ASSERT(aIns + aOuts == aTotal);
  973. fInfo.aIns = aIns;
  974. fInfo.aOuts = aOuts;
  975. break;
  976. // unused
  977. (void)aTotal;
  978. }
  979. case kPluginBridgeMidiCount:
  980. {
  981. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  982. const int32_t mIns = argv[0]->i;
  983. const int32_t mOuts = argv[1]->i;
  984. const int32_t mTotal = argv[2]->i;
  985. CARLA_ASSERT(mIns >= 0);
  986. CARLA_ASSERT(mOuts >= 0);
  987. CARLA_ASSERT(mIns + mOuts == mTotal);
  988. fInfo.mIns = mIns;
  989. fInfo.mOuts = mOuts;
  990. break;
  991. // unused
  992. (void)mTotal;
  993. }
  994. case kPluginBridgeParameterCount:
  995. {
  996. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  997. const int32_t pIns = argv[0]->i;
  998. const int32_t pOuts = argv[1]->i;
  999. const int32_t pTotal = argv[2]->i;
  1000. CARLA_ASSERT(pIns >= 0);
  1001. CARLA_ASSERT(pOuts >= 0);
  1002. CARLA_ASSERT(pIns + pOuts <= pTotal);
  1003. // delete old data
  1004. pData->param.clear();
  1005. if (fParams != nullptr)
  1006. {
  1007. delete[] fParams;
  1008. fParams = nullptr;
  1009. }
  1010. CARLA_SAFE_ASSERT_INT2(pTotal < static_cast<int32_t>(pData->engine->getOptions().maxParameters), pTotal, pData->engine->getOptions().maxParameters);
  1011. const int32_t count(carla_min<int32_t>(pTotal, pData->engine->getOptions().maxParameters, 0));
  1012. if (count > 0)
  1013. {
  1014. pData->param.createNew(count);
  1015. fParams = new BridgeParamInfo[count];
  1016. }
  1017. break;
  1018. // unused
  1019. (void)pIns;
  1020. (void)pOuts;
  1021. }
  1022. case kPluginBridgeProgramCount:
  1023. {
  1024. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1025. const int32_t count = argv[0]->i;
  1026. CARLA_ASSERT(count >= 0);
  1027. pData->prog.clear();
  1028. if (count > 0)
  1029. pData->prog.createNew(count);
  1030. break;
  1031. }
  1032. case kPluginBridgeMidiProgramCount:
  1033. {
  1034. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1035. const int32_t count = argv[0]->i;
  1036. CARLA_ASSERT(count >= 0);
  1037. pData->midiprog.clear();
  1038. if (count > 0)
  1039. pData->midiprog.createNew(count);
  1040. break;
  1041. }
  1042. case kPluginBridgePluginInfo:
  1043. {
  1044. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh");
  1045. const int32_t category = argv[0]->i;
  1046. const int32_t hints = argv[1]->i;
  1047. const char* const name = (const char*)&argv[2]->s;
  1048. const char* const label = (const char*)&argv[3]->s;
  1049. const char* const maker = (const char*)&argv[4]->s;
  1050. const char* const copyright = (const char*)&argv[5]->s;
  1051. const int64_t uniqueId = argv[6]->h;
  1052. CARLA_ASSERT(category >= 0);
  1053. CARLA_ASSERT(hints >= 0);
  1054. CARLA_ASSERT(name != nullptr);
  1055. CARLA_ASSERT(label != nullptr);
  1056. CARLA_ASSERT(maker != nullptr);
  1057. CARLA_ASSERT(copyright != nullptr);
  1058. pData->hints = hints | PLUGIN_IS_BRIDGE;
  1059. fInfo.category = static_cast<PluginCategory>(category);
  1060. fInfo.uniqueId = static_cast<long int>(uniqueId);
  1061. fInfo.name = name;
  1062. fInfo.label = label;
  1063. fInfo.maker = maker;
  1064. fInfo.copyright = copyright;
  1065. if (pData->name == nullptr)
  1066. pData->name = carla_strdup(name);
  1067. break;
  1068. }
  1069. case kPluginBridgeParameterInfo:
  1070. {
  1071. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
  1072. const int32_t index = argv[0]->i;
  1073. const char* const name = (const char*)&argv[1]->s;
  1074. const char* const unit = (const char*)&argv[2]->s;
  1075. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1076. CARLA_ASSERT(name != nullptr);
  1077. CARLA_ASSERT(unit != nullptr);
  1078. if (index >= 0 && static_cast<int32_t>(pData->param.count))
  1079. {
  1080. fParams[index].name = name;
  1081. fParams[index].unit = unit;
  1082. }
  1083. break;
  1084. }
  1085. case kPluginBridgeParameterData:
  1086. {
  1087. CARLA_BRIDGE_CHECK_OSC_TYPES(5, "iiiii");
  1088. const int32_t index = argv[0]->i;
  1089. const int32_t rindex = argv[2]->i;
  1090. const int32_t hints = argv[3]->i;
  1091. const int32_t channel = argv[4]->i;
  1092. const int32_t cc = argv[5]->i;
  1093. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1094. CARLA_ASSERT(rindex >= 0);
  1095. CARLA_ASSERT(hints >= 0);
  1096. CARLA_ASSERT(channel >= 0 && channel < MAX_MIDI_CHANNELS);
  1097. CARLA_ASSERT(cc >= -1 && cc < 0x5F);
  1098. if (index >= 0 && static_cast<int32_t>(pData->param.count))
  1099. {
  1100. pData->param.data[index].index = index;
  1101. pData->param.data[index].rindex = rindex;
  1102. pData->param.data[index].hints = hints;
  1103. pData->param.data[index].midiChannel = static_cast<uint8_t>(channel);
  1104. pData->param.data[index].midiCC = static_cast<int16_t>(cc);
  1105. }
  1106. break;
  1107. }
  1108. case kPluginBridgeParameterRanges:
  1109. {
  1110. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iffffff");
  1111. const int32_t index = argv[0]->i;
  1112. const float def = argv[1]->f;
  1113. const float min = argv[2]->f;
  1114. const float max = argv[3]->f;
  1115. const float step = argv[4]->f;
  1116. const float stepSmall = argv[5]->f;
  1117. const float stepLarge = argv[6]->f;
  1118. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1119. CARLA_ASSERT(min < max);
  1120. CARLA_ASSERT(def >= min);
  1121. CARLA_ASSERT(def <= max);
  1122. if (index >= 0 && static_cast<int32_t>(pData->param.count))
  1123. {
  1124. pData->param.ranges[index].def = def;
  1125. pData->param.ranges[index].min = min;
  1126. pData->param.ranges[index].max = max;
  1127. pData->param.ranges[index].step = step;
  1128. pData->param.ranges[index].stepSmall = stepSmall;
  1129. pData->param.ranges[index].stepLarge = stepLarge;
  1130. }
  1131. break;
  1132. }
  1133. case kPluginBridgeProgramInfo:
  1134. {
  1135. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "is");
  1136. const int32_t index = argv[0]->i;
  1137. const char* const name = (const char*)&argv[1]->s;
  1138. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1139. CARLA_ASSERT(name != nullptr);
  1140. if (index >= 0 && index < static_cast<int32_t>(pData->prog.count))
  1141. {
  1142. if (pData->prog.names[index] != nullptr)
  1143. delete[] pData->prog.names[index];
  1144. pData->prog.names[index] = carla_strdup(name);
  1145. }
  1146. break;
  1147. }
  1148. case kPluginBridgeMidiProgramInfo:
  1149. {
  1150. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "iiis");
  1151. const int32_t index = argv[0]->i;
  1152. const int32_t bank = argv[1]->i;
  1153. const int32_t program = argv[2]->i;
  1154. const char* const name = (const char*)&argv[3]->s;
  1155. CARLA_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1156. CARLA_ASSERT(bank >= 0);
  1157. CARLA_ASSERT(program >= 0 && program < 128);
  1158. CARLA_ASSERT(name != nullptr);
  1159. if (index >= 0 && index < static_cast<int32_t>(pData->midiprog.count))
  1160. {
  1161. if (pData->midiprog.data[index].name != nullptr)
  1162. delete[] pData->midiprog.data[index].name;
  1163. pData->midiprog.data[index].bank = bank;
  1164. pData->midiprog.data[index].program = program;
  1165. pData->midiprog.data[index].name = carla_strdup(name);
  1166. }
  1167. break;
  1168. }
  1169. case kPluginBridgeConfigure:
  1170. {
  1171. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");
  1172. const char* const key = (const char*)&argv[0]->s;
  1173. const char* const value = (const char*)&argv[1]->s;
  1174. CARLA_ASSERT(key != nullptr);
  1175. CARLA_ASSERT(value != nullptr);
  1176. if (key == nullptr || value == nullptr)
  1177. break;
  1178. if (std::strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
  1179. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  1180. else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
  1181. fSaved = true;
  1182. break;
  1183. }
  1184. case kPluginBridgeSetParameterValue:
  1185. {
  1186. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "if");
  1187. const int32_t index = argv[0]->i;
  1188. const float value = argv[1]->f;
  1189. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1190. if (index >= 0 && static_cast<int32_t>(pData->param.count))
  1191. {
  1192. const float fixedValue(pData->param.getFixedValue(index, value));
  1193. fParams[index].value = fixedValue;
  1194. CarlaPlugin::setParameterValue(index, fixedValue, false, true, true);
  1195. }
  1196. break;
  1197. }
  1198. case kPluginBridgeSetDefaultValue:
  1199. {
  1200. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "if");
  1201. const int32_t index = argv[0]->i;
  1202. const float value = argv[1]->f;
  1203. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->param.count), index, pData->param.count);
  1204. if (index >= 0 && static_cast<int32_t>(pData->param.count))
  1205. pData->param.ranges[index].def = value;
  1206. break;
  1207. }
  1208. case kPluginBridgeSetProgram:
  1209. {
  1210. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1211. const int32_t index = argv[0]->i;
  1212. CARLA_ASSERT_INT2(index >= 0 && index < static_cast<int32_t>(pData->prog.count), index, pData->prog.count);
  1213. setProgram(index, false, true, true);
  1214. break;
  1215. }
  1216. case kPluginBridgeSetMidiProgram:
  1217. {
  1218. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  1219. const int32_t index = argv[0]->i;
  1220. CARLA_ASSERT_INT2(index < static_cast<int32_t>(pData->midiprog.count), index, pData->midiprog.count);
  1221. setMidiProgram(index, false, true, true);
  1222. break;
  1223. }
  1224. case kPluginBridgeSetCustomData:
  1225. {
  1226. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");
  1227. const char* const type = (const char*)&argv[0]->s;
  1228. const char* const key = (const char*)&argv[1]->s;
  1229. const char* const value = (const char*)&argv[2]->s;
  1230. CARLA_ASSERT(type != nullptr);
  1231. CARLA_ASSERT(key != nullptr);
  1232. CARLA_ASSERT(value != nullptr);
  1233. setCustomData(type, key, value, false);
  1234. break;
  1235. }
  1236. case kPluginBridgeSetChunkData:
  1237. {
  1238. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  1239. #if 0
  1240. const char* const chunkFileChar = (const char*)&argv[0]->s;
  1241. CARLA_ASSERT(chunkFileChar);
  1242. QString chunkFileStr(chunkFileChar);
  1243. #ifndef CARLA_OS_WIN
  1244. // Using Wine, fix temp dir
  1245. if (m_binary == BINARY_WIN32 || m_binary == BINARY_WIN64)
  1246. {
  1247. // Get WINEPREFIX
  1248. QString wineDir;
  1249. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  1250. wineDir = QString(WINEPREFIX);
  1251. else
  1252. wineDir = QDir::homePath() + "/.wine";
  1253. QStringList chunkFileStrSplit1 = chunkFileStr.split(":/");
  1254. QStringList chunkFileStrSplit2 = chunkFileStrSplit1.at(1).split("\\");
  1255. QString wineDrive = chunkFileStrSplit1.at(0).toLower();
  1256. QString wineTMP = chunkFileStrSplit2.at(0);
  1257. QString baseName = chunkFileStrSplit2.at(1);
  1258. chunkFileStr = wineDir;
  1259. chunkFileStr += "/drive_";
  1260. chunkFileStr += wineDrive;
  1261. chunkFileStr += "/";
  1262. chunkFileStr += wineTMP;
  1263. chunkFileStr += "/";
  1264. chunkFileStr += baseName;
  1265. chunkFileStr = QDir::toNativeSeparators(chunkFileStr);
  1266. }
  1267. #endif
  1268. QFile chunkFile(chunkFileStr);
  1269. if (chunkFile.open(QIODevice::ReadOnly))
  1270. {
  1271. info.chunk = chunkFile.readAll();
  1272. chunkFile.close();
  1273. chunkFile.remove();
  1274. }
  1275. #endif
  1276. break;
  1277. }
  1278. case kPluginBridgeUpdateNow:
  1279. {
  1280. fInitiated = true;
  1281. break;
  1282. }
  1283. case kPluginBridgeError:
  1284. {
  1285. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  1286. const char* const error = (const char*)&argv[0]->s;
  1287. CARLA_ASSERT(error != nullptr);
  1288. pData->engine->setLastError(error);
  1289. fInitError = true;
  1290. fInitiated = true;
  1291. break;
  1292. }
  1293. }
  1294. return 0;
  1295. }
  1296. // -------------------------------------------------------------------
  1297. const void* getExtraStuff() const noexcept override
  1298. {
  1299. return fBridgeBinary.isNotEmpty() ? (const char*)fBridgeBinary : nullptr;
  1300. }
  1301. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  1302. {
  1303. CARLA_ASSERT(pData->engine != nullptr);
  1304. CARLA_ASSERT(pData->client == nullptr);
  1305. // ---------------------------------------------------------------
  1306. // first checks
  1307. if (pData->engine == nullptr)
  1308. {
  1309. return false;
  1310. }
  1311. if (pData->client != nullptr)
  1312. {
  1313. pData->engine->setLastError("Plugin client is already registered");
  1314. return false;
  1315. }
  1316. // ---------------------------------------------------------------
  1317. // set info
  1318. if (name != nullptr)
  1319. pData->name = pData->engine->getUniquePluginName(name);
  1320. pData->filename = filename;
  1321. fBridgeBinary = bridgeBinary;
  1322. // ---------------------------------------------------------------
  1323. // SHM Audio Pool
  1324. {
  1325. char tmpFileBase[60];
  1326. std::srand(static_cast<uint>(std::time(nullptr)));
  1327. std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");
  1328. fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
  1329. if (! carla_is_shm_valid(fShmAudioPool.shm))
  1330. {
  1331. carla_stdout("Failed to open or create shared memory file #1");
  1332. return false;
  1333. }
  1334. fShmAudioPool.filename = tmpFileBase;
  1335. }
  1336. // ---------------------------------------------------------------
  1337. // SHM Control
  1338. {
  1339. char tmpFileBase[60];
  1340. std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX");
  1341. fShmControl.shm = shm_mkstemp(tmpFileBase);
  1342. if (! carla_is_shm_valid(fShmControl.shm))
  1343. {
  1344. carla_stdout("Failed to open or create shared memory file #2");
  1345. // clear
  1346. carla_shm_close(fShmAudioPool.shm);
  1347. return false;
  1348. }
  1349. fShmControl.filename = tmpFileBase;
  1350. if (! fShmControl.mapData())
  1351. {
  1352. carla_stdout("Failed to mmap shared memory file");
  1353. // clear
  1354. carla_shm_close(fShmControl.shm);
  1355. carla_shm_close(fShmAudioPool.shm);
  1356. return false;
  1357. }
  1358. CARLA_ASSERT(fShmControl.data != nullptr);
  1359. if (! jackbridge_sem_init(&fShmControl.data->runServer))
  1360. {
  1361. carla_stdout("Failed to initialize shared memory semaphore #1");
  1362. // clear
  1363. fShmControl.unmapData();
  1364. carla_shm_close(fShmControl.shm);
  1365. carla_shm_close(fShmAudioPool.shm);
  1366. return false;
  1367. }
  1368. if (! jackbridge_sem_init(&fShmControl.data->runClient))
  1369. {
  1370. carla_stdout("Failed to initialize shared memory semaphore #2");
  1371. // clear
  1372. jackbridge_sem_destroy(&fShmControl.data->runServer);
  1373. fShmControl.unmapData();
  1374. carla_shm_close(fShmControl.shm);
  1375. carla_shm_close(fShmAudioPool.shm);
  1376. return false;
  1377. }
  1378. fNeedsSemDestroy = true;
  1379. }
  1380. // initial values
  1381. fShmControl.writeOpcode(kPluginBridgeOpcodeSetBufferSize);
  1382. fShmControl.writeInt(pData->engine->getBufferSize());
  1383. fShmControl.writeOpcode(kPluginBridgeOpcodeSetSampleRate);
  1384. fShmControl.writeFloat(float(pData->engine->getSampleRate()));
  1385. fShmControl.commitWrite();
  1386. // register plugin now so we can receive OSC (and wait for it)
  1387. pData->hints |= PLUGIN_IS_BRIDGE;
  1388. pData->engine->registerEnginePlugin(pData->id, this);
  1389. // init OSC
  1390. {
  1391. char shmIdStr[12+1] = { 0 };
  1392. std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  1393. std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6);
  1394. pData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
  1395. pData->osc.thread.start();
  1396. }
  1397. for (int i=0; i < 200; ++i)
  1398. {
  1399. if (fInitiated || ! pData->osc.thread.isRunning())
  1400. break;
  1401. carla_msleep(50);
  1402. }
  1403. if (fInitError || ! fInitiated)
  1404. {
  1405. // unregister so it gets handled properly
  1406. pData->engine->registerEnginePlugin(pData->id, nullptr);
  1407. pData->osc.thread.stop(6000);
  1408. if (! fInitError)
  1409. pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  1410. return false;
  1411. }
  1412. // ---------------------------------------------------------------
  1413. // register client
  1414. if (pData->name == nullptr)
  1415. {
  1416. if (name != nullptr)
  1417. pData->name = pData->engine->getUniquePluginName(name);
  1418. else if (label != nullptr)
  1419. pData->name = pData->engine->getUniquePluginName(label);
  1420. else
  1421. pData->name = pData->engine->getUniquePluginName("unknown");
  1422. }
  1423. pData->client = pData->engine->addClient(this);
  1424. if (pData->client == nullptr || ! pData->client->isOk())
  1425. {
  1426. pData->engine->setLastError("Failed to register plugin client");
  1427. return false;
  1428. }
  1429. return true;
  1430. }
  1431. private:
  1432. const BinaryType fBinaryType;
  1433. const PluginType fPluginType;
  1434. bool fInitiated;
  1435. bool fInitError;
  1436. bool fSaved;
  1437. bool fNeedsSemDestroy;
  1438. CarlaString fBridgeBinary;
  1439. BridgeAudioPool fShmAudioPool;
  1440. BridgeControl fShmControl;
  1441. struct Info {
  1442. uint32_t aIns, aOuts;
  1443. uint32_t mIns, mOuts;
  1444. PluginCategory category;
  1445. long uniqueId;
  1446. CarlaString name;
  1447. CarlaString label;
  1448. CarlaString maker;
  1449. CarlaString copyright;
  1450. //QByteArray chunk;
  1451. Info()
  1452. : aIns(0),
  1453. aOuts(0),
  1454. mIns(0),
  1455. mOuts(0),
  1456. category(PLUGIN_CATEGORY_NONE),
  1457. uniqueId(0) {}
  1458. } fInfo;
  1459. BridgeParamInfo* fParams;
  1460. void resizeAudioPool(const uint32_t bufferSize)
  1461. {
  1462. fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts);
  1463. fShmControl.writeOpcode(kPluginBridgeOpcodeSetAudioPool);
  1464. fShmControl.writeLong(fShmAudioPool.size);
  1465. fShmControl.commitWrite();
  1466. waitForServer();
  1467. }
  1468. bool waitForServer()
  1469. {
  1470. if (! fShmControl.waitForServer())
  1471. {
  1472. carla_stderr("waitForServer() timeout");
  1473. pData->active = false; // TODO
  1474. return false;
  1475. }
  1476. return true;
  1477. }
  1478. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
  1479. };
  1480. CARLA_BACKEND_END_NAMESPACE
  1481. #endif // ! BUILD_BRIDGE
  1482. CARLA_BACKEND_START_NAMESPACE
  1483. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
  1484. {
  1485. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1486. #ifndef BUILD_BRIDGE
  1487. if (bridgeBinary == nullptr)
  1488. {
  1489. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1490. return nullptr;
  1491. }
  1492. BridgePlugin* const plugin(new BridgePlugin(init.engine, init.id, btype, ptype));
  1493. if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
  1494. {
  1495. delete plugin;
  1496. return nullptr;
  1497. }
  1498. plugin->reload();
  1499. if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack())
  1500. {
  1501. init.engine->setLastError("Carla's rack mode can only work with Stereo Bridged plugins, sorry!");
  1502. delete plugin;
  1503. return nullptr;
  1504. }
  1505. return plugin;
  1506. #else
  1507. init.engine->setLastError("Plugin bridge support not available");
  1508. return nullptr;
  1509. // unused
  1510. (void)bridgeBinary;
  1511. #endif
  1512. }
  1513. #ifndef BUILD_BRIDGE
  1514. // -------------------------------------------------------------------
  1515. // Bridge Helper
  1516. #define bridgePlugin ((BridgePlugin*)plugin)
  1517. int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type,
  1518. const int argc, const lo_arg* const* const argv, const char* const types)
  1519. {
  1520. CARLA_ASSERT(plugin != nullptr && (plugin->getHints() & PLUGIN_IS_BRIDGE) != 0);
  1521. return bridgePlugin->setOscPluginBridgeInfo(type, argc, argv, types);
  1522. }
  1523. #undef bridgePlugin
  1524. #endif
  1525. CARLA_BACKEND_END_NAMESPACE