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.

741 lines
19KB

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