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.

1445 lines
42KB

  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