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.

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