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.

761 lines
20KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.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/QFile>
  19. #include <QtCore/QTextStream>
  20. CARLA_BACKEND_START_NAMESPACE
  21. #if 0
  22. } /* adjust editor indent */
  23. #endif
  24. struct BridgeParamInfo {
  25. double value;
  26. QString name;
  27. QString unit;
  28. };
  29. class BridgePlugin : public CarlaPlugin
  30. {
  31. public:
  32. BridgePlugin(CarlaEngine* const engine, unsigned short id, BinaryType btype, PluginType ptype) : CarlaPlugin(engine, id),
  33. m_binary(btype)
  34. {
  35. qDebug("BridgePlugin::BridgePlugin()");
  36. m_type = ptype;
  37. m_hints = PLUGIN_IS_BRIDGE;
  38. m_initiated = false;
  39. m_saved = false;
  40. info.ains = 0;
  41. info.aouts = 0;
  42. info.mins = 0;
  43. info.mouts = 0;
  44. info.category = PLUGIN_CATEGORY_NONE;
  45. info.uniqueId = 0;
  46. info.name = nullptr;
  47. info.label = nullptr;
  48. info.maker = nullptr;
  49. info.copyright = nullptr;
  50. params = nullptr;
  51. osc.thread = new CarlaPluginThread(engine, this, CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  52. }
  53. ~BridgePlugin()
  54. {
  55. qDebug("BridgePlugin::~BridgePlugin()");
  56. if (osc.data.target)
  57. {
  58. osc_send_hide(&osc.data);
  59. osc_send_quit(&osc.data);
  60. osc_clear_data(&osc.data);
  61. }
  62. if (osc.thread)
  63. {
  64. // Wait a bit first, try safe quit, then force kill
  65. if (osc.thread->isRunning() && ! osc.thread->wait(3000))
  66. {
  67. qWarning("Failed to properly stop Plugin Bridge thread");
  68. osc.thread->terminate();
  69. }
  70. delete osc.thread;
  71. }
  72. if (info.name)
  73. free((void*)info.name);
  74. if (info.label)
  75. free((void*)info.label);
  76. if (info.maker)
  77. free((void*)info.maker);
  78. if (info.copyright)
  79. free((void*)info.copyright);
  80. info.chunk.clear();
  81. }
  82. // -------------------------------------------------------------------
  83. // Information (base)
  84. PluginCategory category()
  85. {
  86. return info.category;
  87. }
  88. long uniqueId()
  89. {
  90. return info.uniqueId;
  91. }
  92. // -------------------------------------------------------------------
  93. // Information (count)
  94. uint32_t audioInCount()
  95. {
  96. return info.ains;
  97. }
  98. uint32_t audioOutCount()
  99. {
  100. return info.aouts;
  101. }
  102. uint32_t midiInCount()
  103. {
  104. return info.mins;
  105. }
  106. uint32_t midiOutCount()
  107. {
  108. return info.mouts;
  109. }
  110. // -------------------------------------------------------------------
  111. // Information (current data)
  112. int32_t chunkData(void** const dataPtr)
  113. {
  114. Q_ASSERT(dataPtr);
  115. if (! info.chunk.isEmpty())
  116. {
  117. *dataPtr = info.chunk.data();
  118. return info.chunk.size();
  119. }
  120. return 0;
  121. }
  122. // -------------------------------------------------------------------
  123. // Information (per-plugin data)
  124. double getParameterValue(const uint32_t parameterId)
  125. {
  126. Q_ASSERT(parameterId < param.count);
  127. return params[parameterId].value;
  128. }
  129. void getLabel(char* const strBuf)
  130. {
  131. if (info.label)
  132. strncpy(strBuf, info.label, STR_MAX);
  133. else
  134. CarlaPlugin::getLabel(strBuf);
  135. }
  136. void getMaker(char* const strBuf)
  137. {
  138. if (info.maker)
  139. strncpy(strBuf, info.maker, STR_MAX);
  140. else
  141. CarlaPlugin::getMaker(strBuf);
  142. }
  143. void getCopyright(char* const strBuf)
  144. {
  145. if (info.copyright)
  146. strncpy(strBuf, info.copyright, STR_MAX);
  147. else
  148. CarlaPlugin::getCopyright(strBuf);
  149. }
  150. void getRealName(char* const strBuf)
  151. {
  152. if (info.name)
  153. strncpy(strBuf, info.name, STR_MAX);
  154. else
  155. CarlaPlugin::getRealName(strBuf);
  156. }
  157. void getParameterName(uint32_t parameterId, char* const strBuf)
  158. {
  159. Q_ASSERT(parameterId < param.count);
  160. strncpy(strBuf, params[parameterId].name.toUtf8().constData(), STR_MAX);
  161. }
  162. void getParameterUnit(uint32_t parameterId, char* const strBuf)
  163. {
  164. Q_ASSERT(parameterId < param.count);
  165. strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX);
  166. }
  167. void getGuiInfo(GuiType* type, bool* resizable)
  168. {
  169. if (m_hints & PLUGIN_HAS_GUI)
  170. *type = GUI_EXTERNAL_OSC;
  171. else
  172. *type = GUI_NONE;
  173. *resizable = false;
  174. }
  175. // -------------------------------------------------------------------
  176. // Set data (internal stuff)
  177. int setOscBridgeInfo(const PluginBridgeInfoType type, const lo_arg* const* const argv)
  178. {
  179. qDebug("setOscBridgeInfo(%i, %p)", type, argv);
  180. switch (type)
  181. {
  182. // case PluginBridgeAudioCount:
  183. // {
  184. // int aIns = argv[0]->i;
  185. // int aOuts = argv[1]->i;
  186. // int aTotal = argv[2]->i;
  187. // info.ains = aIns;
  188. // info.aouts = aOuts;
  189. // break;
  190. // Q_UNUSED(aTotal);
  191. // }
  192. // case PluginBridgeMidiCount:
  193. // {
  194. // int mIns = argv[0]->i;
  195. // int mOuts = argv[1]->i;
  196. // int mTotal = argv[2]->i;
  197. // info.mins = mIns;
  198. // info.mouts = mOuts;
  199. // break;
  200. // Q_UNUSED(mTotal);
  201. // }
  202. // case PluginBridgeParameterCount:
  203. // {
  204. // int pIns = argv[0]->i;
  205. // int pOuts = argv[1]->i;
  206. // int pTotal = argv[2]->i;
  207. // // delete old data
  208. // if (param.count > 0)
  209. // {
  210. // delete[] param.data;
  211. // delete[] param.ranges;
  212. // delete[] params;
  213. // }
  214. // // create new if needed
  215. // param.count = (pTotal < (int)carlaOptions.maxParameters) ? pTotal : 0;
  216. // if (param.count > 0)
  217. // {
  218. // param.data = new ParameterData[param.count];
  219. // param.ranges = new ParameterRanges[param.count];
  220. // params = new BridgeParamInfo[param.count];
  221. // }
  222. // else
  223. // {
  224. // param.data = nullptr;
  225. // param.ranges = nullptr;
  226. // params = nullptr;
  227. // }
  228. // // initialize
  229. // for (uint32_t i=0; i < param.count; i++)
  230. // {
  231. // param.data[i].type = PARAMETER_UNKNOWN;
  232. // param.data[i].index = -1;
  233. // param.data[i].rindex = -1;
  234. // param.data[i].hints = 0;
  235. // param.data[i].midiChannel = 0;
  236. // param.data[i].midiCC = -1;
  237. // param.ranges[i].def = 0.0;
  238. // param.ranges[i].min = 0.0;
  239. // param.ranges[i].max = 1.0;
  240. // param.ranges[i].step = 0.01;
  241. // param.ranges[i].stepSmall = 0.0001;
  242. // param.ranges[i].stepLarge = 0.1;
  243. // params[i].value = 0.0;
  244. // params[i].name = QString();
  245. // params[i].unit = QString();
  246. // }
  247. // break;
  248. // Q_UNUSED(pIns);
  249. // Q_UNUSED(pOuts);
  250. // }
  251. // case PluginBridgeProgramCount:
  252. // {
  253. // int count = argv[0]->i;
  254. // // Delete old programs
  255. // if (prog.count > 0)
  256. // {
  257. // for (uint32_t i=0; i < prog.count; i++)
  258. // free((void*)prog.names[i]);
  259. // delete[] prog.names;
  260. // }
  261. // prog.count = 0;
  262. // prog.names = nullptr;
  263. // // Query new programs
  264. // prog.count = count;
  265. // if (prog.count > 0)
  266. // prog.names = new const char* [prog.count];
  267. // // Update names (NULL)
  268. // for (uint32_t i=0; i < prog.count; i++)
  269. // prog.names[i] = nullptr;
  270. // break;
  271. // }
  272. // case PluginBridgeMidiProgramCount:
  273. // {
  274. // int count = argv[0]->i;
  275. // // Delete old programs
  276. // if (midiprog.count > 0)
  277. // {
  278. // for (uint32_t i=0; i < midiprog.count; i++)
  279. // free((void*)midiprog.data[i].name);
  280. // delete[] midiprog.data;
  281. // }
  282. // midiprog.count = 0;
  283. // midiprog.data = nullptr;
  284. // // Query new programs
  285. // midiprog.count = count;
  286. // if (midiprog.count > 0)
  287. // midiprog.data = new midi_program_t [midiprog.count];
  288. // // Update data (NULL)
  289. // for (uint32_t i=0; i < midiprog.count; i++)
  290. // {
  291. // midiprog.data[i].bank = 0;
  292. // midiprog.data[i].program = 0;
  293. // midiprog.data[i].name = nullptr;
  294. // }
  295. // break;
  296. // }
  297. case PluginBridgePluginInfo:
  298. {
  299. int category = argv[0]->i;
  300. int hints = argv[1]->i;
  301. const char* name = (const char*)&argv[2]->s;
  302. const char* label = (const char*)&argv[3]->s;
  303. const char* maker = (const char*)&argv[4]->s;
  304. const char* copyright = (const char*)&argv[5]->s;
  305. long uniqueId = argv[6]->i;
  306. m_hints = hints | PLUGIN_IS_BRIDGE;
  307. info.category = (PluginCategory)category;
  308. info.uniqueId = uniqueId;
  309. info.name = strdup(name);
  310. info.label = strdup(label);
  311. info.maker = strdup(maker);
  312. info.copyright = strdup(copyright);
  313. if (! m_name)
  314. m_name = x_engine->getUniqueName(name);
  315. break;
  316. }
  317. // case PluginBridgeParameterInfo:
  318. // {
  319. // int index = argv[0]->i;
  320. // const char* name = (const char*)&argv[1]->s;
  321. // const char* unit = (const char*)&argv[2]->s;
  322. // if (index >= 0 && index < (int32_t)param.count)
  323. // {
  324. // params[index].name = QString(name);
  325. // params[index].unit = QString(unit);
  326. // }
  327. // break;
  328. // }
  329. // case PluginBridgeParameterDataInfo:
  330. // {
  331. // int index = argv[0]->i;
  332. // int type = argv[1]->i;
  333. // int rindex = argv[2]->i;
  334. // int hints = argv[3]->i;
  335. // int channel = argv[4]->i;
  336. // int cc = argv[5]->i;
  337. // if (index >= 0 && index < (int32_t)param.count)
  338. // {
  339. // param.data[index].type = (ParameterType)type;
  340. // param.data[index].index = index;
  341. // param.data[index].rindex = rindex;
  342. // param.data[index].hints = hints;
  343. // param.data[index].midiChannel = channel;
  344. // param.data[index].midiCC = cc;
  345. // }
  346. // break;
  347. // }
  348. // case PluginBridgeParameterRangesInfo:
  349. // {
  350. // int index = argv[0]->i;
  351. // float def = argv[1]->f;
  352. // float min = argv[2]->f;
  353. // float max = argv[3]->f;
  354. // float step = argv[4]->f;
  355. // float stepSmall = argv[5]->f;
  356. // float stepLarge = argv[6]->f;
  357. // if (index >= 0 && index < (int32_t)param.count)
  358. // {
  359. // param.ranges[index].def = def;
  360. // param.ranges[index].min = min;
  361. // param.ranges[index].max = max;
  362. // param.ranges[index].step = step;
  363. // param.ranges[index].stepSmall = stepSmall;
  364. // param.ranges[index].stepLarge = stepLarge;
  365. // }
  366. // break;
  367. // }
  368. // case PluginBridgeProgramInfo:
  369. // {
  370. // int index = argv[0]->i;
  371. // const char* name = (const char*)&argv[1]->s;
  372. // if (index >= 0 && index < (int32_t)prog.count)
  373. // prog.names[index] = strdup(name);
  374. // break;
  375. // }
  376. // case PluginBridgeMidiProgramInfo:
  377. // {
  378. // int index = argv[0]->i;
  379. // int bank = argv[1]->i;
  380. // int program = argv[2]->i;
  381. // const char* name = (const char*)&argv[3]->s;
  382. // if (index >= 0 && index < (int32_t)midiprog.count)
  383. // {
  384. // midiprog.data[index].bank = bank;
  385. // midiprog.data[index].program = program;
  386. // midiprog.data[index].name = strdup(name);
  387. // }
  388. // break;
  389. // }
  390. // case PluginBridgeCustomData:
  391. // {
  392. // const char* stype = (const char*)&argv[0]->s;
  393. // const char* key = (const char*)&argv[1]->s;
  394. // const char* value = (const char*)&argv[2]->s;
  395. // setCustomData(getCustomDataStringType(stype), key, value, false);
  396. // break;
  397. // }
  398. // case PluginBridgeChunkData:
  399. // {
  400. // const char* const filePath = (const char*)&argv[0]->s;
  401. // QFile file(filePath);
  402. // if (file.open(QIODevice::ReadOnly))
  403. // {
  404. // info.chunk = file.readAll();
  405. // file.remove();
  406. // }
  407. // break;
  408. // }
  409. case PluginBridgeUpdateNow:
  410. m_initiated = true;
  411. break;
  412. case PluginBridgeSaved:
  413. m_saved = true;
  414. break;
  415. }
  416. return 0;
  417. }
  418. // -------------------------------------------------------------------
  419. // Set data (plugin-specific stuff)
  420. void setParameterValue(uint32_t parameterId, double value, bool sendGui, bool sendOsc, bool sendCallback)
  421. {
  422. Q_ASSERT(parameterId < param.count);
  423. params[parameterId].value = fixParameterValue(value, param.ranges[parameterId]);
  424. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  425. }
  426. void setCustomData(CustomDataType type, const char* const key, const char* const value, bool sendGui)
  427. {
  428. Q_ASSERT(key);
  429. Q_ASSERT(value);
  430. if (sendGui)
  431. {
  432. QString cData;
  433. cData += getCustomDataTypeString(type);
  434. cData += "·";
  435. cData += key;
  436. cData += "·";
  437. cData += value;
  438. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  439. }
  440. CarlaPlugin::setCustomData(type, key, value, sendGui);
  441. }
  442. void setChunkData(const char* const stringData)
  443. {
  444. Q_ASSERT(m_hints & PLUGIN_USES_CHUNKS);
  445. Q_ASSERT(stringData);
  446. QString filePath;
  447. filePath += "/tmp/.CarlaChunk_";
  448. filePath += m_name;
  449. QFile file(filePath);
  450. if (file.open(QIODevice::WriteOnly | QIODevice::Text))
  451. {
  452. QTextStream out(&file);
  453. out << stringData;
  454. file.close();
  455. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
  456. }
  457. }
  458. // -------------------------------------------------------------------
  459. // Set gui stuff
  460. void showGui(const bool yesNo)
  461. {
  462. if (yesNo)
  463. osc_send_show(&osc.data);
  464. else
  465. osc_send_hide(&osc.data);
  466. }
  467. // -------------------------------------------------------------------
  468. // Plugin state
  469. void prepareForSave()
  470. {
  471. m_saved = false;
  472. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SAVE_NOW, "");
  473. for (int i=0; i < 100; i++)
  474. {
  475. if (m_saved)
  476. break;
  477. carla_msleep(100);
  478. }
  479. if (! m_saved)
  480. qWarning("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  481. else
  482. qDebug("BridgePlugin::prepareForSave() - success!");
  483. }
  484. // -------------------------------------------------------------------
  485. // Post-poned events
  486. void uiParameterChange(const uint32_t index, const double value)
  487. {
  488. Q_ASSERT(index < param.count);
  489. osc_send_control(&osc.data, param.data[index].rindex, value);
  490. }
  491. void uiProgramChange(const uint32_t index)
  492. {
  493. Q_ASSERT(index < prog.count);
  494. osc_send_program(&osc.data, index);
  495. }
  496. void uiMidiProgramChange(const uint32_t index)
  497. {
  498. Q_ASSERT(index < midiprog.count);
  499. osc_send_midi_program(&osc.data, index);
  500. }
  501. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
  502. {
  503. Q_ASSERT(channel < 16);
  504. Q_ASSERT(note < 128);
  505. Q_ASSERT(velo > 0 && velo < 128);
  506. // TODO
  507. Q_UNUSED(channel);
  508. Q_UNUSED(note);
  509. Q_UNUSED(velo);
  510. }
  511. void uiNoteOff(const uint8_t channel, const uint8_t note)
  512. {
  513. Q_ASSERT(channel < 16);
  514. Q_ASSERT(note < 128);
  515. // TODO
  516. Q_UNUSED(channel);
  517. Q_UNUSED(note);
  518. }
  519. // -------------------------------------------------------------------
  520. // Cleanup
  521. void deleteBuffers()
  522. {
  523. qDebug("BridgePlugin::delete_buffers() - start");
  524. if (param.count > 0)
  525. delete[] params;
  526. params = nullptr;
  527. qDebug("BridgePlugin::delete_buffers() - end");
  528. }
  529. // -------------------------------------------------------------------
  530. bool init(const char* const filename, const char* const name, const char* const label)
  531. {
  532. const char* const bridgeBinary = getBinaryBidgePath(m_binary);
  533. if (! bridgeBinary)
  534. {
  535. setLastError("Bridge not possible, bridge-binary not found");
  536. return false;
  537. }
  538. m_filename = strdup(filename);
  539. if (name)
  540. m_name = x_engine->getUniqueName(name);
  541. // register plugin now so we can receive OSC (and wait for it)
  542. x_engine->__bridgePluginRegister(m_id, this);
  543. osc.thread->setOscData(bridgeBinary, label, getPluginTypeString(m_type));
  544. osc.thread->start();
  545. for (int i=0; i < 200; i++)
  546. {
  547. if (m_initiated)
  548. break;
  549. carla_msleep(50);
  550. }
  551. if (! m_initiated)
  552. {
  553. // unregister so it gets handled properly
  554. x_engine->__bridgePluginRegister(m_id, nullptr);
  555. osc.thread->terminate();
  556. setLastError("Timeout while waiting for a response from plugin-bridge");
  557. return false;
  558. }
  559. return true;
  560. }
  561. private:
  562. const BinaryType m_binary;
  563. bool m_initiated;
  564. bool m_saved;
  565. struct {
  566. uint32_t ains, aouts;
  567. uint32_t mins, mouts;
  568. PluginCategory category;
  569. long uniqueId;
  570. const char* name;
  571. const char* label;
  572. const char* maker;
  573. const char* copyright;
  574. QByteArray chunk;
  575. } info;
  576. BridgeParamInfo* params;
  577. };
  578. CarlaPlugin* CarlaPlugin::newBridge(const initializer& init, BinaryType btype, PluginType ptype)
  579. {
  580. qDebug("CarlaPlugin::newBridge(%p, \"%s\", \"%s\", \"%s\", %s, %s)", init.engine, init.filename, init.name, init.label, BinaryType2str(btype), PluginType2str(ptype));
  581. short id = init.engine->getNewPluginId();
  582. if (id < 0 || id > MAX_PLUGINS)
  583. {
  584. setLastError("Maximum number of plugins reached");
  585. return nullptr;
  586. }
  587. BridgePlugin* const plugin = new BridgePlugin(init.engine, id, btype, ptype);
  588. if (! plugin->init(init.filename, init.name, init.label))
  589. {
  590. delete plugin;
  591. return nullptr;
  592. }
  593. //plugin->reload();
  594. plugin->registerToOsc();
  595. return plugin;
  596. }
  597. CARLA_BACKEND_END_NAMESPACE