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.

1037 lines
30KB

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