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.

1522 lines
44KB

  1. /*
  2. * Carla Bridge Plugin
  3. * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or 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 GPL.txt file
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #ifndef BUILD_BRIDGE
  19. #include "CarlaBridgeUtils.hpp"
  20. #include "CarlaShmUtils.hpp"
  21. #include <cerrno>
  22. #include <ctime>
  23. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  24. # include <sys/time.h>
  25. #endif
  26. #include <QtCore/QDir>
  27. #include <QtCore/QFile>
  28. #include <QtCore/QStringList>
  29. #include <QtCore/QTextStream>
  30. #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
  31. /* check argument count */ \
  32. if (argc != argcToCompare) \
  33. { \
  34. carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \
  35. return 1; \
  36. } \
  37. if (argc > 0) \
  38. { \
  39. /* check for nullness */ \
  40. if (! (types && typesToCompare)) \
  41. { \
  42. carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \
  43. return 1; \
  44. } \
  45. /* check argument types */ \
  46. if (std::strcmp(types, typesToCompare) != 0) \
  47. { \
  48. carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \
  49. return 1; \
  50. } \
  51. }
  52. CARLA_BACKEND_START_NAMESPACE
  53. // -------------------------------------------------------------------------------------------------------------------
  54. // Engine Helpers
  55. extern void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin);
  56. // -------------------------------------------------------------------------------------------------------------------
  57. shm_t shm_mkstemp(char* const fileBase)
  58. {
  59. static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
  60. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  61. "0123456789";
  62. const int size = (fileBase != nullptr) ? std::strlen(fileBase) : 0;
  63. shm_t shm;
  64. carla_shm_init(shm);
  65. if (size < 6)
  66. {
  67. errno = EINVAL;
  68. return shm;
  69. }
  70. if (std::strcmp(fileBase + size - 6, "XXXXXX") != 0)
  71. {
  72. errno = EINVAL;
  73. return shm;
  74. }
  75. while (true)
  76. {
  77. for (int c = size - 6; c < size; c++)
  78. {
  79. // Note the -1 to avoid the trailing '\0' in charSet.
  80. fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)];
  81. }
  82. shm_t shm = carla_shm_create(fileBase);
  83. if (carla_is_shm_valid(shm) || errno != EEXIST)
  84. return shm;
  85. }
  86. }
  87. // -------------------------------------------------------------------------------------------------------------------
  88. struct BridgeParamInfo {
  89. float value;
  90. CarlaString name;
  91. CarlaString unit;
  92. BridgeParamInfo()
  93. : value(0.0f) {}
  94. };
  95. class BridgePlugin : public CarlaPlugin
  96. {
  97. public:
  98. BridgePlugin(CarlaEngine* const engine, const unsigned int id, const BinaryType btype, const PluginType ptype)
  99. : CarlaPlugin(engine, id),
  100. fBinaryType(btype),
  101. fPluginType(ptype),
  102. fInitiated(false),
  103. fInitError(false),
  104. fSaved(false),
  105. fParams(nullptr)
  106. {
  107. carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  108. kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  109. fHints |= PLUGIN_IS_BRIDGE;
  110. }
  111. ~BridgePlugin() override
  112. {
  113. carla_debug("BridgePlugin::~BridgePlugin()");
  114. kData->singleMutex.lock();
  115. kData->masterMutex.lock();
  116. if (kData->active)
  117. {
  118. deactivate();
  119. kData->active = false;
  120. }
  121. if (kData->osc.data.target != nullptr)
  122. {
  123. osc_send_hide(&kData->osc.data);
  124. osc_send_quit(&kData->osc.data);
  125. }
  126. kData->osc.data.free();
  127. // Wait a bit first, then force kill
  128. if (kData->osc.thread.isRunning() && ! kData->osc.thread.wait(kData->engine->getOptions().oscUiTimeout))
  129. {
  130. carla_stderr("Failed to properly stop Plugin Bridge thread");
  131. kData->osc.thread.terminate();
  132. }
  133. cleanup();
  134. //info.chunk.clear();
  135. }
  136. // -------------------------------------------------------------------
  137. // Information (base)
  138. BinaryType binaryType() const
  139. {
  140. return fBinaryType;
  141. }
  142. PluginType type() const override
  143. {
  144. return fPluginType;
  145. }
  146. PluginCategory category() override
  147. {
  148. return fInfo.category;
  149. }
  150. long uniqueId() const override
  151. {
  152. return fInfo.uniqueId;
  153. }
  154. // -------------------------------------------------------------------
  155. // Information (count)
  156. uint32_t midiInCount() const override
  157. {
  158. return fInfo.mIns;
  159. }
  160. uint32_t midiOutCount() const override
  161. {
  162. return fInfo.mOuts;
  163. }
  164. // -------------------------------------------------------------------
  165. // Information (current data)
  166. int32_t chunkData(void** const dataPtr) override
  167. {
  168. CARLA_ASSERT(fOptions & PLUGIN_OPTION_USE_CHUNKS);
  169. CARLA_ASSERT(dataPtr != nullptr);
  170. #if 0
  171. if (! info.chunk.isEmpty())
  172. {
  173. *dataPtr = info.chunk.data();
  174. return info.chunk.size();
  175. }
  176. #endif
  177. return 0;
  178. }
  179. // -------------------------------------------------------------------
  180. // Information (per-plugin data)
  181. unsigned int availableOptions() override
  182. {
  183. unsigned int options = 0x0;
  184. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  185. options |= PLUGIN_OPTION_USE_CHUNKS;
  186. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  187. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  188. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  189. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  190. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  191. return options;
  192. }
  193. #if 0
  194. double getParameterValue(const uint32_t parameterId) override
  195. {
  196. CARLA_ASSERT(parameterId < param.count);
  197. return params[parameterId].value;
  198. }
  199. #endif
  200. void getLabel(char* const strBuf) override
  201. {
  202. std::strncpy(strBuf, (const char*)fInfo.label, STR_MAX);
  203. }
  204. void getMaker(char* const strBuf) override
  205. {
  206. std::strncpy(strBuf, (const char*)fInfo.maker, STR_MAX);
  207. }
  208. void getCopyright(char* const strBuf) override
  209. {
  210. std::strncpy(strBuf, (const char*)fInfo.copyright, STR_MAX);
  211. }
  212. void getRealName(char* const strBuf) override
  213. {
  214. std::strncpy(strBuf, (const char*)fInfo.name, STR_MAX);
  215. }
  216. #if 0
  217. void getParameterName(const uint32_t parameterId, char* const strBuf) override
  218. {
  219. CARLA_ASSERT(parameterId < param.count);
  220. strncpy(strBuf, params[parameterId].name.toUtf8().constData(), STR_MAX);
  221. }
  222. void getParameterUnit(const uint32_t parameterId, char* const strBuf) override
  223. {
  224. CARLA_ASSERT(parameterId < param.count);
  225. strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX);
  226. }
  227. #endif
  228. // -------------------------------------------------------------------
  229. // Set data (state)
  230. void prepareForSave() override
  231. {
  232. #if 0
  233. m_saved = false;
  234. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SAVE_NOW, "");
  235. for (int i=0; i < 200; ++i)
  236. {
  237. if (m_saved)
  238. break;
  239. carla_msleep(50);
  240. }
  241. if (! m_saved)
  242. carla_stderr("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  243. else
  244. carla_debug("BridgePlugin::prepareForSave() - success!");
  245. #endif
  246. }
  247. // -------------------------------------------------------------------
  248. // Set data (internal stuff)
  249. // nothing
  250. // -------------------------------------------------------------------
  251. // Set data (plugin-specific stuff)
  252. #if 0
  253. void setParameterValue(const uint32_t parameterId, double value, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  254. {
  255. CARLA_ASSERT(parameterId < param.count);
  256. params[parameterId].value = fixParameterValue(value, param.ranges[parameterId]);
  257. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  258. }
  259. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  260. {
  261. CARLA_ASSERT(type);
  262. CARLA_ASSERT(key);
  263. CARLA_ASSERT(value);
  264. if (sendGui)
  265. {
  266. // TODO - if type is chunk|binary, store it in a file and send path instead
  267. QString cData;
  268. cData = type;
  269. cData += "·";
  270. cData += key;
  271. cData += "·";
  272. cData += value;
  273. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  274. }
  275. CarlaPlugin::setCustomData(type, key, value, sendGui);
  276. }
  277. void setChunkData(const char* const stringData) override
  278. {
  279. CARLA_ASSERT(m_hints & PLUGIN_USES_CHUNKS);
  280. CARLA_ASSERT(stringData);
  281. QString filePath;
  282. filePath = QDir::tempPath();
  283. filePath += "/.CarlaChunk_";
  284. filePath += m_name;
  285. filePath = QDir::toNativeSeparators(filePath);
  286. QFile file(filePath);
  287. if (file.open(QIODevice::WriteOnly | QIODevice::Text))
  288. {
  289. QTextStream out(&file);
  290. out << stringData;
  291. file.close();
  292. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
  293. }
  294. }
  295. #endif
  296. // -------------------------------------------------------------------
  297. // Set gui stuff
  298. void showGui(const bool yesNo) override
  299. {
  300. if (yesNo)
  301. osc_send_show(&kData->osc.data);
  302. else
  303. osc_send_hide(&kData->osc.data);
  304. }
  305. void idleGui() override
  306. {
  307. if (! kData->osc.thread.isRunning())
  308. carla_stderr2("TESTING: Bridge has closed!");
  309. CarlaPlugin::idleGui();
  310. }
  311. // -------------------------------------------------------------------
  312. // Plugin state
  313. void reload() override
  314. {
  315. carla_debug("BridgePlugin::reload() - start");
  316. CARLA_ASSERT(kData->engine != nullptr);
  317. if (kData->engine == nullptr)
  318. return;
  319. const ProcessMode processMode(kData->engine->getProccessMode());
  320. // Safely disable plugin for reload
  321. const ScopedDisabler sd(this);
  322. kData->clearBuffers();
  323. bool needsCtrlIn, needsCtrlOut;
  324. needsCtrlIn = needsCtrlOut = false;
  325. if (fInfo.aIns > 0)
  326. {
  327. kData->audioIn.createNew(fInfo.aIns);
  328. }
  329. if (fInfo.aOuts > 0)
  330. {
  331. kData->audioOut.createNew(fInfo.aOuts);
  332. needsCtrlIn = true;
  333. }
  334. if (fInfo.mIns > 0)
  335. needsCtrlIn = true;
  336. if (fInfo.mOuts > 0)
  337. needsCtrlOut = true;
  338. const uint portNameSize(kData->engine->maxPortNameSize());
  339. CarlaString portName;
  340. // Audio Ins
  341. for (uint32_t j=0; j < fInfo.aIns; ++j)
  342. {
  343. portName.clear();
  344. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  345. {
  346. portName = fName;
  347. portName += ":";
  348. }
  349. if (fInfo.aIns > 1)
  350. {
  351. portName += "input_";
  352. portName += CarlaString(j+1);
  353. }
  354. else
  355. portName += "input";
  356. portName.truncate(portNameSize);
  357. kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  358. kData->audioIn.ports[j].rindex = j;
  359. }
  360. // Audio Outs
  361. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  362. {
  363. portName.clear();
  364. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  365. {
  366. portName = fName;
  367. portName += ":";
  368. }
  369. if (fInfo.aOuts > 1)
  370. {
  371. portName += "output_";
  372. portName += CarlaString(j+1);
  373. }
  374. else
  375. portName += "output";
  376. portName.truncate(portNameSize);
  377. kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  378. kData->audioOut.ports[j].rindex = j;
  379. }
  380. if (needsCtrlIn)
  381. {
  382. portName.clear();
  383. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  384. {
  385. portName = fName;
  386. portName += ":";
  387. }
  388. portName += "event-in";
  389. portName.truncate(portNameSize);
  390. kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
  391. }
  392. if (needsCtrlOut)
  393. {
  394. portName.clear();
  395. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  396. {
  397. portName = fName;
  398. portName += ":";
  399. }
  400. portName += "event-out";
  401. portName.truncate(portNameSize);
  402. kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
  403. }
  404. //bufferSizeChanged(kData->engine->getBufferSize());
  405. //reloadPrograms(true);
  406. carla_debug("BridgePlugin::reload() - end");
  407. }
  408. // -------------------------------------------------------------------
  409. // Plugin processing
  410. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override
  411. {
  412. uint32_t i, k;
  413. // --------------------------------------------------------------------------------------------------------
  414. // Check if active
  415. if (! kData->active)
  416. {
  417. // disable any output sound
  418. for (i=0; i < kData->audioOut.count; ++i)
  419. carla_zeroFloat(outBuffer[i], frames);
  420. return;
  421. }
  422. for (i=0; i < fInfo.aIns; ++i)
  423. carla_copyFloat(fShmAudioPool.data + i * frames, inBuffer[i], frames);
  424. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeProcess);
  425. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  426. waitForServer();
  427. for (i=0; i < fInfo.aOuts; ++i)
  428. carla_copyFloat(outBuffer[i], fShmAudioPool.data + (i+fInfo.aIns) * frames, frames);
  429. }
  430. // -------------------------------------------------------------------
  431. // Plugin buffers
  432. // nothing
  433. // -------------------------------------------------------------------
  434. // Post-poned UI Stuff
  435. void uiParameterChange(const uint32_t index, const float value) override
  436. {
  437. CARLA_ASSERT(index < kData->param.count);
  438. if (index >= kData->param.count)
  439. return;
  440. if (kData->osc.data.target == nullptr)
  441. return;
  442. osc_send_control(&kData->osc.data, kData->param.data[index].rindex, value);
  443. }
  444. void uiProgramChange(const uint32_t index) override
  445. {
  446. CARLA_ASSERT(index < kData->prog.count);
  447. if (index >= kData->prog.count)
  448. return;
  449. if (kData->osc.data.target == nullptr)
  450. return;
  451. osc_send_program(&kData->osc.data, index);
  452. }
  453. void uiMidiProgramChange(const uint32_t index) override
  454. {
  455. CARLA_ASSERT(index < kData->midiprog.count);
  456. if (index >= kData->midiprog.count)
  457. return;
  458. if (kData->osc.data.target == nullptr)
  459. return;
  460. osc_send_midi_program(&kData->osc.data, index);
  461. }
  462. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
  463. {
  464. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  465. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  466. CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);
  467. if (channel >= MAX_MIDI_CHANNELS)
  468. return;
  469. if (note >= MAX_MIDI_NOTE)
  470. return;
  471. if (velo >= MAX_MIDI_VALUE)
  472. return;
  473. if (kData->osc.data.target == nullptr)
  474. return;
  475. uint8_t midiData[4] = { 0 };
  476. midiData[1] = MIDI_STATUS_NOTE_ON + channel;
  477. midiData[2] = note;
  478. midiData[3] = velo;
  479. osc_send_midi(&kData->osc.data, midiData);
  480. }
  481. void uiNoteOff(const uint8_t channel, const uint8_t note) override
  482. {
  483. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  484. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  485. if (channel >= MAX_MIDI_CHANNELS)
  486. return;
  487. if (note >= MAX_MIDI_NOTE)
  488. return;
  489. if (kData->osc.data.target == nullptr)
  490. return;
  491. uint8_t midiData[4] = { 0 };
  492. midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
  493. midiData[2] = note;
  494. osc_send_midi(&kData->osc.data, midiData);
  495. }
  496. void bufferSizeChanged(const uint32_t newBufferSize) override
  497. {
  498. resizeAudioPool(newBufferSize);
  499. }
  500. // -------------------------------------------------------------------
  501. int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types)
  502. {
  503. carla_stdout("setOscPluginBridgeInfo(%i, %i, %p, \"%s\")", type, argc, argv, types);
  504. switch (type)
  505. {
  506. case kPluginBridgeAudioCount:
  507. {
  508. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  509. const int32_t aIns = argv[0]->i;
  510. const int32_t aOuts = argv[1]->i;
  511. const int32_t aTotal = argv[2]->i;
  512. CARLA_ASSERT(aIns >= 0);
  513. CARLA_ASSERT(aOuts >= 0);
  514. CARLA_ASSERT(aIns + aOuts == aTotal);
  515. fInfo.aIns = aIns;
  516. fInfo.aOuts = aOuts;
  517. break;
  518. // unused
  519. (void)aTotal;
  520. }
  521. case kPluginBridgeMidiCount:
  522. {
  523. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  524. const int32_t mIns = argv[0]->i;
  525. const int32_t mOuts = argv[1]->i;
  526. const int32_t mTotal = argv[2]->i;
  527. CARLA_ASSERT(mIns >= 0);
  528. CARLA_ASSERT(mOuts >= 0);
  529. CARLA_ASSERT(mIns + mOuts == mTotal);
  530. fInfo.mIns = mIns;
  531. fInfo.mOuts = mOuts;
  532. break;
  533. // unused
  534. (void)mTotal;
  535. }
  536. #if 0
  537. case PluginBridgeParameterCount:
  538. {
  539. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  540. const int32_t pIns = argv[0]->i;
  541. const int32_t pOuts = argv[1]->i;
  542. const int32_t pTotal = argv[2]->i;
  543. CARLA_ASSERT(pIns >= 0);
  544. CARLA_ASSERT(pOuts >= 0);
  545. CARLA_ASSERT(pIns + pOuts <= pTotal);
  546. // delete old data
  547. if (param.count > 0)
  548. {
  549. delete[] param.data;
  550. delete[] param.ranges;
  551. delete[] params;
  552. }
  553. // create new if needed
  554. const int32_t maxParams = x_engine->getOptions().maxParameters;
  555. param.count = (pTotal < maxParams) ? pTotal : 0;
  556. if (param.count > 0)
  557. {
  558. param.data = new ParameterData[param.count];
  559. param.ranges = new ParameterRanges[param.count];
  560. params = new BridgeParamInfo[param.count];
  561. }
  562. else
  563. {
  564. param.data = nullptr;
  565. param.ranges = nullptr;
  566. params = nullptr;
  567. }
  568. break;
  569. Q_UNUSED(pIns);
  570. Q_UNUSED(pOuts);
  571. }
  572. case PluginBridgeProgramCount:
  573. {
  574. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  575. const int32_t count = argv[0]->i;
  576. CARLA_ASSERT(count >= 0);
  577. // delete old programs
  578. if (prog.count > 0)
  579. {
  580. for (uint32_t i=0; i < prog.count; ++i)
  581. {
  582. if (prog.names[i])
  583. free((void*)prog.names[i]);
  584. }
  585. delete[] prog.names;
  586. }
  587. prog.count = count;
  588. // create new if needed
  589. if (prog.count > 0)
  590. {
  591. prog.names = new const char* [prog.count];
  592. for (uint32_t i=0; i < prog.count; ++i)
  593. prog.names[i] = nullptr;
  594. }
  595. else
  596. prog.names = nullptr;
  597. break;
  598. }
  599. case PluginBridgeMidiProgramCount:
  600. {
  601. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  602. const int32_t count = argv[0]->i;
  603. // delete old programs
  604. if (midiprog.count > 0)
  605. {
  606. for (uint32_t i=0; i < midiprog.count; ++i)
  607. {
  608. if (midiprog.data[i].name)
  609. free((void*)midiprog.data[i].name);
  610. }
  611. delete[] midiprog.data;
  612. }
  613. // create new if needed
  614. midiprog.count = count;
  615. if (midiprog.count > 0)
  616. midiprog.data = new MidiProgramData[midiprog.count];
  617. else
  618. midiprog.data = nullptr;
  619. break;
  620. }
  621. #endif
  622. case kPluginBridgePluginInfo:
  623. {
  624. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh");
  625. const int32_t category = argv[0]->i;
  626. const int32_t hints = argv[1]->i;
  627. const char* const name = (const char*)&argv[2]->s;
  628. const char* const label = (const char*)&argv[3]->s;
  629. const char* const maker = (const char*)&argv[4]->s;
  630. const char* const copyright = (const char*)&argv[5]->s;
  631. const int64_t uniqueId = argv[6]->h;
  632. CARLA_ASSERT(category >= 0);
  633. CARLA_ASSERT(hints >= 0);
  634. CARLA_ASSERT(name);
  635. CARLA_ASSERT(label);
  636. CARLA_ASSERT(maker);
  637. CARLA_ASSERT(copyright);
  638. fHints = hints | PLUGIN_IS_BRIDGE;
  639. fInfo.category = static_cast<PluginCategory>(category);
  640. fInfo.uniqueId = uniqueId;
  641. fInfo.name = name;
  642. fInfo.label = label;
  643. fInfo.maker = maker;
  644. fInfo.copyright = copyright;
  645. if (fName.isEmpty())
  646. fName = kData->engine->getUniquePluginName(name);
  647. break;
  648. }
  649. #if 0
  650. case PluginBridgeParameterInfo:
  651. {
  652. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
  653. const int32_t index = argv[0]->i;
  654. const char* const name = (const char*)&argv[1]->s;
  655. const char* const unit = (const char*)&argv[2]->s;
  656. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  657. CARLA_ASSERT(name);
  658. CARLA_ASSERT(unit);
  659. if (index >= 0 && index < (int32_t)param.count)
  660. {
  661. params[index].name = QString(name);
  662. params[index].unit = QString(unit);
  663. }
  664. break;
  665. }
  666. case PluginBridgeParameterData:
  667. {
  668. CARLA_BRIDGE_CHECK_OSC_TYPES(6, "iiiiii");
  669. const int32_t index = argv[0]->i;
  670. const int32_t type = argv[1]->i;
  671. const int32_t rindex = argv[2]->i;
  672. const int32_t hints = argv[3]->i;
  673. const int32_t channel = argv[4]->i;
  674. const int32_t cc = argv[5]->i;
  675. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  676. CARLA_ASSERT(type >= 0);
  677. CARLA_ASSERT(rindex >= 0);
  678. CARLA_ASSERT(hints >= 0);
  679. CARLA_ASSERT(channel >= 0 && channel < 16);
  680. CARLA_ASSERT(cc >= -1);
  681. if (index >= 0 && index < (int32_t)param.count)
  682. {
  683. param.data[index].type = (ParameterType)type;
  684. param.data[index].index = index;
  685. param.data[index].rindex = rindex;
  686. param.data[index].hints = hints;
  687. param.data[index].midiChannel = channel;
  688. param.data[index].midiCC = cc;
  689. }
  690. break;
  691. }
  692. case PluginBridgeParameterRanges:
  693. {
  694. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "idddddd");
  695. const int32_t index = argv[0]->i;
  696. const double def = argv[1]->d;
  697. const double min = argv[2]->d;
  698. const double max = argv[3]->d;
  699. const double step = argv[4]->d;
  700. const double stepSmall = argv[5]->d;
  701. const double stepLarge = argv[6]->d;
  702. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  703. CARLA_ASSERT(min < max);
  704. CARLA_ASSERT(def >= min);
  705. CARLA_ASSERT(def <= max);
  706. if (index >= 0 && index < (int32_t)param.count)
  707. {
  708. param.ranges[index].def = def;
  709. param.ranges[index].min = min;
  710. param.ranges[index].max = max;
  711. param.ranges[index].step = step;
  712. param.ranges[index].stepSmall = stepSmall;
  713. param.ranges[index].stepLarge = stepLarge;
  714. params[index].value = def;
  715. }
  716. break;
  717. }
  718. case PluginBridgeProgramInfo:
  719. {
  720. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "is");
  721. const int32_t index = argv[0]->i;
  722. const char* const name = (const char*)&argv[1]->s;
  723. CARLA_ASSERT(index >= 0 && index < (int32_t)prog.count);
  724. CARLA_ASSERT(name);
  725. if (index >= 0 && index < (int32_t)prog.count)
  726. {
  727. if (prog.names[index])
  728. free((void*)prog.names[index]);
  729. prog.names[index] = strdup(name);
  730. }
  731. break;
  732. }
  733. case PluginBridgeMidiProgramInfo:
  734. {
  735. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "iiis");
  736. const int32_t index = argv[0]->i;
  737. const int32_t bank = argv[1]->i;
  738. const int32_t program = argv[2]->i;
  739. const char* const name = (const char*)&argv[3]->s;
  740. CARLA_ASSERT(index >= 0 && index < (int32_t)midiprog.count);
  741. CARLA_ASSERT(bank >= 0);
  742. CARLA_ASSERT(program >= 0 && program < 128);
  743. CARLA_ASSERT(name);
  744. if (index >= 0 && index < (int32_t)midiprog.count)
  745. {
  746. if (midiprog.data[index].name)
  747. free((void*)midiprog.data[index].name);
  748. midiprog.data[index].bank = bank;
  749. midiprog.data[index].program = program;
  750. midiprog.data[index].name = strdup(name);
  751. }
  752. break;
  753. }
  754. case PluginBridgeConfigure:
  755. {
  756. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");
  757. const char* const key = (const char*)&argv[0]->s;
  758. const char* const value = (const char*)&argv[1]->s;
  759. CARLA_ASSERT(key);
  760. CARLA_ASSERT(value);
  761. if (! (key && value))
  762. {
  763. // invalid
  764. pass();
  765. }
  766. else if (std::strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
  767. {
  768. x_engine->callback(CALLBACK_SHOW_GUI, m_id, 0, 0, 0.0, nullptr);
  769. }
  770. else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
  771. {
  772. m_saved = true;
  773. }
  774. break;
  775. }
  776. case PluginBridgeSetParameterValue:
  777. {
  778. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  779. const int32_t index = argv[0]->i;
  780. const double value = argv[1]->d;
  781. CARLA_ASSERT(index != PARAMETER_NULL);
  782. setParameterValueByRIndex(index, value, false, true, true);
  783. break;
  784. }
  785. case PluginBridgeSetDefaultValue:
  786. {
  787. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  788. const int32_t index = argv[0]->i;
  789. const double value = argv[1]->d;
  790. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  791. if (index >= 0 && index < (int32_t)param.count)
  792. param.ranges[index].def = value;
  793. break;
  794. }
  795. case PluginBridgeSetProgram:
  796. {
  797. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  798. const int32_t index = argv[0]->i;
  799. CARLA_ASSERT(index < (int32_t)prog.count);
  800. setProgram(index, false, true, true, true);
  801. break;
  802. }
  803. case PluginBridgeSetMidiProgram:
  804. {
  805. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  806. const int32_t index = argv[0]->i;
  807. CARLA_ASSERT(index < (int32_t)midiprog.count);
  808. setMidiProgram(index, false, true, true, true);
  809. break;
  810. }
  811. case PluginBridgeSetCustomData:
  812. {
  813. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");
  814. const char* const type = (const char*)&argv[0]->s;
  815. const char* const key = (const char*)&argv[1]->s;
  816. const char* const value = (const char*)&argv[2]->s;
  817. CARLA_ASSERT(type);
  818. CARLA_ASSERT(key);
  819. CARLA_ASSERT(value);
  820. setCustomData(type, key, value, false);
  821. break;
  822. }
  823. case PluginBridgeSetChunkData:
  824. {
  825. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  826. const char* const chunkFileChar = (const char*)&argv[0]->s;
  827. CARLA_ASSERT(chunkFileChar);
  828. QString chunkFileStr(chunkFileChar);
  829. #ifndef Q_OS_WIN
  830. // Using Wine, fix temp dir
  831. if (m_binary == BINARY_WIN32 || m_binary == BINARY_WIN64)
  832. {
  833. // Get WINEPREFIX
  834. QString wineDir;
  835. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  836. wineDir = QString(WINEPREFIX);
  837. else
  838. wineDir = QDir::homePath() + "/.wine";
  839. QStringList chunkFileStrSplit1 = chunkFileStr.split(":/");
  840. QStringList chunkFileStrSplit2 = chunkFileStrSplit1.at(1).split("\\");
  841. QString wineDrive = chunkFileStrSplit1.at(0).toLower();
  842. QString wineTMP = chunkFileStrSplit2.at(0);
  843. QString baseName = chunkFileStrSplit2.at(1);
  844. chunkFileStr = wineDir;
  845. chunkFileStr += "/drive_";
  846. chunkFileStr += wineDrive;
  847. chunkFileStr += "/";
  848. chunkFileStr += wineTMP;
  849. chunkFileStr += "/";
  850. chunkFileStr += baseName;
  851. chunkFileStr = QDir::toNativeSeparators(chunkFileStr);
  852. }
  853. #endif
  854. QFile chunkFile(chunkFileStr);
  855. if (chunkFile.open(QIODevice::ReadOnly))
  856. {
  857. info.chunk = chunkFile.readAll();
  858. chunkFile.close();
  859. chunkFile.remove();
  860. }
  861. break;
  862. }
  863. #endif
  864. case kPluginBridgeUpdateNow:
  865. {
  866. fInitiated = true;
  867. break;
  868. }
  869. case kPluginBridgeError:
  870. {
  871. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  872. const char* const error = (const char*)&argv[0]->s;
  873. CARLA_ASSERT(error != nullptr);
  874. kData->engine->setLastError(error);
  875. fInitError = true;
  876. fInitiated = true;
  877. break;
  878. }
  879. }
  880. return 0;
  881. }
  882. // -------------------------------------------------------------------
  883. const void* getExtraStuff() override
  884. {
  885. return fBridgeBinary.isNotEmpty() ? (const char*)fBridgeBinary : nullptr;
  886. }
  887. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  888. {
  889. CARLA_ASSERT(kData->engine != nullptr);
  890. CARLA_ASSERT(kData->client == nullptr);
  891. CARLA_ASSERT(filename != nullptr);
  892. // ---------------------------------------------------------------
  893. // first checks
  894. if (kData->engine == nullptr)
  895. {
  896. return false;
  897. }
  898. if (kData->client != nullptr)
  899. {
  900. kData->engine->setLastError("Plugin client is already registered");
  901. return false;
  902. }
  903. if (filename == nullptr)
  904. {
  905. kData->engine->setLastError("null filename");
  906. return false;
  907. }
  908. // ---------------------------------------------------------------
  909. // set info
  910. if (name != nullptr)
  911. fName = kData->engine->getUniquePluginName(name);
  912. fFilename = filename;
  913. // ---------------------------------------------------------------
  914. // register client
  915. kData->client = kData->engine->addClient(this);
  916. if (kData->client == nullptr || ! kData->client->isOk())
  917. {
  918. kData->engine->setLastError("Failed to register plugin client");
  919. return false;
  920. }
  921. // ---------------------------------------------------------------
  922. // SHM Audio Pool
  923. {
  924. char tmpFileBase[60];
  925. std::srand(std::time(NULL));
  926. std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");
  927. fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
  928. if (! carla_is_shm_valid(fShmAudioPool.shm))
  929. {
  930. //_cleanup();
  931. carla_stdout("Failed to open or create shared memory file #1");
  932. return false;
  933. }
  934. fShmAudioPool.filename = tmpFileBase;
  935. }
  936. // ---------------------------------------------------------------
  937. // SHM Control
  938. {
  939. char tmpFileBase[60];
  940. std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX");
  941. fShmControl.shm = shm_mkstemp(tmpFileBase);
  942. if (! carla_is_shm_valid(fShmControl.shm))
  943. {
  944. //_cleanup();
  945. carla_stdout("Failed to open or create shared memory file #2");
  946. return false;
  947. }
  948. fShmControl.filename = tmpFileBase;
  949. if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
  950. {
  951. //_cleanup();
  952. carla_stdout("Failed to mmap shared memory file");
  953. return false;
  954. }
  955. CARLA_ASSERT(fShmControl.data != nullptr);
  956. std::memset(fShmControl.data, 0, sizeof(BridgeShmControl));
  957. std::strcpy(fShmControl.data->ringBuffer.buf, "This thing is actually working!!!!");
  958. if (sem_init(&fShmControl.data->runServer, 1, 0) != 0)
  959. {
  960. //_cleanup();
  961. carla_stdout("Failed to initialize shared memory semaphore #1");
  962. return false;
  963. }
  964. if (sem_init(&fShmControl.data->runClient, 1, 0) != 0)
  965. {
  966. //_cleanup();
  967. carla_stdout("Failed to initialize shared memory semaphore #2");
  968. return false;
  969. }
  970. }
  971. // initial values
  972. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeBufferSize);
  973. rdwr_writeInt(&fShmControl.data->ringBuffer, kData->engine->getBufferSize());
  974. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSampleRate);
  975. rdwr_writeFloat(&fShmControl.data->ringBuffer, kData->engine->getSampleRate());
  976. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  977. // register plugin now so we can receive OSC (and wait for it)
  978. fHints |= PLUGIN_IS_BRIDGE;
  979. registerEnginePlugin(kData->engine, fId, this);
  980. // init OSC
  981. {
  982. char shmIdStr[12+1] = { 0 };
  983. std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  984. std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6);
  985. kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
  986. kData->osc.thread.start();
  987. //kData->osc.thread.waitForStarted();
  988. }
  989. for (int i=0; i < 200; ++i)
  990. {
  991. if (fInitiated || ! kData->osc.thread.isRunning())
  992. break;
  993. carla_msleep(50);
  994. }
  995. if (! fInitiated)
  996. {
  997. // unregister so it gets handled properly
  998. registerEnginePlugin(kData->engine, fId, nullptr);
  999. if (kData->osc.thread.isRunning())
  1000. kData->osc.thread.terminate();
  1001. kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  1002. return false;
  1003. }
  1004. else if (fInitError)
  1005. {
  1006. // unregister so it gets handled properly
  1007. registerEnginePlugin(kData->engine, fId, nullptr);
  1008. kData->osc.thread.quit();
  1009. // last error was set before
  1010. return false;
  1011. }
  1012. fBridgeBinary = bridgeBinary;
  1013. resizeAudioPool(kData->engine->getBufferSize());
  1014. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeReadyWait);
  1015. rdwr_writeInt(&fShmControl.data->ringBuffer, fShmAudioPool.size);
  1016. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  1017. waitForServer();
  1018. return true;
  1019. }
  1020. private:
  1021. const BinaryType fBinaryType;
  1022. const PluginType fPluginType;
  1023. bool fInitiated;
  1024. bool fInitError;
  1025. bool fSaved;
  1026. CarlaString fBridgeBinary;
  1027. struct BridgeAudioPool {
  1028. CarlaString filename;
  1029. float* data;
  1030. size_t size;
  1031. shm_t shm;
  1032. BridgeAudioPool()
  1033. : data(nullptr),
  1034. size(0)
  1035. {
  1036. carla_shm_init(shm);
  1037. }
  1038. } fShmAudioPool;
  1039. struct BridgeControl {
  1040. CarlaString filename;
  1041. BridgeShmControl* data;
  1042. shm_t shm;
  1043. BridgeControl()
  1044. : data(nullptr)
  1045. {
  1046. carla_shm_init(shm);
  1047. }
  1048. } fShmControl;
  1049. struct Info {
  1050. uint32_t aIns, aOuts;
  1051. uint32_t mIns, mOuts;
  1052. PluginCategory category;
  1053. long uniqueId;
  1054. CarlaString name;
  1055. CarlaString label;
  1056. CarlaString maker;
  1057. CarlaString copyright;
  1058. //QByteArray chunk;
  1059. Info()
  1060. : aIns(0),
  1061. aOuts(0),
  1062. mIns(0),
  1063. mOuts(0),
  1064. category(PLUGIN_CATEGORY_NONE),
  1065. uniqueId(0) {}
  1066. } fInfo;
  1067. BridgeParamInfo* fParams;
  1068. void cleanup()
  1069. {
  1070. if (fShmAudioPool.filename.isNotEmpty())
  1071. fShmAudioPool.filename.clear();
  1072. if (fShmControl.filename.isNotEmpty())
  1073. fShmControl.filename.clear();
  1074. if (fShmAudioPool.data != nullptr)
  1075. {
  1076. carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
  1077. fShmAudioPool.data = nullptr;
  1078. }
  1079. fShmAudioPool.size = 0;
  1080. // and again
  1081. if (fShmControl.data != nullptr)
  1082. {
  1083. carla_shm_unmap(fShmControl.shm, fShmControl.data, sizeof(BridgeShmControl));
  1084. fShmControl.data = nullptr;
  1085. }
  1086. if (carla_is_shm_valid(fShmAudioPool.shm))
  1087. carla_shm_close(fShmAudioPool.shm);
  1088. if (carla_is_shm_valid(fShmControl.shm))
  1089. carla_shm_close(fShmControl.shm);
  1090. }
  1091. void resizeAudioPool(const uint32_t bufferSize)
  1092. {
  1093. if (fShmAudioPool.data != nullptr)
  1094. carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
  1095. fShmAudioPool.size = (fInfo.aIns+fInfo.aOuts)*bufferSize*sizeof(float);
  1096. if (fShmAudioPool.size > 0)
  1097. fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, fShmAudioPool.size);
  1098. else
  1099. fShmAudioPool.data = nullptr;
  1100. }
  1101. void waitForServer()
  1102. {
  1103. sem_post(&fShmControl.data->runServer);
  1104. #ifdef CARLA_OS_MAC
  1105. alarm(5);
  1106. if (sem_wait(&fShmControl.data->runClient) == EINTR)
  1107. {
  1108. #else
  1109. timespec timeout;
  1110. # ifdef CARLA_OS_WIN
  1111. timeval now;
  1112. gettimeofday(&now, nullptr);
  1113. ts_timeout.tv_sec = now.tv_sec;
  1114. ts_timeout.tv_nsec = now.tv_usec * 1000;
  1115. # else
  1116. clock_gettime(CLOCK_REALTIME, &timeout);
  1117. # endif
  1118. timeout.tv_sec += 5;
  1119. if (sem_timedwait(&fShmControl.data->runClient, &timeout) != 0)
  1120. {
  1121. #endif
  1122. kData->active = false; // TODO
  1123. }
  1124. }
  1125. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
  1126. };
  1127. CARLA_BACKEND_END_NAMESPACE
  1128. #endif // ! BUILD_BRIDGE
  1129. CARLA_BACKEND_START_NAMESPACE
  1130. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
  1131. {
  1132. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1133. #ifndef BUILD_BRIDGE
  1134. if (bridgeBinary == nullptr)
  1135. {
  1136. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1137. return nullptr;
  1138. }
  1139. BridgePlugin* const plugin(new BridgePlugin(init.engine, init.id, btype, ptype));
  1140. if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
  1141. {
  1142. delete plugin;
  1143. return nullptr;
  1144. }
  1145. plugin->reload();
  1146. if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK && ! CarlaPluginProtectedData::canRunInRack(plugin))
  1147. {
  1148. init.engine->setLastError("Carla's rack mode can only work with Stereo Bridged plugins, sorry!");
  1149. delete plugin;
  1150. return nullptr;
  1151. }
  1152. return plugin;
  1153. #else
  1154. init.engine->setLastError("Plugin bridge support not available");
  1155. return nullptr;
  1156. // unused
  1157. (void)bridgeBinary;
  1158. #endif
  1159. }
  1160. #ifndef BUILD_BRIDGE
  1161. // -------------------------------------------------------------------
  1162. // Bridge Helper
  1163. int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type,
  1164. const int argc, const lo_arg* const* const argv, const char* const types)
  1165. {
  1166. CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0);
  1167. return ((BridgePlugin*)plugin)->setOscPluginBridgeInfo(type, argc, argv, types);
  1168. }
  1169. BinaryType CarlaPluginGetBridgeBinaryType(CarlaPlugin* const plugin)
  1170. {
  1171. CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0);
  1172. return ((BridgePlugin*)plugin)->binaryType();
  1173. }
  1174. #endif
  1175. CARLA_BACKEND_END_NAMESPACE