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.

1025 lines
29KB

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