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.

982 lines
28KB

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