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

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  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 GPL.txt file
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #ifndef BUILD_BRIDGE
  19. #include "CarlaBridge.hpp"
  20. #include "CarlaShmUtils.hpp"
  21. #include <cerrno>
  22. #include <ctime>
  23. #include <QtCore/QDir>
  24. #include <QtCore/QFile>
  25. #include <QtCore/QStringList>
  26. #include <QtCore/QTextStream>
  27. #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
  28. /* check argument count */ \
  29. if (argc != argcToCompare) \
  30. { \
  31. carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \
  32. return 1; \
  33. } \
  34. if (argc > 0) \
  35. { \
  36. /* check for nullness */ \
  37. if (! (types && typesToCompare)) \
  38. { \
  39. carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \
  40. return 1; \
  41. } \
  42. /* check argument types */ \
  43. if (std::strcmp(types, typesToCompare) != 0) \
  44. { \
  45. carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \
  46. return 1; \
  47. } \
  48. }
  49. CARLA_BACKEND_START_NAMESPACE
  50. // -------------------------------------------------------------------------------------------------------------------
  51. // Engine Helpers
  52. extern void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin);
  53. // -------------------------------------------------------------------------------------------------------------------
  54. shm_t shm_mkstemp(char* const fileBase)
  55. {
  56. static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
  57. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  58. "0123456789";
  59. const int size = (fileBase != nullptr) ? std::strlen(fileBase) : 0;
  60. shm_t shm;
  61. carla_shm_init(shm);
  62. if (size < 6)
  63. {
  64. errno = EINVAL;
  65. return shm;
  66. }
  67. if (std::strcmp(fileBase + size - 6, "XXXXXX") != 0)
  68. {
  69. errno = EINVAL;
  70. return shm;
  71. }
  72. while (true)
  73. {
  74. for (int c = size - 6; c < size; c++)
  75. {
  76. // Note the -1 to avoid the trailing '\0' in charSet.
  77. fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)];
  78. }
  79. shm_t shm = carla_shm_create(fileBase);
  80. if (carla_is_shm_valid(shm) || errno != EEXIST)
  81. return shm;
  82. }
  83. }
  84. // -------------------------------------------------------------------------------------------------------------------
  85. struct BridgeParamInfo {
  86. float value;
  87. CarlaString name;
  88. CarlaString unit;
  89. BridgeParamInfo()
  90. : value(0.0f) {}
  91. };
  92. class BridgePlugin : public CarlaPlugin
  93. {
  94. public:
  95. BridgePlugin(CarlaEngine* const engine, const unsigned int id, const BinaryType btype, const PluginType ptype)
  96. : CarlaPlugin(engine, id),
  97. fBinaryType(btype),
  98. fPluginType(ptype),
  99. fInitiated(false),
  100. fInitError(false),
  101. fSaved(false),
  102. fParams(nullptr)
  103. {
  104. carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  105. kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  106. }
  107. ~BridgePlugin()
  108. {
  109. carla_debug("BridgePlugin::~BridgePlugin()");
  110. kData->singleMutex.lock();
  111. kData->masterMutex.lock();
  112. _cleanup();
  113. if (kData->osc.data.target != nullptr)
  114. {
  115. osc_send_hide(&kData->osc.data);
  116. osc_send_quit(&kData->osc.data);
  117. }
  118. kData->osc.data.free();
  119. // Wait a bit first, then force kill
  120. if (kData->osc.thread.isRunning() && ! kData->osc.thread.stop(1000)) // kData->engine->getOptions().oscUiTimeout
  121. {
  122. carla_stderr("Failed to properly stop Plugin Bridge thread");
  123. kData->osc.thread.terminate();
  124. }
  125. //info.chunk.clear();
  126. }
  127. // -------------------------------------------------------------------
  128. // Information (base)
  129. PluginType type() const
  130. {
  131. return fPluginType;
  132. }
  133. PluginCategory category()
  134. {
  135. return fInfo.category;
  136. }
  137. long uniqueId() const
  138. {
  139. return fInfo.uniqueId;
  140. }
  141. // -------------------------------------------------------------------
  142. // Information (count)
  143. uint32_t audioInCount()
  144. {
  145. return fInfo.aIns;
  146. }
  147. uint32_t audioOutCount()
  148. {
  149. return fInfo.aOuts;
  150. }
  151. uint32_t midiInCount()
  152. {
  153. return fInfo.mIns;
  154. }
  155. uint32_t midiOutCount()
  156. {
  157. return fInfo.mOuts;
  158. }
  159. #if 0
  160. // -------------------------------------------------------------------
  161. // Information (current data)
  162. int32_t chunkData(void** const dataPtr)
  163. {
  164. CARLA_ASSERT(dataPtr);
  165. if (! info.chunk.isEmpty())
  166. {
  167. *dataPtr = info.chunk.data();
  168. return info.chunk.size();
  169. }
  170. return 0;
  171. }
  172. // -------------------------------------------------------------------
  173. // Information (per-plugin data)
  174. double getParameterValue(const uint32_t parameterId)
  175. {
  176. CARLA_ASSERT(parameterId < param.count);
  177. return params[parameterId].value;
  178. }
  179. #endif
  180. void getLabel(char* const strBuf)
  181. {
  182. std::strncpy(strBuf, (const char*)fInfo.label, STR_MAX);
  183. }
  184. void getMaker(char* const strBuf)
  185. {
  186. std::strncpy(strBuf, (const char*)fInfo.maker, STR_MAX);
  187. }
  188. void getCopyright(char* const strBuf)
  189. {
  190. std::strncpy(strBuf, (const char*)fInfo.copyright, STR_MAX);
  191. }
  192. void getRealName(char* const strBuf)
  193. {
  194. std::strncpy(strBuf, (const char*)fInfo.name, STR_MAX);
  195. }
  196. #if 0
  197. void getParameterName(const uint32_t parameterId, char* const strBuf)
  198. {
  199. CARLA_ASSERT(parameterId < param.count);
  200. strncpy(strBuf, params[parameterId].name.toUtf8().constData(), STR_MAX);
  201. }
  202. void getParameterUnit(const uint32_t parameterId, char* const strBuf)
  203. {
  204. CARLA_ASSERT(parameterId < param.count);
  205. strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX);
  206. }
  207. #endif
  208. // -------------------------------------------------------------------
  209. // Set data (internal stuff)
  210. int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types)
  211. {
  212. carla_stdout("setOscPluginBridgeInfo(%i, %i, %p, \"%s\")", type, argc, argv, types);
  213. switch (type)
  214. {
  215. case kPluginBridgeAudioCount:
  216. {
  217. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  218. const int32_t aIns = argv[0]->i;
  219. const int32_t aOuts = argv[1]->i;
  220. const int32_t aTotal = argv[2]->i;
  221. CARLA_ASSERT(aIns >= 0);
  222. CARLA_ASSERT(aOuts >= 0);
  223. CARLA_ASSERT(aIns + aOuts == aTotal);
  224. fInfo.aIns = aIns;
  225. fInfo.aOuts = aOuts;
  226. break;
  227. // unused
  228. (void)aTotal;
  229. }
  230. case kPluginBridgeMidiCount:
  231. {
  232. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  233. const int32_t mIns = argv[0]->i;
  234. const int32_t mOuts = argv[1]->i;
  235. const int32_t mTotal = argv[2]->i;
  236. CARLA_ASSERT(mIns >= 0);
  237. CARLA_ASSERT(mOuts >= 0);
  238. CARLA_ASSERT(mIns + mOuts == mTotal);
  239. fInfo.mIns = mIns;
  240. fInfo.mOuts = mOuts;
  241. break;
  242. // unused
  243. (void)mTotal;
  244. }
  245. #if 0
  246. case PluginBridgeParameterCount:
  247. {
  248. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  249. const int32_t pIns = argv[0]->i;
  250. const int32_t pOuts = argv[1]->i;
  251. const int32_t pTotal = argv[2]->i;
  252. CARLA_ASSERT(pIns >= 0);
  253. CARLA_ASSERT(pOuts >= 0);
  254. CARLA_ASSERT(pIns + pOuts <= pTotal);
  255. // delete old data
  256. if (param.count > 0)
  257. {
  258. delete[] param.data;
  259. delete[] param.ranges;
  260. delete[] params;
  261. }
  262. // create new if needed
  263. const int32_t maxParams = x_engine->getOptions().maxParameters;
  264. param.count = (pTotal < maxParams) ? pTotal : 0;
  265. if (param.count > 0)
  266. {
  267. param.data = new ParameterData[param.count];
  268. param.ranges = new ParameterRanges[param.count];
  269. params = new BridgeParamInfo[param.count];
  270. }
  271. else
  272. {
  273. param.data = nullptr;
  274. param.ranges = nullptr;
  275. params = nullptr;
  276. }
  277. break;
  278. Q_UNUSED(pIns);
  279. Q_UNUSED(pOuts);
  280. }
  281. case PluginBridgeProgramCount:
  282. {
  283. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  284. const int32_t count = argv[0]->i;
  285. CARLA_ASSERT(count >= 0);
  286. // delete old programs
  287. if (prog.count > 0)
  288. {
  289. for (uint32_t i=0; i < prog.count; i++)
  290. {
  291. if (prog.names[i])
  292. free((void*)prog.names[i]);
  293. }
  294. delete[] prog.names;
  295. }
  296. prog.count = count;
  297. // create new if needed
  298. if (prog.count > 0)
  299. {
  300. prog.names = new const char* [prog.count];
  301. for (uint32_t i=0; i < prog.count; i++)
  302. prog.names[i] = nullptr;
  303. }
  304. else
  305. prog.names = nullptr;
  306. break;
  307. }
  308. case PluginBridgeMidiProgramCount:
  309. {
  310. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  311. const int32_t count = argv[0]->i;
  312. // delete old programs
  313. if (midiprog.count > 0)
  314. {
  315. for (uint32_t i=0; i < midiprog.count; i++)
  316. {
  317. if (midiprog.data[i].name)
  318. free((void*)midiprog.data[i].name);
  319. }
  320. delete[] midiprog.data;
  321. }
  322. // create new if needed
  323. midiprog.count = count;
  324. if (midiprog.count > 0)
  325. midiprog.data = new MidiProgramData[midiprog.count];
  326. else
  327. midiprog.data = nullptr;
  328. break;
  329. }
  330. #endif
  331. case kPluginBridgePluginInfo:
  332. {
  333. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh");
  334. const int32_t category = argv[0]->i;
  335. const int32_t hints = argv[1]->i;
  336. const char* const name = (const char*)&argv[2]->s;
  337. const char* const label = (const char*)&argv[3]->s;
  338. const char* const maker = (const char*)&argv[4]->s;
  339. const char* const copyright = (const char*)&argv[5]->s;
  340. const int64_t uniqueId = argv[6]->h;
  341. CARLA_ASSERT(category >= 0);
  342. CARLA_ASSERT(hints >= 0);
  343. CARLA_ASSERT(name);
  344. CARLA_ASSERT(label);
  345. CARLA_ASSERT(maker);
  346. CARLA_ASSERT(copyright);
  347. fHints = hints | PLUGIN_IS_BRIDGE;
  348. fInfo.category = static_cast<PluginCategory>(category);
  349. fInfo.uniqueId = uniqueId;
  350. fInfo.name = name;
  351. fInfo.label = label;
  352. fInfo.maker = maker;
  353. fInfo.copyright = copyright;
  354. if (fName.isEmpty())
  355. fName = kData->engine->getNewUniquePluginName(name);
  356. break;
  357. }
  358. #if 0
  359. case PluginBridgeParameterInfo:
  360. {
  361. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
  362. const int32_t index = argv[0]->i;
  363. const char* const name = (const char*)&argv[1]->s;
  364. const char* const unit = (const char*)&argv[2]->s;
  365. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  366. CARLA_ASSERT(name);
  367. CARLA_ASSERT(unit);
  368. if (index >= 0 && index < (int32_t)param.count)
  369. {
  370. params[index].name = QString(name);
  371. params[index].unit = QString(unit);
  372. }
  373. break;
  374. }
  375. case PluginBridgeParameterData:
  376. {
  377. CARLA_BRIDGE_CHECK_OSC_TYPES(6, "iiiiii");
  378. const int32_t index = argv[0]->i;
  379. const int32_t type = argv[1]->i;
  380. const int32_t rindex = argv[2]->i;
  381. const int32_t hints = argv[3]->i;
  382. const int32_t channel = argv[4]->i;
  383. const int32_t cc = argv[5]->i;
  384. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  385. CARLA_ASSERT(type >= 0);
  386. CARLA_ASSERT(rindex >= 0);
  387. CARLA_ASSERT(hints >= 0);
  388. CARLA_ASSERT(channel >= 0 && channel < 16);
  389. CARLA_ASSERT(cc >= -1);
  390. if (index >= 0 && index < (int32_t)param.count)
  391. {
  392. param.data[index].type = (ParameterType)type;
  393. param.data[index].index = index;
  394. param.data[index].rindex = rindex;
  395. param.data[index].hints = hints;
  396. param.data[index].midiChannel = channel;
  397. param.data[index].midiCC = cc;
  398. }
  399. break;
  400. }
  401. case PluginBridgeParameterRanges:
  402. {
  403. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "idddddd");
  404. const int32_t index = argv[0]->i;
  405. const double def = argv[1]->d;
  406. const double min = argv[2]->d;
  407. const double max = argv[3]->d;
  408. const double step = argv[4]->d;
  409. const double stepSmall = argv[5]->d;
  410. const double stepLarge = argv[6]->d;
  411. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  412. CARLA_ASSERT(min < max);
  413. CARLA_ASSERT(def >= min);
  414. CARLA_ASSERT(def <= max);
  415. if (index >= 0 && index < (int32_t)param.count)
  416. {
  417. param.ranges[index].def = def;
  418. param.ranges[index].min = min;
  419. param.ranges[index].max = max;
  420. param.ranges[index].step = step;
  421. param.ranges[index].stepSmall = stepSmall;
  422. param.ranges[index].stepLarge = stepLarge;
  423. params[index].value = def;
  424. }
  425. break;
  426. }
  427. case PluginBridgeProgramInfo:
  428. {
  429. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "is");
  430. const int32_t index = argv[0]->i;
  431. const char* const name = (const char*)&argv[1]->s;
  432. CARLA_ASSERT(index >= 0 && index < (int32_t)prog.count);
  433. CARLA_ASSERT(name);
  434. if (index >= 0 && index < (int32_t)prog.count)
  435. {
  436. if (prog.names[index])
  437. free((void*)prog.names[index]);
  438. prog.names[index] = strdup(name);
  439. }
  440. break;
  441. }
  442. case PluginBridgeMidiProgramInfo:
  443. {
  444. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "iiis");
  445. const int32_t index = argv[0]->i;
  446. const int32_t bank = argv[1]->i;
  447. const int32_t program = argv[2]->i;
  448. const char* const name = (const char*)&argv[3]->s;
  449. CARLA_ASSERT(index >= 0 && index < (int32_t)midiprog.count);
  450. CARLA_ASSERT(bank >= 0);
  451. CARLA_ASSERT(program >= 0 && program < 128);
  452. CARLA_ASSERT(name);
  453. if (index >= 0 && index < (int32_t)midiprog.count)
  454. {
  455. if (midiprog.data[index].name)
  456. free((void*)midiprog.data[index].name);
  457. midiprog.data[index].bank = bank;
  458. midiprog.data[index].program = program;
  459. midiprog.data[index].name = strdup(name);
  460. }
  461. break;
  462. }
  463. case PluginBridgeConfigure:
  464. {
  465. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");
  466. const char* const key = (const char*)&argv[0]->s;
  467. const char* const value = (const char*)&argv[1]->s;
  468. CARLA_ASSERT(key);
  469. CARLA_ASSERT(value);
  470. if (! (key && value))
  471. {
  472. // invalid
  473. pass();
  474. }
  475. else if (std::strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
  476. {
  477. x_engine->callback(CALLBACK_SHOW_GUI, m_id, 0, 0, 0.0, nullptr);
  478. }
  479. else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
  480. {
  481. m_saved = true;
  482. }
  483. break;
  484. }
  485. case PluginBridgeSetParameterValue:
  486. {
  487. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  488. const int32_t index = argv[0]->i;
  489. const double value = argv[1]->d;
  490. CARLA_ASSERT(index != PARAMETER_NULL);
  491. setParameterValueByRIndex(index, value, false, true, true);
  492. break;
  493. }
  494. case PluginBridgeSetDefaultValue:
  495. {
  496. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  497. const int32_t index = argv[0]->i;
  498. const double value = argv[1]->d;
  499. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  500. if (index >= 0 && index < (int32_t)param.count)
  501. param.ranges[index].def = value;
  502. break;
  503. }
  504. case PluginBridgeSetProgram:
  505. {
  506. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  507. const int32_t index = argv[0]->i;
  508. CARLA_ASSERT(index < (int32_t)prog.count);
  509. setProgram(index, false, true, true, true);
  510. break;
  511. }
  512. case PluginBridgeSetMidiProgram:
  513. {
  514. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  515. const int32_t index = argv[0]->i;
  516. CARLA_ASSERT(index < (int32_t)midiprog.count);
  517. setMidiProgram(index, false, true, true, true);
  518. break;
  519. }
  520. case PluginBridgeSetCustomData:
  521. {
  522. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");
  523. const char* const type = (const char*)&argv[0]->s;
  524. const char* const key = (const char*)&argv[1]->s;
  525. const char* const value = (const char*)&argv[2]->s;
  526. CARLA_ASSERT(type);
  527. CARLA_ASSERT(key);
  528. CARLA_ASSERT(value);
  529. setCustomData(type, key, value, false);
  530. break;
  531. }
  532. case PluginBridgeSetChunkData:
  533. {
  534. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  535. const char* const chunkFileChar = (const char*)&argv[0]->s;
  536. CARLA_ASSERT(chunkFileChar);
  537. QString chunkFileStr(chunkFileChar);
  538. #ifndef Q_OS_WIN
  539. // Using Wine, fix temp dir
  540. if (m_binary == BINARY_WIN32 || m_binary == BINARY_WIN64)
  541. {
  542. // Get WINEPREFIX
  543. QString wineDir;
  544. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  545. wineDir = QString(WINEPREFIX);
  546. else
  547. wineDir = QDir::homePath() + "/.wine";
  548. QStringList chunkFileStrSplit1 = chunkFileStr.split(":/");
  549. QStringList chunkFileStrSplit2 = chunkFileStrSplit1.at(1).split("\\");
  550. QString wineDrive = chunkFileStrSplit1.at(0).toLower();
  551. QString wineTMP = chunkFileStrSplit2.at(0);
  552. QString baseName = chunkFileStrSplit2.at(1);
  553. chunkFileStr = wineDir;
  554. chunkFileStr += "/drive_";
  555. chunkFileStr += wineDrive;
  556. chunkFileStr += "/";
  557. chunkFileStr += wineTMP;
  558. chunkFileStr += "/";
  559. chunkFileStr += baseName;
  560. chunkFileStr = QDir::toNativeSeparators(chunkFileStr);
  561. }
  562. #endif
  563. QFile chunkFile(chunkFileStr);
  564. if (chunkFile.open(QIODevice::ReadOnly))
  565. {
  566. info.chunk = chunkFile.readAll();
  567. chunkFile.close();
  568. chunkFile.remove();
  569. }
  570. break;
  571. }
  572. #endif
  573. case kPluginBridgeUpdateNow:
  574. {
  575. fInitiated = true;
  576. break;
  577. }
  578. case kPluginBridgeError:
  579. {
  580. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  581. const char* const error = (const char*)&argv[0]->s;
  582. CARLA_ASSERT(error != nullptr);
  583. kData->engine->setLastError(error);
  584. fInitError = true;
  585. fInitiated = true;
  586. break;
  587. }
  588. }
  589. return 0;
  590. }
  591. #if 0
  592. // -------------------------------------------------------------------
  593. // Set data (plugin-specific stuff)
  594. void setParameterValue(const uint32_t parameterId, double value, const bool sendGui, const bool sendOsc, const bool sendCallback)
  595. {
  596. CARLA_ASSERT(parameterId < param.count);
  597. params[parameterId].value = fixParameterValue(value, param.ranges[parameterId]);
  598. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  599. }
  600. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui)
  601. {
  602. CARLA_ASSERT(type);
  603. CARLA_ASSERT(key);
  604. CARLA_ASSERT(value);
  605. if (sendGui)
  606. {
  607. // TODO - if type is chunk|binary, store it in a file and send path instead
  608. QString cData;
  609. cData = type;
  610. cData += "·";
  611. cData += key;
  612. cData += "·";
  613. cData += value;
  614. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  615. }
  616. CarlaPlugin::setCustomData(type, key, value, sendGui);
  617. }
  618. void setChunkData(const char* const stringData)
  619. {
  620. CARLA_ASSERT(m_hints & PLUGIN_USES_CHUNKS);
  621. CARLA_ASSERT(stringData);
  622. QString filePath;
  623. filePath = QDir::tempPath();
  624. filePath += "/.CarlaChunk_";
  625. filePath += m_name;
  626. filePath = QDir::toNativeSeparators(filePath);
  627. QFile file(filePath);
  628. if (file.open(QIODevice::WriteOnly | QIODevice::Text))
  629. {
  630. QTextStream out(&file);
  631. out << stringData;
  632. file.close();
  633. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
  634. }
  635. }
  636. #endif
  637. // -------------------------------------------------------------------
  638. // Set gui stuff
  639. void showGui(const bool yesNo)
  640. {
  641. if (yesNo)
  642. osc_send_show(&kData->osc.data);
  643. else
  644. osc_send_hide(&kData->osc.data);
  645. }
  646. void idleGui()
  647. {
  648. if (! kData->osc.thread.isRunning())
  649. carla_stderr2("TESTING: Bridge has closed!");
  650. CarlaPlugin::idleGui();
  651. }
  652. // -------------------------------------------------------------------
  653. // Plugin state
  654. void reload()
  655. {
  656. carla_debug("BridgePlugin::reload() - start");
  657. CARLA_ASSERT(kData->engine != nullptr);
  658. if (kData->engine == nullptr)
  659. return;
  660. const ProcessMode processMode(kData->engine->getProccessMode());
  661. // Safely disable plugin for reload
  662. const ScopedDisabler sd(this);
  663. deleteBuffers();
  664. bool needsCtrlIn, needsCtrlOut;
  665. needsCtrlIn = needsCtrlOut = false;
  666. if (fInfo.aIns > 0)
  667. {
  668. kData->audioIn.createNew(fInfo.aIns);
  669. }
  670. if (fInfo.aOuts > 0)
  671. {
  672. kData->audioOut.createNew(fInfo.aOuts);
  673. needsCtrlIn = true;
  674. }
  675. if (fInfo.mIns > 0)
  676. needsCtrlIn = true;
  677. if (fInfo.mOuts > 0)
  678. needsCtrlOut = true;
  679. const uint portNameSize = kData->engine->maxPortNameSize();
  680. CarlaString portName;
  681. // Audio Ins
  682. for (uint32_t j=0; j < fInfo.aIns; j++)
  683. {
  684. portName.clear();
  685. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  686. {
  687. portName = fName;
  688. portName += ":";
  689. }
  690. if (fInfo.aIns > 1)
  691. {
  692. portName += "input_";
  693. portName += CarlaString(j+1);
  694. }
  695. else
  696. portName += "input";
  697. portName.truncate(portNameSize);
  698. kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  699. kData->audioIn.ports[j].rindex = j;
  700. }
  701. // Audio Outs
  702. for (uint32_t j=0; j < fInfo.aOuts; j++)
  703. {
  704. portName.clear();
  705. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  706. {
  707. portName = fName;
  708. portName += ":";
  709. }
  710. if (fInfo.aOuts > 1)
  711. {
  712. portName += "output_";
  713. portName += CarlaString(j+1);
  714. }
  715. else
  716. portName += "output";
  717. portName.truncate(portNameSize);
  718. kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  719. kData->audioOut.ports[j].rindex = j;
  720. }
  721. if (needsCtrlIn)
  722. {
  723. portName.clear();
  724. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  725. {
  726. portName = fName;
  727. portName += ":";
  728. }
  729. portName += "event-in";
  730. portName.truncate(portNameSize);
  731. kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
  732. }
  733. if (needsCtrlOut)
  734. {
  735. portName.clear();
  736. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  737. {
  738. portName = fName;
  739. portName += ":";
  740. }
  741. portName += "event-out";
  742. portName.truncate(portNameSize);
  743. kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
  744. }
  745. //bufferSizeChanged(kData->engine->getBufferSize());
  746. //reloadPrograms(true);
  747. carla_debug("BridgePlugin::reload() - end");
  748. }
  749. #if 0
  750. void prepareForSave()
  751. {
  752. m_saved = false;
  753. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SAVE_NOW, "");
  754. for (int i=0; i < 200; i++)
  755. {
  756. if (m_saved)
  757. break;
  758. carla_msleep(50);
  759. }
  760. if (! m_saved)
  761. carla_stderr("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  762. else
  763. carla_debug("BridgePlugin::prepareForSave() - success!");
  764. }
  765. #endif
  766. // -------------------------------------------------------------------
  767. // Plugin processing
  768. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames)
  769. {
  770. uint32_t i, k;
  771. // --------------------------------------------------------------------------------------------------------
  772. // Check if active
  773. if (! kData->active)
  774. {
  775. // disable any output sound
  776. for (i=0; i < kData->audioOut.count; i++)
  777. carla_zeroFloat(outBuffer[i], frames);
  778. kData->activeBefore = kData->active;
  779. return;
  780. }
  781. for (i=0; i < fInfo.aIns; ++i)
  782. carla_copyFloat(fShmAudioPool.data + i * frames, inBuffer[i], frames);
  783. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeProcess);
  784. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  785. waitForServer();
  786. for (i=0; i < fInfo.aOuts; ++i)
  787. carla_copyFloat(outBuffer[i], fShmAudioPool.data + (i+fInfo.aIns) * frames, frames);
  788. }
  789. // -------------------------------------------------------------------
  790. // Post-poned events
  791. void uiParameterChange(const uint32_t index, const float value)
  792. {
  793. CARLA_ASSERT(index < kData->param.count);
  794. if (index >= kData->param.count)
  795. return;
  796. if (kData->osc.data.target == nullptr)
  797. return;
  798. osc_send_control(&kData->osc.data, kData->param.data[index].rindex, value);
  799. }
  800. void uiProgramChange(const uint32_t index)
  801. {
  802. CARLA_ASSERT(index < kData->prog.count);
  803. if (index >= kData->prog.count)
  804. return;
  805. if (kData->osc.data.target == nullptr)
  806. return;
  807. osc_send_program(&kData->osc.data, index);
  808. }
  809. void uiMidiProgramChange(const uint32_t index)
  810. {
  811. CARLA_ASSERT(index < kData->midiprog.count);
  812. if (index >= kData->midiprog.count)
  813. return;
  814. if (kData->osc.data.target == nullptr)
  815. return;
  816. osc_send_midi_program(&kData->osc.data, index);
  817. }
  818. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
  819. {
  820. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  821. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  822. CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);
  823. if (channel >= MAX_MIDI_CHANNELS)
  824. return;
  825. if (note >= MAX_MIDI_NOTE)
  826. return;
  827. if (velo >= MAX_MIDI_VALUE)
  828. return;
  829. if (kData->osc.data.target == nullptr)
  830. return;
  831. uint8_t midiData[4] = { 0 };
  832. midiData[1] = MIDI_STATUS_NOTE_ON + channel;
  833. midiData[2] = note;
  834. midiData[3] = velo;
  835. osc_send_midi(&kData->osc.data, midiData);
  836. }
  837. void uiNoteOff(const uint8_t channel, const uint8_t note)
  838. {
  839. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  840. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  841. if (channel >= MAX_MIDI_CHANNELS)
  842. return;
  843. if (note >= MAX_MIDI_NOTE)
  844. return;
  845. if (kData->osc.data.target == nullptr)
  846. return;
  847. uint8_t midiData[4] = { 0 };
  848. midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
  849. midiData[2] = note;
  850. osc_send_midi(&kData->osc.data, midiData);
  851. }
  852. void bufferSizeChanged(const uint32_t newBufferSize)
  853. {
  854. resizeAudioPool(newBufferSize);
  855. }
  856. // -------------------------------------------------------------------
  857. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  858. {
  859. CARLA_ASSERT(kData->engine != nullptr);
  860. CARLA_ASSERT(kData->client == nullptr);
  861. CARLA_ASSERT(filename != nullptr);
  862. // ---------------------------------------------------------------
  863. // first checks
  864. if (kData->engine == nullptr)
  865. {
  866. return false;
  867. }
  868. if (kData->client != nullptr)
  869. {
  870. kData->engine->setLastError("Plugin client is already registered");
  871. return false;
  872. }
  873. if (filename == nullptr)
  874. {
  875. kData->engine->setLastError("null filename");
  876. return false;
  877. }
  878. // ---------------------------------------------------------------
  879. // set info
  880. if (name != nullptr)
  881. fName = kData->engine->getNewUniquePluginName(name);
  882. fFilename = filename;
  883. // ---------------------------------------------------------------
  884. // register client
  885. kData->client = kData->engine->addClient(this);
  886. if (kData->client == nullptr || ! kData->client->isOk())
  887. {
  888. kData->engine->setLastError("Failed to register plugin client");
  889. return false;
  890. }
  891. // ---------------------------------------------------------------
  892. // SHM Audio Pool
  893. {
  894. char tmpFileBase[60];
  895. std::srand(std::time(NULL));
  896. std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");
  897. fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
  898. if (! carla_is_shm_valid(fShmAudioPool.shm))
  899. {
  900. //_cleanup();
  901. carla_stdout("Failed to open or create shared memory file #1");
  902. return false;
  903. }
  904. fShmAudioPool.filename = tmpFileBase;
  905. }
  906. // ---------------------------------------------------------------
  907. // SHM Control
  908. {
  909. char tmpFileBase[60];
  910. std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX");
  911. fShmControl.shm = shm_mkstemp(tmpFileBase);
  912. if (! carla_is_shm_valid(fShmControl.shm))
  913. {
  914. //_cleanup();
  915. carla_stdout("Failed to open or create shared memory file #2");
  916. return false;
  917. }
  918. fShmControl.filename = tmpFileBase;
  919. if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
  920. {
  921. //_cleanup();
  922. carla_stdout("Failed to mmap shared memory file");
  923. return false;
  924. }
  925. CARLA_ASSERT(fShmControl.data != nullptr);
  926. std::memset(fShmControl.data, 0, sizeof(BridgeShmControl));
  927. std::strcpy(fShmControl.data->ringBuffer.buf, "This thing is actually working!!!!");
  928. if (sem_init(&fShmControl.data->runServer, 1, 0) != 0)
  929. {
  930. //_cleanup();
  931. carla_stdout("Failed to initialize shared memory semaphore #1");
  932. return false;
  933. }
  934. if (sem_init(&fShmControl.data->runClient, 1, 0) != 0)
  935. {
  936. //_cleanup();
  937. carla_stdout("Failed to initialize shared memory semaphore #2");
  938. return false;
  939. }
  940. }
  941. // initial values
  942. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeBufferSize);
  943. rdwr_writeInt(&fShmControl.data->ringBuffer, kData->engine->getBufferSize());
  944. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSampleRate);
  945. rdwr_writeFloat(&fShmControl.data->ringBuffer, kData->engine->getSampleRate());
  946. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  947. // register plugin now so we can receive OSC (and wait for it)
  948. fHints |= PLUGIN_IS_BRIDGE;
  949. registerEnginePlugin(kData->engine, fId, this);
  950. // init OSC
  951. {
  952. char shmIdStr[12+1] = { 0 };
  953. std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  954. std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6);
  955. kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
  956. kData->osc.thread.start();
  957. kData->osc.thread.waitForStarted();
  958. }
  959. for (int i=0; i < 200; i++)
  960. {
  961. if (fInitiated || ! kData->osc.thread.isRunning())
  962. break;
  963. carla_msleep(50);
  964. }
  965. if (! fInitiated)
  966. {
  967. // unregister so it gets handled properly
  968. registerEnginePlugin(kData->engine, fId, nullptr);
  969. if (kData->osc.thread.isRunning())
  970. kData->osc.thread.terminate();
  971. kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  972. return false;
  973. }
  974. else if (fInitError)
  975. {
  976. // unregister so it gets handled properly
  977. registerEnginePlugin(kData->engine, fId, nullptr);
  978. kData->osc.thread.stop();
  979. // last error was set before
  980. return false;
  981. }
  982. resizeAudioPool(kData->engine->getBufferSize());
  983. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeReadyWait);
  984. rdwr_writeInt(&fShmControl.data->ringBuffer, fShmAudioPool.size);
  985. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  986. waitForServer();
  987. return true;
  988. }
  989. private:
  990. const BinaryType fBinaryType;
  991. const PluginType fPluginType;
  992. bool fInitiated;
  993. bool fInitError;
  994. bool fSaved;
  995. struct BridgeAudioPool {
  996. CarlaString filename;
  997. float* data;
  998. size_t size;
  999. shm_t shm;
  1000. BridgeAudioPool()
  1001. : data(nullptr),
  1002. size(0)
  1003. {
  1004. carla_shm_init(shm);
  1005. }
  1006. } fShmAudioPool;
  1007. struct BridgeControl {
  1008. CarlaString filename;
  1009. BridgeShmControl* data;
  1010. shm_t shm;
  1011. BridgeControl()
  1012. : data(nullptr)
  1013. {
  1014. carla_shm_init(shm);
  1015. }
  1016. } fShmControl;
  1017. struct Info {
  1018. uint32_t aIns, aOuts;
  1019. uint32_t mIns, mOuts;
  1020. PluginCategory category;
  1021. long uniqueId;
  1022. CarlaString name;
  1023. CarlaString label;
  1024. CarlaString maker;
  1025. CarlaString copyright;
  1026. //QByteArray chunk;
  1027. Info()
  1028. : aIns(0),
  1029. aOuts(0),
  1030. mIns(0),
  1031. mOuts(0),
  1032. category(PLUGIN_CATEGORY_NONE),
  1033. uniqueId(0) {}
  1034. } fInfo;
  1035. BridgeParamInfo* fParams;
  1036. void _cleanup()
  1037. {
  1038. if (fShmAudioPool.filename.isNotEmpty())
  1039. fShmAudioPool.filename.clear();
  1040. if (fShmControl.filename.isNotEmpty())
  1041. fShmControl.filename.clear();
  1042. if (fShmAudioPool.data != nullptr)
  1043. {
  1044. carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
  1045. fShmAudioPool.data = nullptr;
  1046. }
  1047. fShmAudioPool.size = 0;
  1048. // and again
  1049. if (fShmControl.data != nullptr)
  1050. {
  1051. carla_shm_unmap(fShmControl.shm, fShmControl.data, sizeof(BridgeShmControl));
  1052. fShmControl.data = nullptr;
  1053. }
  1054. if (carla_is_shm_valid(fShmAudioPool.shm))
  1055. carla_shm_close(fShmAudioPool.shm);
  1056. if (carla_is_shm_valid(fShmControl.shm))
  1057. carla_shm_close(fShmControl.shm);
  1058. }
  1059. void resizeAudioPool(const uint32_t bufferSize)
  1060. {
  1061. if (fShmAudioPool.data != nullptr)
  1062. carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
  1063. fShmAudioPool.size = (fInfo.aIns+fInfo.aOuts)*bufferSize*sizeof(float);
  1064. if (fShmAudioPool.size > 0)
  1065. fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, fShmAudioPool.size);
  1066. else
  1067. fShmAudioPool.data = nullptr;
  1068. }
  1069. void waitForServer()
  1070. {
  1071. sem_post(&fShmControl.data->runServer);
  1072. timespec ts_timeout;
  1073. clock_gettime(CLOCK_REALTIME, &ts_timeout);
  1074. ts_timeout.tv_sec += 5;
  1075. if (sem_timedwait(&fShmControl.data->runClient, &ts_timeout) != 0)
  1076. kData->active = false; // TODO
  1077. }
  1078. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
  1079. };
  1080. CARLA_BACKEND_END_NAMESPACE
  1081. #endif // ! BUILD_BRIDGE
  1082. CARLA_BACKEND_START_NAMESPACE
  1083. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
  1084. {
  1085. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1086. #ifndef BUILD_BRIDGE
  1087. if (bridgeBinary == nullptr)
  1088. {
  1089. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1090. return nullptr;
  1091. }
  1092. BridgePlugin* const plugin = new BridgePlugin(init.engine, init.id, btype, ptype);
  1093. if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
  1094. {
  1095. delete plugin;
  1096. return nullptr;
  1097. }
  1098. plugin->reload();
  1099. return plugin;
  1100. #else
  1101. init.engine->setLastError("Plugin bridge support not available");
  1102. return nullptr;
  1103. // unused
  1104. (void)bridgeBinary;
  1105. #endif
  1106. }
  1107. #ifndef BUILD_BRIDGE
  1108. // -------------------------------------------------------------------
  1109. // Bridge Helper
  1110. int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type,
  1111. const int argc, const lo_arg* const* const argv, const char* const types)
  1112. {
  1113. return ((BridgePlugin*)plugin)->setOscPluginBridgeInfo(type, argc, argv, types);
  1114. }
  1115. #endif
  1116. CARLA_BACKEND_END_NAMESPACE