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.

1031 lines
29KB

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