Collection of tools useful for audio production
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.

1046 lines
30KB

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