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.

1206 lines
34KB

  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. std::srand(std::time(NULL));
  73. while (true)
  74. {
  75. for (int c = size - 6; c < size; c++)
  76. {
  77. // Note the -1 to avoid the trailing '\0' in charSet.
  78. fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)];
  79. }
  80. shm_t shm = carla_shm_create(fileBase);
  81. if (carla_is_shm_valid(shm) || errno != EEXIST)
  82. return shm;
  83. }
  84. }
  85. // -------------------------------------------------------------------------------------------------------------------
  86. struct BridgeParamInfo {
  87. float value;
  88. CarlaString name;
  89. CarlaString unit;
  90. BridgeParamInfo()
  91. : value(0.0f) {}
  92. };
  93. class BridgePlugin : public CarlaPlugin
  94. {
  95. public:
  96. BridgePlugin(CarlaEngine* const engine, const unsigned int id, const BinaryType btype, const PluginType ptype)
  97. : CarlaPlugin(engine, id),
  98. fBinaryType(btype),
  99. fPluginType(ptype),
  100. fInitiated(false),
  101. fInitError(false),
  102. fSaved(false),
  103. fParams(nullptr)
  104. {
  105. carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  106. kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  107. }
  108. ~BridgePlugin()
  109. {
  110. carla_debug("BridgePlugin::~BridgePlugin()");
  111. kData->singleMutex.lock();
  112. kData->masterMutex.lock();
  113. #if 0
  114. if (osc.data.target)
  115. {
  116. osc_send_hide(&osc.data);
  117. osc_send_quit(&osc.data);
  118. osc.data.free();
  119. }
  120. if (osc.thread)
  121. {
  122. // Wait a bit first, try safe quit, then force kill
  123. if (osc.thread->isRunning() && ! osc.thread->wait(3000))
  124. {
  125. carla_stderr("Failed to properly stop Plugin Bridge thread");
  126. osc.thread->terminate();
  127. }
  128. delete osc.thread;
  129. }
  130. info.chunk.clear();
  131. #endif
  132. }
  133. // -------------------------------------------------------------------
  134. // Information (base)
  135. PluginType type() const
  136. {
  137. return fPluginType;
  138. }
  139. PluginCategory category()
  140. {
  141. return fInfo.category;
  142. }
  143. long uniqueId() const
  144. {
  145. return fInfo.uniqueId;
  146. }
  147. // -------------------------------------------------------------------
  148. // Information (count)
  149. uint32_t audioInCount()
  150. {
  151. return fInfo.aIns;
  152. }
  153. uint32_t audioOutCount()
  154. {
  155. return fInfo.aOuts;
  156. }
  157. uint32_t midiInCount()
  158. {
  159. return fInfo.mIns;
  160. }
  161. uint32_t midiOutCount()
  162. {
  163. return fInfo.mOuts;
  164. }
  165. #if 0
  166. // -------------------------------------------------------------------
  167. // Information (current data)
  168. int32_t chunkData(void** const dataPtr)
  169. {
  170. CARLA_ASSERT(dataPtr);
  171. if (! info.chunk.isEmpty())
  172. {
  173. *dataPtr = info.chunk.data();
  174. return info.chunk.size();
  175. }
  176. return 0;
  177. }
  178. // -------------------------------------------------------------------
  179. // Information (per-plugin data)
  180. double getParameterValue(const uint32_t parameterId)
  181. {
  182. CARLA_ASSERT(parameterId < param.count);
  183. return params[parameterId].value;
  184. }
  185. void getLabel(char* const strBuf)
  186. {
  187. if (info.label)
  188. strncpy(strBuf, info.label, STR_MAX);
  189. else
  190. CarlaPlugin::getLabel(strBuf);
  191. }
  192. void getMaker(char* const strBuf)
  193. {
  194. if (info.maker)
  195. strncpy(strBuf, info.maker, STR_MAX);
  196. else
  197. CarlaPlugin::getMaker(strBuf);
  198. }
  199. void getCopyright(char* const strBuf)
  200. {
  201. if (info.copyright)
  202. strncpy(strBuf, info.copyright, STR_MAX);
  203. else
  204. CarlaPlugin::getCopyright(strBuf);
  205. }
  206. void getRealName(char* const strBuf)
  207. {
  208. if (info.name)
  209. strncpy(strBuf, info.name, STR_MAX);
  210. else
  211. CarlaPlugin::getRealName(strBuf);
  212. }
  213. void getParameterName(const uint32_t parameterId, char* const strBuf)
  214. {
  215. CARLA_ASSERT(parameterId < param.count);
  216. strncpy(strBuf, params[parameterId].name.toUtf8().constData(), STR_MAX);
  217. }
  218. void getParameterUnit(const uint32_t parameterId, char* const strBuf)
  219. {
  220. CARLA_ASSERT(parameterId < param.count);
  221. strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX);
  222. }
  223. void getGuiInfo(GuiType* const type, bool* const resizable)
  224. {
  225. if (m_hints & PLUGIN_HAS_GUI)
  226. *type = GUI_EXTERNAL_OSC;
  227. else
  228. *type = GUI_NONE;
  229. *resizable = false;
  230. }
  231. #endif
  232. // -------------------------------------------------------------------
  233. // Set data (internal stuff)
  234. int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types)
  235. {
  236. carla_debug("setOscPluginBridgeInfo(%i, %i, %p, \"%s\")", type, argc, argv, types);
  237. #if 0
  238. switch (type)
  239. {
  240. case PluginBridgeAudioCount:
  241. {
  242. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  243. const int32_t aIns = argv[0]->i;
  244. const int32_t aOuts = argv[1]->i;
  245. const int32_t aTotal = argv[2]->i;
  246. CARLA_ASSERT(aIns >= 0);
  247. CARLA_ASSERT(aOuts >= 0);
  248. CARLA_ASSERT(aIns + aOuts == aTotal);
  249. info.aIns = aIns;
  250. info.aOuts = aOuts;
  251. break;
  252. Q_UNUSED(aTotal);
  253. }
  254. case PluginBridgeMidiCount:
  255. {
  256. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  257. const int32_t mIns = argv[0]->i;
  258. const int32_t mOuts = argv[1]->i;
  259. const int32_t mTotal = argv[2]->i;
  260. CARLA_ASSERT(mIns >= 0);
  261. CARLA_ASSERT(mOuts >= 0);
  262. CARLA_ASSERT(mIns + mOuts == mTotal);
  263. info.mIns = mIns;
  264. info.mOuts = mOuts;
  265. break;
  266. Q_UNUSED(mTotal);
  267. }
  268. case PluginBridgeParameterCount:
  269. {
  270. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  271. const int32_t pIns = argv[0]->i;
  272. const int32_t pOuts = argv[1]->i;
  273. const int32_t pTotal = argv[2]->i;
  274. CARLA_ASSERT(pIns >= 0);
  275. CARLA_ASSERT(pOuts >= 0);
  276. CARLA_ASSERT(pIns + pOuts <= pTotal);
  277. // delete old data
  278. if (param.count > 0)
  279. {
  280. delete[] param.data;
  281. delete[] param.ranges;
  282. delete[] params;
  283. }
  284. // create new if needed
  285. const int32_t maxParams = x_engine->getOptions().maxParameters;
  286. param.count = (pTotal < maxParams) ? pTotal : 0;
  287. if (param.count > 0)
  288. {
  289. param.data = new ParameterData[param.count];
  290. param.ranges = new ParameterRanges[param.count];
  291. params = new BridgeParamInfo[param.count];
  292. }
  293. else
  294. {
  295. param.data = nullptr;
  296. param.ranges = nullptr;
  297. params = nullptr;
  298. }
  299. break;
  300. Q_UNUSED(pIns);
  301. Q_UNUSED(pOuts);
  302. }
  303. case PluginBridgeProgramCount:
  304. {
  305. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  306. const int32_t count = argv[0]->i;
  307. CARLA_ASSERT(count >= 0);
  308. // delete old programs
  309. if (prog.count > 0)
  310. {
  311. for (uint32_t i=0; i < prog.count; i++)
  312. {
  313. if (prog.names[i])
  314. free((void*)prog.names[i]);
  315. }
  316. delete[] prog.names;
  317. }
  318. prog.count = count;
  319. // create new if needed
  320. if (prog.count > 0)
  321. {
  322. prog.names = new const char* [prog.count];
  323. for (uint32_t i=0; i < prog.count; i++)
  324. prog.names[i] = nullptr;
  325. }
  326. else
  327. prog.names = nullptr;
  328. break;
  329. }
  330. case PluginBridgeMidiProgramCount:
  331. {
  332. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  333. const int32_t count = argv[0]->i;
  334. // delete old programs
  335. if (midiprog.count > 0)
  336. {
  337. for (uint32_t i=0; i < midiprog.count; i++)
  338. {
  339. if (midiprog.data[i].name)
  340. free((void*)midiprog.data[i].name);
  341. }
  342. delete[] midiprog.data;
  343. }
  344. // create new if needed
  345. midiprog.count = count;
  346. if (midiprog.count > 0)
  347. midiprog.data = new MidiProgramData[midiprog.count];
  348. else
  349. midiprog.data = nullptr;
  350. break;
  351. }
  352. case PluginBridgePluginInfo:
  353. {
  354. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh");
  355. const int32_t category = argv[0]->i;
  356. const int32_t hints = argv[1]->i;
  357. const char* const name = (const char*)&argv[2]->s;
  358. const char* const label = (const char*)&argv[3]->s;
  359. const char* const maker = (const char*)&argv[4]->s;
  360. const char* const copyright = (const char*)&argv[5]->s;
  361. const int64_t uniqueId = argv[6]->h;
  362. CARLA_ASSERT(category >= 0);
  363. CARLA_ASSERT(hints >= 0);
  364. CARLA_ASSERT(name);
  365. CARLA_ASSERT(label);
  366. CARLA_ASSERT(maker);
  367. CARLA_ASSERT(copyright);
  368. m_hints = hints | PLUGIN_IS_BRIDGE;
  369. info.category = (PluginCategory)category;
  370. info.uniqueId = uniqueId;
  371. info.name = strdup(name);
  372. info.label = strdup(label);
  373. info.maker = strdup(maker);
  374. info.copyright = strdup(copyright);
  375. if (! m_name)
  376. m_name = x_engine->getUniquePluginName(name);
  377. break;
  378. }
  379. case PluginBridgeParameterInfo:
  380. {
  381. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
  382. const int32_t index = argv[0]->i;
  383. const char* const name = (const char*)&argv[1]->s;
  384. const char* const unit = (const char*)&argv[2]->s;
  385. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  386. CARLA_ASSERT(name);
  387. CARLA_ASSERT(unit);
  388. if (index >= 0 && index < (int32_t)param.count)
  389. {
  390. params[index].name = QString(name);
  391. params[index].unit = QString(unit);
  392. }
  393. break;
  394. }
  395. case PluginBridgeParameterData:
  396. {
  397. CARLA_BRIDGE_CHECK_OSC_TYPES(6, "iiiiii");
  398. const int32_t index = argv[0]->i;
  399. const int32_t type = argv[1]->i;
  400. const int32_t rindex = argv[2]->i;
  401. const int32_t hints = argv[3]->i;
  402. const int32_t channel = argv[4]->i;
  403. const int32_t cc = argv[5]->i;
  404. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  405. CARLA_ASSERT(type >= 0);
  406. CARLA_ASSERT(rindex >= 0);
  407. CARLA_ASSERT(hints >= 0);
  408. CARLA_ASSERT(channel >= 0 && channel < 16);
  409. CARLA_ASSERT(cc >= -1);
  410. if (index >= 0 && index < (int32_t)param.count)
  411. {
  412. param.data[index].type = (ParameterType)type;
  413. param.data[index].index = index;
  414. param.data[index].rindex = rindex;
  415. param.data[index].hints = hints;
  416. param.data[index].midiChannel = channel;
  417. param.data[index].midiCC = cc;
  418. }
  419. break;
  420. }
  421. case PluginBridgeParameterRanges:
  422. {
  423. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "idddddd");
  424. const int32_t index = argv[0]->i;
  425. const double def = argv[1]->d;
  426. const double min = argv[2]->d;
  427. const double max = argv[3]->d;
  428. const double step = argv[4]->d;
  429. const double stepSmall = argv[5]->d;
  430. const double stepLarge = argv[6]->d;
  431. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  432. CARLA_ASSERT(min < max);
  433. CARLA_ASSERT(def >= min);
  434. CARLA_ASSERT(def <= max);
  435. if (index >= 0 && index < (int32_t)param.count)
  436. {
  437. param.ranges[index].def = def;
  438. param.ranges[index].min = min;
  439. param.ranges[index].max = max;
  440. param.ranges[index].step = step;
  441. param.ranges[index].stepSmall = stepSmall;
  442. param.ranges[index].stepLarge = stepLarge;
  443. params[index].value = def;
  444. }
  445. break;
  446. }
  447. case PluginBridgeProgramInfo:
  448. {
  449. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "is");
  450. const int32_t index = argv[0]->i;
  451. const char* const name = (const char*)&argv[1]->s;
  452. CARLA_ASSERT(index >= 0 && index < (int32_t)prog.count);
  453. CARLA_ASSERT(name);
  454. if (index >= 0 && index < (int32_t)prog.count)
  455. {
  456. if (prog.names[index])
  457. free((void*)prog.names[index]);
  458. prog.names[index] = strdup(name);
  459. }
  460. break;
  461. }
  462. case PluginBridgeMidiProgramInfo:
  463. {
  464. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "iiis");
  465. const int32_t index = argv[0]->i;
  466. const int32_t bank = argv[1]->i;
  467. const int32_t program = argv[2]->i;
  468. const char* const name = (const char*)&argv[3]->s;
  469. CARLA_ASSERT(index >= 0 && index < (int32_t)midiprog.count);
  470. CARLA_ASSERT(bank >= 0);
  471. CARLA_ASSERT(program >= 0 && program < 128);
  472. CARLA_ASSERT(name);
  473. if (index >= 0 && index < (int32_t)midiprog.count)
  474. {
  475. if (midiprog.data[index].name)
  476. free((void*)midiprog.data[index].name);
  477. midiprog.data[index].bank = bank;
  478. midiprog.data[index].program = program;
  479. midiprog.data[index].name = strdup(name);
  480. }
  481. break;
  482. }
  483. case PluginBridgeConfigure:
  484. {
  485. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");
  486. const char* const key = (const char*)&argv[0]->s;
  487. const char* const value = (const char*)&argv[1]->s;
  488. CARLA_ASSERT(key);
  489. CARLA_ASSERT(value);
  490. if (! (key && value))
  491. {
  492. // invalid
  493. pass();
  494. }
  495. else if (std::strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
  496. {
  497. x_engine->callback(CALLBACK_SHOW_GUI, m_id, 0, 0, 0.0, nullptr);
  498. }
  499. else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
  500. {
  501. m_saved = true;
  502. }
  503. break;
  504. }
  505. case PluginBridgeSetParameterValue:
  506. {
  507. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  508. const int32_t index = argv[0]->i;
  509. const double value = argv[1]->d;
  510. CARLA_ASSERT(index != PARAMETER_NULL);
  511. setParameterValueByRIndex(index, value, false, true, true);
  512. break;
  513. }
  514. case PluginBridgeSetDefaultValue:
  515. {
  516. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  517. const int32_t index = argv[0]->i;
  518. const double value = argv[1]->d;
  519. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  520. if (index >= 0 && index < (int32_t)param.count)
  521. param.ranges[index].def = value;
  522. break;
  523. }
  524. case PluginBridgeSetProgram:
  525. {
  526. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  527. const int32_t index = argv[0]->i;
  528. CARLA_ASSERT(index < (int32_t)prog.count);
  529. setProgram(index, false, true, true, true);
  530. break;
  531. }
  532. case PluginBridgeSetMidiProgram:
  533. {
  534. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  535. const int32_t index = argv[0]->i;
  536. CARLA_ASSERT(index < (int32_t)midiprog.count);
  537. setMidiProgram(index, false, true, true, true);
  538. break;
  539. }
  540. case PluginBridgeSetCustomData:
  541. {
  542. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");
  543. const char* const type = (const char*)&argv[0]->s;
  544. const char* const key = (const char*)&argv[1]->s;
  545. const char* const value = (const char*)&argv[2]->s;
  546. CARLA_ASSERT(type);
  547. CARLA_ASSERT(key);
  548. CARLA_ASSERT(value);
  549. setCustomData(type, key, value, false);
  550. break;
  551. }
  552. case PluginBridgeSetChunkData:
  553. {
  554. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  555. const char* const chunkFileChar = (const char*)&argv[0]->s;
  556. CARLA_ASSERT(chunkFileChar);
  557. QString chunkFileStr(chunkFileChar);
  558. #ifndef Q_OS_WIN
  559. // Using Wine, fix temp dir
  560. if (m_binary == BINARY_WIN32 || m_binary == BINARY_WIN64)
  561. {
  562. // Get WINEPREFIX
  563. QString wineDir;
  564. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  565. wineDir = QString(WINEPREFIX);
  566. else
  567. wineDir = QDir::homePath() + "/.wine";
  568. QStringList chunkFileStrSplit1 = chunkFileStr.split(":/");
  569. QStringList chunkFileStrSplit2 = chunkFileStrSplit1.at(1).split("\\");
  570. QString wineDrive = chunkFileStrSplit1.at(0).toLower();
  571. QString wineTMP = chunkFileStrSplit2.at(0);
  572. QString baseName = chunkFileStrSplit2.at(1);
  573. chunkFileStr = wineDir;
  574. chunkFileStr += "/drive_";
  575. chunkFileStr += wineDrive;
  576. chunkFileStr += "/";
  577. chunkFileStr += wineTMP;
  578. chunkFileStr += "/";
  579. chunkFileStr += baseName;
  580. chunkFileStr = QDir::toNativeSeparators(chunkFileStr);
  581. }
  582. #endif
  583. QFile chunkFile(chunkFileStr);
  584. if (chunkFile.open(QIODevice::ReadOnly))
  585. {
  586. info.chunk = chunkFile.readAll();
  587. chunkFile.close();
  588. chunkFile.remove();
  589. }
  590. break;
  591. }
  592. case PluginBridgeUpdateNow:
  593. {
  594. m_initiated = true;
  595. break;
  596. }
  597. case PluginBridgeError:
  598. {
  599. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  600. const char* const error = (const char*)&argv[0]->s;
  601. CARLA_ASSERT(error);
  602. m_initiated = true;
  603. m_initError = true;
  604. x_engine->setLastError(error);
  605. break;
  606. }
  607. }
  608. #endif
  609. return 0;
  610. }
  611. #if 0
  612. // -------------------------------------------------------------------
  613. // Set data (plugin-specific stuff)
  614. void setParameterValue(const uint32_t parameterId, double value, const bool sendGui, const bool sendOsc, const bool sendCallback)
  615. {
  616. CARLA_ASSERT(parameterId < param.count);
  617. params[parameterId].value = fixParameterValue(value, param.ranges[parameterId]);
  618. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  619. }
  620. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui)
  621. {
  622. CARLA_ASSERT(type);
  623. CARLA_ASSERT(key);
  624. CARLA_ASSERT(value);
  625. if (sendGui)
  626. {
  627. // TODO - if type is chunk|binary, store it in a file and send path instead
  628. QString cData;
  629. cData = type;
  630. cData += "·";
  631. cData += key;
  632. cData += "·";
  633. cData += value;
  634. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  635. }
  636. CarlaPlugin::setCustomData(type, key, value, sendGui);
  637. }
  638. void setChunkData(const char* const stringData)
  639. {
  640. CARLA_ASSERT(m_hints & PLUGIN_USES_CHUNKS);
  641. CARLA_ASSERT(stringData);
  642. QString filePath;
  643. filePath = QDir::tempPath();
  644. filePath += "/.CarlaChunk_";
  645. filePath += m_name;
  646. filePath = QDir::toNativeSeparators(filePath);
  647. QFile file(filePath);
  648. if (file.open(QIODevice::WriteOnly | QIODevice::Text))
  649. {
  650. QTextStream out(&file);
  651. out << stringData;
  652. file.close();
  653. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
  654. }
  655. }
  656. // -------------------------------------------------------------------
  657. // Set gui stuff
  658. void showGui(const bool yesNo)
  659. {
  660. if (yesNo)
  661. osc_send_show(&osc.data);
  662. else
  663. osc_send_hide(&osc.data);
  664. }
  665. void idleGui()
  666. {
  667. if (! osc.thread->isRunning())
  668. carla_stderr("TESTING: Bridge has closed!");
  669. CarlaPlugin::idleGui();
  670. }
  671. // -------------------------------------------------------------------
  672. // Plugin state
  673. void prepareForSave()
  674. {
  675. m_saved = false;
  676. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SAVE_NOW, "");
  677. for (int i=0; i < 200; i++)
  678. {
  679. if (m_saved)
  680. break;
  681. carla_msleep(50);
  682. }
  683. if (! m_saved)
  684. carla_stderr("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  685. else
  686. carla_debug("BridgePlugin::prepareForSave() - success!");
  687. }
  688. // -------------------------------------------------------------------
  689. // Post-poned events
  690. void uiParameterChange(const uint32_t index, const double value)
  691. {
  692. CARLA_ASSERT(index < param.count);
  693. if (index >= param.count)
  694. return;
  695. if (! osc.data.target)
  696. return;
  697. osc_send_control(&osc.data, param.data[index].rindex, value);
  698. }
  699. void uiProgramChange(const uint32_t index)
  700. {
  701. CARLA_ASSERT(index < prog.count);
  702. if (index >= prog.count)
  703. return;
  704. if (! osc.data.target)
  705. return;
  706. osc_send_program(&osc.data, index);
  707. }
  708. void uiMidiProgramChange(const uint32_t index)
  709. {
  710. CARLA_ASSERT(index < midiprog.count);
  711. if (index >= midiprog.count)
  712. return;
  713. if (! osc.data.target)
  714. return;
  715. osc_send_midi_program(&osc.data, index);
  716. }
  717. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
  718. {
  719. CARLA_ASSERT(channel < 16);
  720. CARLA_ASSERT(note < 128);
  721. CARLA_ASSERT(velo > 0 && velo < 128);
  722. if (! osc.data.target)
  723. return;
  724. uint8_t midiData[4] = { 0 };
  725. midiData[1] = MIDI_STATUS_NOTE_ON + channel;
  726. midiData[2] = note;
  727. midiData[3] = velo;
  728. osc_send_midi(&osc.data, midiData);
  729. }
  730. void uiNoteOff(const uint8_t channel, const uint8_t note)
  731. {
  732. CARLA_ASSERT(channel < 16);
  733. CARLA_ASSERT(note < 128);
  734. if (! osc.data.target)
  735. return;
  736. uint8_t midiData[4] = { 0 };
  737. midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
  738. midiData[2] = note;
  739. osc_send_midi(&osc.data, midiData);
  740. }
  741. // -------------------------------------------------------------------
  742. // Cleanup
  743. void deleteBuffers()
  744. {
  745. carla_debug("BridgePlugin::delete_buffers() - start");
  746. if (param.count > 0)
  747. delete[] params;
  748. params = nullptr;
  749. CarlaPlugin::deleteBuffers();
  750. carla_debug("BridgePlugin::delete_buffers() - end");
  751. }
  752. #endif
  753. // -------------------------------------------------------------------
  754. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  755. {
  756. CARLA_ASSERT(kData->engine != nullptr);
  757. CARLA_ASSERT(kData->client == nullptr);
  758. CARLA_ASSERT(filename != nullptr);
  759. // ---------------------------------------------------------------
  760. // first checks
  761. if (kData->engine == nullptr)
  762. {
  763. return false;
  764. }
  765. if (kData->client != nullptr)
  766. {
  767. kData->engine->setLastError("Plugin client is already registered");
  768. return false;
  769. }
  770. if (filename == nullptr)
  771. {
  772. kData->engine->setLastError("null filename");
  773. return false;
  774. }
  775. // ---------------------------------------------------------------
  776. // set info
  777. if (name != nullptr)
  778. fName = kData->engine->getNewUniquePluginName(name);
  779. fFilename = filename;
  780. // ---------------------------------------------------------------
  781. // SHM Audio Pool
  782. {
  783. char tmpFileBase[60];
  784. std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");
  785. fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
  786. if (! carla_is_shm_valid(fShmAudioPool.shm))
  787. {
  788. //_cleanup();
  789. carla_stdout("Failed to open or create shared memory file #1");
  790. return false;
  791. }
  792. fShmAudioPool.filename = tmpFileBase;
  793. }
  794. // ---------------------------------------------------------------
  795. // SHM Control
  796. {
  797. char tmpFileBase[60];
  798. std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX");
  799. fShmControl.shm = shm_mkstemp(tmpFileBase);
  800. if (! carla_is_shm_valid(fShmControl.shm))
  801. {
  802. //_cleanup();
  803. carla_stdout("Failed to open or create shared memory file #2");
  804. return false;
  805. }
  806. fShmControl.filename = tmpFileBase;
  807. if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
  808. {
  809. //_cleanup();
  810. carla_stdout("Failed to mmap shared memory file");
  811. return false;
  812. }
  813. std::memset(fShmControl.data, 0, sizeof(BridgeShmControl));
  814. if (sem_init(&fShmControl.data->runServer, 1, 0) != 0)
  815. {
  816. //_cleanup();
  817. carla_stdout("Failed to initialize shared memory semaphore #1");
  818. return false;
  819. }
  820. if (sem_init(&fShmControl.data->runClient, 1, 0) != 0)
  821. {
  822. //_cleanup();
  823. carla_stdout("Failed to initialize shared memory semaphore #2");
  824. return false;
  825. }
  826. }
  827. // register plugin now so we can receive OSC (and wait for it)
  828. registerEnginePlugin(kData->engine, fId, this);
  829. kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType));
  830. kData->osc.thread.start();
  831. for (int i=0; i < 200; i++)
  832. {
  833. if (fInitiated || ! kData->osc.thread.isRunning())
  834. break;
  835. carla_msleep(50);
  836. }
  837. if (! fInitiated)
  838. {
  839. // unregister so it gets handled properly
  840. registerEnginePlugin(kData->engine, fId, nullptr);
  841. kData->osc.thread.terminate();
  842. kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  843. return false;
  844. }
  845. else if (fInitError)
  846. {
  847. // unregister so it gets handled properly
  848. registerEnginePlugin(kData->engine, fId, nullptr);
  849. kData->osc.thread.stop();
  850. // last error was set before
  851. return false;
  852. }
  853. return true;
  854. }
  855. private:
  856. const BinaryType fBinaryType;
  857. const PluginType fPluginType;
  858. bool fInitiated;
  859. bool fInitError;
  860. bool fSaved;
  861. struct BridgeAudioPool {
  862. CarlaString filename;
  863. float* data;
  864. size_t size;
  865. shm_t shm;
  866. BridgeAudioPool()
  867. : data(nullptr),
  868. size(0)
  869. {
  870. carla_shm_init(shm);
  871. }
  872. } fShmAudioPool;
  873. struct BridgeControl {
  874. CarlaString filename;
  875. BridgeShmControl* data;
  876. shm_t shm;
  877. BridgeControl()
  878. : data(nullptr)
  879. {
  880. carla_shm_init(shm);
  881. }
  882. } fShmControl;
  883. struct Info {
  884. uint32_t aIns, aOuts;
  885. uint32_t mIns, mOuts;
  886. PluginCategory category;
  887. long uniqueId;
  888. CarlaString name;
  889. CarlaString label;
  890. CarlaString maker;
  891. CarlaString copyright;
  892. //QByteArray chunk;
  893. Info()
  894. : aIns(0),
  895. aOuts(0),
  896. mIns(0),
  897. mOuts(0),
  898. category(PLUGIN_CATEGORY_NONE),
  899. uniqueId(0) {}
  900. } fInfo;
  901. BridgeParamInfo* fParams;
  902. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
  903. };
  904. CARLA_BACKEND_END_NAMESPACE
  905. #endif // ! BUILD_BRIDGE
  906. CARLA_BACKEND_START_NAMESPACE
  907. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const extra)
  908. {
  909. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s)", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype));
  910. #if 1//ndef BUILD_BRIDGE
  911. if (extra == nullptr)
  912. {
  913. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  914. return nullptr;
  915. }
  916. BridgePlugin* const plugin = new BridgePlugin(init.engine, init.id, btype, ptype);
  917. //if (! plugin->init(init.filename, init.name, init.label, (const char*)extra))
  918. {
  919. delete plugin;
  920. return nullptr;
  921. }
  922. plugin->reload();
  923. return plugin;
  924. #else
  925. init.engine->setLastError("Plugin bridge support not available");
  926. return nullptr;
  927. #endif
  928. }
  929. #if 1//ndef BUILD_BRIDGE
  930. // -------------------------------------------------------------------
  931. // Bridge Helper
  932. int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type,
  933. const int argc, const lo_arg* const* const argv, const char* const types)
  934. {
  935. return ((BridgePlugin*)plugin)->setOscPluginBridgeInfo(type, argc, argv, types);
  936. }
  937. #endif
  938. CARLA_BACKEND_END_NAMESPACE