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.

1703 lines
58KB

  1. /*
  2. * Carla Plugin JACK
  3. * Copyright (C) 2016-2017 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 doc/GPL.txt file.
  16. */
  17. #ifdef BUILD_BRIDGE
  18. # error This file should not be used under bridge mode
  19. #endif
  20. #include "CarlaPluginInternal.hpp"
  21. #include "CarlaEngine.hpp"
  22. #ifdef CARLA_OS_LINUX
  23. #include "CarlaBackendUtils.hpp"
  24. #include "CarlaBridgeUtils.hpp"
  25. #include "CarlaEngineUtils.hpp"
  26. #include "CarlaMathUtils.hpp"
  27. #include "CarlaShmUtils.hpp"
  28. #include "CarlaThread.hpp"
  29. #include "jackbridge/JackBridge.hpp"
  30. #include <ctime>
  31. // -------------------------------------------------------------------------------------------------------------------
  32. using juce::ChildProcess;
  33. using juce::File;
  34. using juce::ScopedPointer;
  35. using juce::String;
  36. using juce::StringArray;
  37. using juce::Time;
  38. CARLA_BACKEND_START_NAMESPACE
  39. // -------------------------------------------------------------------------------------------------------------------
  40. // Fallback data
  41. static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
  42. // -------------------------------------------------------------------------------------------------------------------
  43. class CarlaPluginJackThread : public CarlaThread
  44. {
  45. public:
  46. CarlaPluginJackThread(CarlaEngine* const engine, CarlaPlugin* const plugin) noexcept
  47. : CarlaThread("CarlaPluginJackThread"),
  48. kEngine(engine),
  49. kPlugin(plugin),
  50. fShmIds(),
  51. fProcess() {}
  52. void setData(const char* const shmIds) noexcept
  53. {
  54. CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',);
  55. CARLA_SAFE_ASSERT(! isThreadRunning());
  56. fShmIds = shmIds;
  57. }
  58. uintptr_t getProcessID() const noexcept
  59. {
  60. CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0);
  61. return (uintptr_t)fProcess->getPID();
  62. }
  63. protected:
  64. void run()
  65. {
  66. if (fProcess == nullptr)
  67. {
  68. fProcess = new ChildProcess();
  69. }
  70. else if (fProcess->isRunning())
  71. {
  72. carla_stderr("CarlaPluginJackThread::run() - already running");
  73. }
  74. String name(kPlugin->getName());
  75. String filename(kPlugin->getFilename());
  76. if (name.isEmpty())
  77. name = "(none)";
  78. CARLA_SAFE_ASSERT_RETURN(filename.isNotEmpty(),);
  79. StringArray arguments;
  80. // binary
  81. arguments.addTokens(filename, true);
  82. bool started;
  83. {
  84. char strBuf[STR_MAX+1];
  85. strBuf[STR_MAX] = '\0';
  86. const EngineOptions& options(kEngine->getOptions());
  87. const ScopedEngineEnvironmentLocker _seel(kEngine);
  88. #ifdef CARLA_OS_LINUX
  89. const char* const oldPreload(std::getenv("LD_PRELOAD"));
  90. if (oldPreload != nullptr)
  91. ::unsetenv("LD_PRELOAD");
  92. #endif
  93. std::snprintf(strBuf, STR_MAX, P_UINTPTR, options.frontendWinId);
  94. carla_setenv("CARLA_FRONTEND_WIN_ID", strBuf);
  95. carla_setenv("CARLA_SHM_IDS", fShmIds.toRawUTF8());
  96. carla_setenv("LD_LIBRARY_PATH", "/home/falktx/Personal/FOSS/GIT/falkTX/Carla/bin/jack");
  97. started = fProcess->start(arguments);
  98. #ifdef CARLA_OS_LINUX
  99. if (oldPreload != nullptr)
  100. ::setenv("LD_PRELOAD", oldPreload, 1);
  101. ::unsetenv("LD_LIBRARY_PATH");
  102. #endif
  103. }
  104. if (! started)
  105. {
  106. carla_stdout("failed!");
  107. fProcess = nullptr;
  108. return;
  109. }
  110. for (; fProcess->isRunning() && ! shouldThreadExit();)
  111. carla_msleep(50);
  112. // we only get here if bridge crashed or thread asked to exit
  113. if (fProcess->isRunning() && shouldThreadExit())
  114. {
  115. fProcess->waitForProcessToFinish(2000);
  116. if (fProcess->isRunning())
  117. {
  118. carla_stdout("CarlaPluginJackThread::run() - bridge refused to close, force kill now");
  119. fProcess->kill();
  120. }
  121. else
  122. {
  123. carla_stdout("CarlaPluginJackThread::run() - bridge auto-closed successfully");
  124. }
  125. }
  126. else
  127. {
  128. // forced quit, may have crashed
  129. if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/)
  130. {
  131. carla_stderr("CarlaPluginJackThread::run() - bridge crashed");
  132. CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n"
  133. "Saving now will lose its current settings.\n"
  134. "Please remove this plugin, and not rely on it from this point.");
  135. kEngine->callback(CarlaBackend::ENGINE_CALLBACK_ERROR, kPlugin->getId(), 0, 0, 0.0f, errorString);
  136. }
  137. else
  138. {
  139. carla_stderr("CarlaPluginJackThread::run() - bridge closed itself");
  140. }
  141. }
  142. fProcess = nullptr;
  143. }
  144. private:
  145. CarlaEngine* const kEngine;
  146. CarlaPlugin* const kPlugin;
  147. String fShmIds;
  148. ScopedPointer<ChildProcess> fProcess;
  149. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginJackThread)
  150. };
  151. // -------------------------------------------------------------------------------------------------------------------
  152. class CarlaPluginJack : public CarlaPlugin
  153. {
  154. public:
  155. CarlaPluginJack(CarlaEngine* const engine, const uint id)
  156. : CarlaPlugin(engine, id),
  157. fInitiated(false),
  158. fInitError(false),
  159. fTimedOut(false),
  160. fTimedError(false),
  161. fProcCanceled(false),
  162. fProcWaitTime(0),
  163. fLastPongTime(-1),
  164. fBridgeThread(engine, this),
  165. fShmAudioPool(),
  166. fShmRtClientControl(),
  167. fShmNonRtClientControl(),
  168. fShmNonRtServerControl(),
  169. fInfo()
  170. {
  171. carla_debug("CarlaPluginJack::CarlaPluginJack(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  172. pData->hints |= PLUGIN_IS_BRIDGE;
  173. }
  174. ~CarlaPluginJack() override
  175. {
  176. carla_debug("CarlaPluginJack::~CarlaPluginJack()");
  177. // close UI
  178. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  179. pData->transientTryCounter = 0;
  180. pData->singleMutex.lock();
  181. pData->masterMutex.lock();
  182. if (pData->client != nullptr && pData->client->isActive())
  183. pData->client->deactivate();
  184. if (pData->active)
  185. {
  186. deactivate();
  187. pData->active = false;
  188. }
  189. if (fBridgeThread.isThreadRunning())
  190. {
  191. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientQuit);
  192. fShmRtClientControl.commitWrite();
  193. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientQuit);
  194. fShmNonRtClientControl.commitWrite();
  195. if (! fTimedOut)
  196. waitForClient("stopping", 3000);
  197. }
  198. fBridgeThread.stopThread(3000);
  199. fShmNonRtServerControl.clear();
  200. fShmNonRtClientControl.clear();
  201. fShmRtClientControl.clear();
  202. fShmAudioPool.clear();
  203. clearBuffers();
  204. fInfo.chunk.clear();
  205. }
  206. // -------------------------------------------------------------------
  207. // Information (base)
  208. PluginType getType() const noexcept override
  209. {
  210. return PLUGIN_JACK;
  211. }
  212. PluginCategory getCategory() const noexcept override
  213. {
  214. return fInfo.category;
  215. }
  216. // -------------------------------------------------------------------
  217. // Information (count)
  218. uint32_t getMidiInCount() const noexcept override
  219. {
  220. return fInfo.mIns;
  221. }
  222. uint32_t getMidiOutCount() const noexcept override
  223. {
  224. return fInfo.mOuts;
  225. }
  226. // -------------------------------------------------------------------
  227. // Information (current data)
  228. // -------------------------------------------------------------------
  229. // Information (per-plugin data)
  230. uint getOptionsAvailable() const noexcept override
  231. {
  232. return fInfo.optionsAvailable;
  233. }
  234. void getLabel(char* const strBuf) const noexcept override
  235. {
  236. std::strncpy(strBuf, fInfo.label, STR_MAX);
  237. }
  238. void getMaker(char* const strBuf) const noexcept override
  239. {
  240. nullStrBuf(strBuf);
  241. }
  242. void getCopyright(char* const strBuf) const noexcept override
  243. {
  244. nullStrBuf(strBuf);
  245. }
  246. void getRealName(char* const strBuf) const noexcept override
  247. {
  248. std::strncpy(strBuf, fInfo.name, STR_MAX);
  249. }
  250. // -------------------------------------------------------------------
  251. // Set data (state)
  252. // -------------------------------------------------------------------
  253. // Set data (internal stuff)
  254. void setOption(const uint option, const bool yesNo, const bool sendCallback) override
  255. {
  256. {
  257. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  258. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetOption);
  259. fShmNonRtClientControl.writeUInt(option);
  260. fShmNonRtClientControl.writeBool(yesNo);
  261. fShmNonRtClientControl.commitWrite();
  262. }
  263. CarlaPlugin::setOption(option, yesNo, sendCallback);
  264. }
  265. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  266. {
  267. CARLA_SAFE_ASSERT_RETURN(sendOsc || sendCallback,); // never call this from RT
  268. {
  269. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  270. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetCtrlChannel);
  271. fShmNonRtClientControl.writeShort(channel);
  272. fShmNonRtClientControl.commitWrite();
  273. }
  274. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  275. }
  276. // -------------------------------------------------------------------
  277. // Set data (plugin-specific stuff)
  278. // -------------------------------------------------------------------
  279. // Set ui stuff
  280. void idle() override
  281. {
  282. if (fBridgeThread.isThreadRunning())
  283. {
  284. if (fInitiated && fTimedOut && pData->active)
  285. setActive(false, true, true);
  286. {
  287. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  288. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientPing);
  289. fShmNonRtClientControl.commitWrite();
  290. }
  291. try {
  292. handleNonRtData();
  293. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  294. }
  295. else if (fInitiated)
  296. {
  297. fTimedOut = true;
  298. fTimedError = true;
  299. fInitiated = false;
  300. carla_stderr2("Plugin bridge has been stopped or crashed");
  301. pData->engine->callback(ENGINE_CALLBACK_PLUGIN_UNAVAILABLE, pData->id, 0, 0, 0.0f,
  302. "Plugin bridge has been stopped or crashed");
  303. }
  304. CarlaPlugin::idle();
  305. }
  306. // -------------------------------------------------------------------
  307. // Plugin state
  308. void reload() override
  309. {
  310. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  311. carla_debug("CarlaPluginJack::reload() - start");
  312. const EngineProcessMode processMode(pData->engine->getProccessMode());
  313. // Safely disable plugin for reload
  314. const ScopedDisabler sd(this);
  315. // cleanup of previous data
  316. pData->audioIn.clear();
  317. pData->audioOut.clear();
  318. pData->cvIn.clear();
  319. pData->cvOut.clear();
  320. pData->event.clear();
  321. bool needsCtrlIn, needsCtrlOut;
  322. needsCtrlIn = needsCtrlOut = false;
  323. if (fInfo.aIns > 0)
  324. {
  325. pData->audioIn.createNew(fInfo.aIns);
  326. }
  327. if (fInfo.aOuts > 0)
  328. {
  329. pData->audioOut.createNew(fInfo.aOuts);
  330. needsCtrlIn = true;
  331. }
  332. if (fInfo.cvIns > 0)
  333. {
  334. pData->cvIn.createNew(fInfo.cvIns);
  335. }
  336. if (fInfo.cvOuts > 0)
  337. {
  338. pData->cvOut.createNew(fInfo.cvOuts);
  339. }
  340. if (fInfo.mIns > 0)
  341. needsCtrlIn = true;
  342. if (fInfo.mOuts > 0)
  343. needsCtrlOut = true;
  344. const uint portNameSize(pData->engine->getMaxPortNameSize());
  345. CarlaString portName;
  346. // Audio Ins
  347. for (uint32_t j=0; j < fInfo.aIns; ++j)
  348. {
  349. portName.clear();
  350. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  351. {
  352. portName = pData->name;
  353. portName += ":";
  354. }
  355. if (fInfo.aInNames != nullptr && fInfo.aInNames[j] != nullptr)
  356. {
  357. portName += fInfo.aInNames[j];
  358. }
  359. else if (fInfo.aIns > 1)
  360. {
  361. portName += "input_";
  362. portName += CarlaString(j+1);
  363. }
  364. else
  365. portName += "input";
  366. portName.truncate(portNameSize);
  367. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
  368. pData->audioIn.ports[j].rindex = j;
  369. }
  370. // Audio Outs
  371. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  372. {
  373. portName.clear();
  374. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  375. {
  376. portName = pData->name;
  377. portName += ":";
  378. }
  379. if (fInfo.aOutNames != nullptr && fInfo.aOutNames[j] != nullptr)
  380. {
  381. portName += fInfo.aOutNames[j];
  382. }
  383. else if (fInfo.aOuts > 1)
  384. {
  385. portName += "output_";
  386. portName += CarlaString(j+1);
  387. }
  388. else
  389. portName += "output";
  390. portName.truncate(portNameSize);
  391. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
  392. pData->audioOut.ports[j].rindex = j;
  393. }
  394. // TODO - MIDI
  395. // TODO - CV
  396. if (needsCtrlIn)
  397. {
  398. portName.clear();
  399. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  400. {
  401. portName = pData->name;
  402. portName += ":";
  403. }
  404. portName += "event-in";
  405. portName.truncate(portNameSize);
  406. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
  407. }
  408. if (needsCtrlOut)
  409. {
  410. portName.clear();
  411. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  412. {
  413. portName = pData->name;
  414. portName += ":";
  415. }
  416. portName += "event-out";
  417. portName.truncate(portNameSize);
  418. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
  419. }
  420. // extra plugin hints
  421. pData->extraHints = 0x0;
  422. if (fInfo.mIns > 0)
  423. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  424. if (fInfo.mOuts > 0)
  425. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  426. if (fInfo.aIns <= 2 && fInfo.aOuts <= 2 && (fInfo.aIns == fInfo.aOuts || fInfo.aIns == 0 || fInfo.aOuts == 0))
  427. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  428. bufferSizeChanged(pData->engine->getBufferSize());
  429. reloadPrograms(true);
  430. carla_debug("CarlaPluginJack::reload() - end");
  431. }
  432. // -------------------------------------------------------------------
  433. // Plugin processing
  434. void activate() noexcept override
  435. {
  436. if (! fBridgeThread.isThreadRunning())
  437. {
  438. CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),);
  439. }
  440. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  441. {
  442. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  443. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate);
  444. fShmNonRtClientControl.commitWrite();
  445. }
  446. fTimedOut = false;
  447. try {
  448. waitForClient("activate", 2000);
  449. } CARLA_SAFE_EXCEPTION("activate - waitForClient");
  450. }
  451. void deactivate() noexcept override
  452. {
  453. if (! fBridgeThread.isThreadRunning())
  454. return;
  455. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  456. {
  457. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  458. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate);
  459. fShmNonRtClientControl.commitWrite();
  460. }
  461. fTimedOut = false;
  462. try {
  463. waitForClient("deactivate", 2000);
  464. } CARLA_SAFE_EXCEPTION("deactivate - waitForClient");
  465. }
  466. void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
  467. {
  468. // --------------------------------------------------------------------------------------------------------
  469. // Check if active
  470. if (fProcCanceled || fTimedOut || fTimedError || ! pData->active)
  471. {
  472. // disable any output sound
  473. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  474. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  475. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  476. FloatVectorOperations::clear(cvOut[i], static_cast<int>(frames));
  477. return;
  478. }
  479. // --------------------------------------------------------------------------------------------------------
  480. // Check if needs reset
  481. if (pData->needsReset)
  482. {
  483. // TODO
  484. pData->needsReset = false;
  485. }
  486. // --------------------------------------------------------------------------------------------------------
  487. // Event Input
  488. if (pData->event.portIn != nullptr)
  489. {
  490. // ----------------------------------------------------------------------------------------------------
  491. // MIDI Input (External)
  492. if (pData->extNotes.mutex.tryLock())
  493. {
  494. for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next())
  495. {
  496. const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback));
  497. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  498. uint8_t data1, data2, data3;
  499. data1 = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  500. data2 = note.note;
  501. data3 = note.velo;
  502. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  503. fShmRtClientControl.writeUInt(0); // time
  504. fShmRtClientControl.writeByte(0); // port
  505. fShmRtClientControl.writeByte(3); // size
  506. fShmRtClientControl.writeByte(data1);
  507. fShmRtClientControl.writeByte(data2);
  508. fShmRtClientControl.writeByte(data3);
  509. fShmRtClientControl.commitWrite();
  510. }
  511. pData->extNotes.data.clear();
  512. pData->extNotes.mutex.unlock();
  513. } // End of MIDI Input (External)
  514. // ----------------------------------------------------------------------------------------------------
  515. // Event Input (System)
  516. bool allNotesOffSent = false;
  517. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  518. {
  519. const EngineEvent& event(pData->event.portIn->getEvent(i));
  520. // Control change
  521. switch (event.type)
  522. {
  523. case kEngineEventTypeNull:
  524. break;
  525. case kEngineEventTypeControl: {
  526. const EngineControlEvent& ctrlEvent = event.ctrl;
  527. switch (ctrlEvent.type)
  528. {
  529. case kEngineControlEventTypeNull:
  530. break;
  531. case kEngineControlEventTypeParameter:
  532. // Control backend stuff
  533. if (event.channel == pData->ctrlChannel)
  534. {
  535. float value;
  536. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  537. {
  538. value = ctrlEvent.value;
  539. setDryWet(value, false, false);
  540. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  541. }
  542. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  543. {
  544. value = ctrlEvent.value*127.0f/100.0f;
  545. setVolume(value, false, false);
  546. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  547. }
  548. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  549. {
  550. float left, right;
  551. value = ctrlEvent.value/0.5f - 1.0f;
  552. if (value < 0.0f)
  553. {
  554. left = -1.0f;
  555. right = (value*2.0f)+1.0f;
  556. }
  557. else if (value > 0.0f)
  558. {
  559. left = (value*2.0f)-1.0f;
  560. right = 1.0f;
  561. }
  562. else
  563. {
  564. left = -1.0f;
  565. right = 1.0f;
  566. }
  567. setBalanceLeft(left, false, false);
  568. setBalanceRight(right, false, false);
  569. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  570. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  571. }
  572. }
  573. break;
  574. case kEngineControlEventTypeMidiBank:
  575. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  576. {
  577. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiBank);
  578. fShmRtClientControl.writeUInt(event.time);
  579. fShmRtClientControl.writeByte(event.channel);
  580. fShmRtClientControl.writeUShort(event.ctrl.param);
  581. fShmRtClientControl.commitWrite();
  582. }
  583. break;
  584. case kEngineControlEventTypeMidiProgram:
  585. if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
  586. {
  587. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventMidiProgram);
  588. fShmRtClientControl.writeUInt(event.time);
  589. fShmRtClientControl.writeByte(event.channel);
  590. fShmRtClientControl.writeUShort(event.ctrl.param);
  591. fShmRtClientControl.commitWrite();
  592. }
  593. break;
  594. case kEngineControlEventTypeAllSoundOff:
  595. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  596. {
  597. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllSoundOff);
  598. fShmRtClientControl.writeUInt(event.time);
  599. fShmRtClientControl.writeByte(event.channel);
  600. fShmRtClientControl.commitWrite();
  601. }
  602. break;
  603. case kEngineControlEventTypeAllNotesOff:
  604. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  605. {
  606. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  607. {
  608. allNotesOffSent = true;
  609. sendMidiAllNotesOffToCallback();
  610. }
  611. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientControlEventAllNotesOff);
  612. fShmRtClientControl.writeUInt(event.time);
  613. fShmRtClientControl.writeByte(event.channel);
  614. fShmRtClientControl.commitWrite();
  615. }
  616. break;
  617. } // switch (ctrlEvent.type)
  618. break;
  619. } // case kEngineEventTypeControl
  620. case kEngineEventTypeMidi: {
  621. const EngineMidiEvent& midiEvent(event.midi);
  622. if (midiEvent.size == 0 || midiEvent.size >= MAX_MIDI_VALUE)
  623. continue;
  624. const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
  625. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
  626. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  627. continue;
  628. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  629. continue;
  630. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  631. continue;
  632. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  633. continue;
  634. // Fix bad note-off
  635. if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
  636. status = MIDI_STATUS_NOTE_OFF;
  637. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientMidiEvent);
  638. fShmRtClientControl.writeUInt(event.time);
  639. fShmRtClientControl.writeByte(midiEvent.port);
  640. fShmRtClientControl.writeByte(midiEvent.size);
  641. fShmRtClientControl.writeByte(uint8_t(midiData[0] | (event.channel & MIDI_CHANNEL_BIT)));
  642. for (uint8_t j=1; j < midiEvent.size; ++j)
  643. fShmRtClientControl.writeByte(midiData[j]);
  644. fShmRtClientControl.commitWrite();
  645. if (status == MIDI_STATUS_NOTE_ON)
  646. pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiData[1], midiData[2]);
  647. else if (status == MIDI_STATUS_NOTE_OFF)
  648. pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiData[1], 0.0f);
  649. } break;
  650. }
  651. }
  652. pData->postRtEvents.trySplice();
  653. } // End of Event Input
  654. if (! processSingle(audioIn, audioOut, cvIn, cvOut, frames))
  655. return;
  656. // --------------------------------------------------------------------------------------------------------
  657. // MIDI Output
  658. if (pData->event.portOut != nullptr)
  659. {
  660. uint8_t size;
  661. uint32_t time;
  662. const uint8_t* midiData(fShmRtClientControl.data->midiOut);
  663. for (std::size_t read=0; read<kBridgeRtClientDataMidiOutSize;)
  664. {
  665. size = *midiData;
  666. if (size == 0)
  667. break;
  668. // advance 8 bits (1 byte)
  669. midiData = midiData + 1;
  670. // get time as 32bit
  671. time = *(const uint32_t*)midiData;
  672. // advance 32 bits (4 bytes)
  673. midiData = midiData + 4;
  674. // store midi data advancing as needed
  675. uint8_t data[size];
  676. for (uint8_t j=0; j<size; ++j)
  677. data[j] = *midiData++;
  678. pData->event.portOut->writeMidiEvent(time, size, data);
  679. read += 1U /* size*/ + 4U /* time */ + size;
  680. }
  681. } // End of Control and MIDI Output
  682. }
  683. bool processSingle(const float** const audioIn, float** const audioOut,
  684. const float** const cvIn, float** const cvOut, const uint32_t frames)
  685. {
  686. CARLA_SAFE_ASSERT_RETURN(! fTimedError, false);
  687. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  688. if (pData->audioIn.count > 0)
  689. {
  690. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  691. }
  692. if (pData->audioOut.count > 0)
  693. {
  694. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  695. }
  696. if (pData->cvIn.count > 0)
  697. {
  698. CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
  699. }
  700. if (pData->cvOut.count > 0)
  701. {
  702. CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
  703. }
  704. const int iframes(static_cast<int>(frames));
  705. // --------------------------------------------------------------------------------------------------------
  706. // Try lock, silence otherwise
  707. if (pData->engine->isOffline())
  708. {
  709. pData->singleMutex.lock();
  710. }
  711. else if (! pData->singleMutex.tryLock())
  712. {
  713. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  714. FloatVectorOperations::clear(audioOut[i], iframes);
  715. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  716. FloatVectorOperations::clear(cvOut[i], iframes);
  717. return false;
  718. }
  719. // --------------------------------------------------------------------------------------------------------
  720. // Reset audio buffers
  721. for (uint32_t i=0; i < fInfo.aIns; ++i)
  722. FloatVectorOperations::copy(fShmAudioPool.data + (i * frames), audioIn[i], iframes);
  723. // --------------------------------------------------------------------------------------------------------
  724. // TimeInfo
  725. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  726. BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  727. bridgeTimeInfo.playing = timeInfo.playing;
  728. bridgeTimeInfo.frame = timeInfo.frame;
  729. bridgeTimeInfo.usecs = timeInfo.usecs;
  730. bridgeTimeInfo.valid = timeInfo.valid;
  731. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  732. {
  733. bridgeTimeInfo.bar = timeInfo.bbt.bar;
  734. bridgeTimeInfo.beat = timeInfo.bbt.beat;
  735. bridgeTimeInfo.tick = timeInfo.bbt.tick;
  736. bridgeTimeInfo.beatsPerBar = timeInfo.bbt.beatsPerBar;
  737. bridgeTimeInfo.beatType = timeInfo.bbt.beatType;
  738. bridgeTimeInfo.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  739. bridgeTimeInfo.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  740. bridgeTimeInfo.barStartTick = timeInfo.bbt.barStartTick;
  741. }
  742. // --------------------------------------------------------------------------------------------------------
  743. // Run plugin
  744. {
  745. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientProcess);
  746. fShmRtClientControl.commitWrite();
  747. }
  748. waitForClient("process", fProcWaitTime);
  749. if (fTimedOut)
  750. {
  751. pData->singleMutex.unlock();
  752. return false;
  753. }
  754. if (fShmRtClientControl.data->procFlags)
  755. {
  756. carla_stdout("PROC Flags active, disabling plugin");
  757. fInitiated = false;
  758. fProcCanceled = true;
  759. }
  760. for (uint32_t i=0; i < fInfo.aOuts; ++i)
  761. FloatVectorOperations::copy(audioOut[i], fShmAudioPool.data + ((i + fInfo.aIns) * frames), iframes);
  762. // --------------------------------------------------------------------------------------------------------
  763. // Post-processing (dry/wet, volume and balance)
  764. {
  765. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f);
  766. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
  767. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
  768. const bool isMono = (pData->audioIn.count == 1);
  769. bool isPair;
  770. float bufValue, oldBufLeft[doBalance ? frames : 1];
  771. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  772. {
  773. // Dry/Wet
  774. if (doDryWet)
  775. {
  776. const uint32_t c = isMono ? 0 : i;
  777. for (uint32_t k=0; k < frames; ++k)
  778. {
  779. bufValue = audioIn[c][k];
  780. audioOut[i][k] = (audioOut[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  781. }
  782. }
  783. // Balance
  784. if (doBalance)
  785. {
  786. isPair = (i % 2 == 0);
  787. if (isPair)
  788. {
  789. CARLA_ASSERT(i+1 < pData->audioOut.count);
  790. FloatVectorOperations::copy(oldBufLeft, audioOut[i], iframes);
  791. }
  792. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  793. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  794. for (uint32_t k=0; k < frames; ++k)
  795. {
  796. if (isPair)
  797. {
  798. // left
  799. audioOut[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  800. audioOut[i][k] += audioOut[i+1][k] * (1.0f - balRangeR);
  801. }
  802. else
  803. {
  804. // right
  805. audioOut[i][k] = audioOut[i][k] * balRangeR;
  806. audioOut[i][k] += oldBufLeft[k] * balRangeL;
  807. }
  808. }
  809. }
  810. // Volume (and buffer copy)
  811. if (doVolume)
  812. {
  813. for (uint32_t k=0; k < frames; ++k)
  814. audioOut[i][k] *= pData->postProc.volume;
  815. }
  816. }
  817. } // End of Post-processing
  818. // --------------------------------------------------------------------------------------------------------
  819. pData->singleMutex.unlock();
  820. return true;
  821. }
  822. void bufferSizeChanged(const uint32_t newBufferSize) override
  823. {
  824. resizeAudioPool(newBufferSize);
  825. {
  826. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  827. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetBufferSize);
  828. fShmNonRtClientControl.writeUInt(newBufferSize);
  829. fShmNonRtClientControl.commitWrite();
  830. }
  831. //fProcWaitTime = newBufferSize*1000/pData->engine->getSampleRate();
  832. fProcWaitTime = 1000;
  833. waitForClient("buffersize", 1000);
  834. }
  835. void sampleRateChanged(const double newSampleRate) override
  836. {
  837. {
  838. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  839. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetSampleRate);
  840. fShmNonRtClientControl.writeDouble(newSampleRate);
  841. fShmNonRtClientControl.commitWrite();
  842. }
  843. //fProcWaitTime = pData->engine->getBufferSize()*1000/newSampleRate;
  844. fProcWaitTime = 1000;
  845. waitForClient("samplerate", 1000);
  846. }
  847. void offlineModeChanged(const bool isOffline) override
  848. {
  849. {
  850. const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
  851. fShmNonRtClientControl.writeOpcode(isOffline ? kPluginBridgeNonRtClientSetOffline : kPluginBridgeNonRtClientSetOnline);
  852. fShmNonRtClientControl.commitWrite();
  853. }
  854. waitForClient("offline", 1000);
  855. }
  856. // -------------------------------------------------------------------
  857. // Post-poned UI Stuff
  858. // -------------------------------------------------------------------
  859. void handleNonRtData()
  860. {
  861. for (; fShmNonRtServerControl.isDataAvailableForReading();)
  862. {
  863. const PluginBridgeNonRtServerOpcode opcode(fShmNonRtServerControl.readOpcode());
  864. //#ifdef DEBUG
  865. if (opcode != kPluginBridgeNonRtServerPong)
  866. {
  867. carla_debug("CarlaPluginJack::handleNonRtData() - got opcode: %s", PluginBridgeNonRtServerOpcode2str(opcode));
  868. }
  869. //#endif
  870. if (opcode != kPluginBridgeNonRtServerNull && fLastPongTime > 0)
  871. fLastPongTime = Time::currentTimeMillis();
  872. switch (opcode)
  873. {
  874. case kPluginBridgeNonRtServerNull:
  875. case kPluginBridgeNonRtServerPong:
  876. break;
  877. case kPluginBridgeNonRtServerPluginInfo1:
  878. // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  879. fShmNonRtServerControl.readUInt();
  880. fShmNonRtServerControl.readUInt();
  881. fShmNonRtServerControl.readUInt();
  882. fShmNonRtServerControl.readUInt();
  883. fShmNonRtServerControl.readLong();
  884. break;
  885. case kPluginBridgeNonRtServerPluginInfo2: {
  886. // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  887. // realName
  888. const uint32_t realNameSize(fShmNonRtServerControl.readUInt());
  889. char realName[realNameSize+1];
  890. carla_zeroChars(realName, realNameSize+1);
  891. fShmNonRtServerControl.readCustomData(realName, realNameSize);
  892. // label
  893. const uint32_t labelSize(fShmNonRtServerControl.readUInt());
  894. char label[labelSize+1];
  895. carla_zeroChars(label, labelSize+1);
  896. fShmNonRtServerControl.readCustomData(label, labelSize);
  897. // maker
  898. const uint32_t makerSize(fShmNonRtServerControl.readUInt());
  899. char maker[makerSize+1];
  900. carla_zeroChars(maker, makerSize+1);
  901. fShmNonRtServerControl.readCustomData(maker, makerSize);
  902. // copyright
  903. const uint32_t copyrightSize(fShmNonRtServerControl.readUInt());
  904. char copyright[copyrightSize+1];
  905. carla_zeroChars(copyright, copyrightSize+1);
  906. fShmNonRtServerControl.readCustomData(copyright, copyrightSize);
  907. fInfo.name = realName;
  908. fInfo.label = label;
  909. if (pData->name == nullptr)
  910. pData->name = pData->engine->getUniquePluginName(realName);
  911. } break;
  912. case kPluginBridgeNonRtServerAudioCount:
  913. // uint/ins, uint/outs
  914. fInfo.aIns = fShmNonRtServerControl.readUInt();
  915. fInfo.aOuts = fShmNonRtServerControl.readUInt();
  916. CARLA_SAFE_ASSERT(fInfo.aInNames == nullptr);
  917. CARLA_SAFE_ASSERT(fInfo.aOutNames == nullptr);
  918. if (fInfo.aIns > 0)
  919. {
  920. fInfo.aInNames = new const char*[fInfo.aIns];
  921. carla_zeroPointers(fInfo.aInNames, fInfo.aIns);
  922. }
  923. if (fInfo.aOuts > 0)
  924. {
  925. fInfo.aOutNames = new const char*[fInfo.aOuts];
  926. carla_zeroPointers(fInfo.aOutNames, fInfo.aOuts);
  927. }
  928. break;
  929. case kPluginBridgeNonRtServerMidiCount:
  930. // uint/ins, uint/outs
  931. fInfo.mIns = fShmNonRtServerControl.readUInt();
  932. fInfo.mOuts = fShmNonRtServerControl.readUInt();
  933. break;
  934. case kPluginBridgeNonRtServerCvCount:
  935. // uint/ins, uint/outs
  936. fInfo.cvIns = fShmNonRtServerControl.readUInt();
  937. fInfo.cvOuts = fShmNonRtServerControl.readUInt();
  938. break;
  939. case kPluginBridgeNonRtServerParameterCount:
  940. // uint/count
  941. fShmNonRtServerControl.readUInt();
  942. break;
  943. case kPluginBridgeNonRtServerProgramCount:
  944. // uint/count
  945. fShmNonRtServerControl.readUInt();
  946. break;
  947. case kPluginBridgeNonRtServerMidiProgramCount:
  948. // uint/count
  949. fShmNonRtServerControl.readUInt();
  950. break;
  951. case kPluginBridgeNonRtServerPortName: {
  952. // byte/type, uint/index, uint/size, str[] (name)
  953. const uint8_t portType = fShmNonRtServerControl.readByte();
  954. const uint32_t index = fShmNonRtServerControl.readUInt();
  955. // name
  956. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  957. char* const name = new char[nameSize+1];
  958. carla_zeroChars(name, nameSize+1);
  959. fShmNonRtServerControl.readCustomData(name, nameSize);
  960. CARLA_SAFE_ASSERT_BREAK(portType > kPluginBridgePortNull && portType < kPluginBridgePortTypeCount);
  961. switch (portType)
  962. {
  963. case kPluginBridgePortAudioInput:
  964. CARLA_SAFE_ASSERT_BREAK(index < fInfo.aIns);
  965. fInfo.aInNames[index] = name;
  966. break;
  967. case kPluginBridgePortAudioOutput:
  968. CARLA_SAFE_ASSERT_BREAK(index < fInfo.aOuts);
  969. fInfo.aOutNames[index] = name;
  970. break;
  971. }
  972. } break;
  973. case kPluginBridgeNonRtServerParameterData1:
  974. // uint/index, int/rindex, uint/type, uint/hints, int/cc
  975. fShmNonRtServerControl.readUInt();
  976. fShmNonRtServerControl.readInt();
  977. fShmNonRtServerControl.readUInt();
  978. fShmNonRtServerControl.readUInt();
  979. fShmNonRtServerControl.readShort();
  980. break;
  981. case kPluginBridgeNonRtServerParameterData2:
  982. // uint/index, uint/size, str[] (name), uint/size, str[] (unit)
  983. fShmNonRtServerControl.readUInt();
  984. if (const uint32_t size = fShmNonRtServerControl.readUInt())
  985. {
  986. char name[size];
  987. fShmNonRtServerControl.readCustomData(name, size);
  988. }
  989. if (const uint32_t size = fShmNonRtServerControl.readUInt())
  990. {
  991. char symbol[size];
  992. fShmNonRtServerControl.readCustomData(symbol, size);
  993. }
  994. if (const uint32_t size = fShmNonRtServerControl.readUInt())
  995. {
  996. char unit[size];
  997. fShmNonRtServerControl.readCustomData(unit, size);
  998. }
  999. break;
  1000. case kPluginBridgeNonRtServerParameterRanges:
  1001. // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
  1002. fShmNonRtServerControl.readUInt();
  1003. fShmNonRtServerControl.readFloat();
  1004. fShmNonRtServerControl.readFloat();
  1005. fShmNonRtServerControl.readFloat();
  1006. fShmNonRtServerControl.readFloat();
  1007. fShmNonRtServerControl.readFloat();
  1008. fShmNonRtServerControl.readFloat();
  1009. break;
  1010. case kPluginBridgeNonRtServerParameterValue:
  1011. // uint/index, float/value
  1012. fShmNonRtServerControl.readUInt();
  1013. fShmNonRtServerControl.readFloat();
  1014. break;
  1015. case kPluginBridgeNonRtServerParameterValue2:
  1016. // uint/index, float/value
  1017. fShmNonRtServerControl.readUInt();
  1018. fShmNonRtServerControl.readFloat();
  1019. break;
  1020. case kPluginBridgeNonRtServerDefaultValue:
  1021. // uint/index, float/value
  1022. fShmNonRtServerControl.readUInt();
  1023. fShmNonRtServerControl.readFloat();
  1024. break;
  1025. case kPluginBridgeNonRtServerCurrentProgram:
  1026. // int/index
  1027. fShmNonRtServerControl.readInt();
  1028. break;
  1029. case kPluginBridgeNonRtServerCurrentMidiProgram: {
  1030. // int/index
  1031. fShmNonRtServerControl.readInt();
  1032. } break;
  1033. case kPluginBridgeNonRtServerProgramName: {
  1034. // uint/index, uint/size, str[] (name)
  1035. fShmNonRtServerControl.readUInt();
  1036. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1037. char name[nameSize];
  1038. fShmNonRtServerControl.readCustomData(name, nameSize);
  1039. } break;
  1040. case kPluginBridgeNonRtServerMidiProgramData: {
  1041. // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  1042. fShmNonRtServerControl.readUInt();
  1043. fShmNonRtServerControl.readUInt();
  1044. fShmNonRtServerControl.readUInt();
  1045. const uint32_t nameSize(fShmNonRtServerControl.readUInt());
  1046. char name[nameSize];
  1047. fShmNonRtServerControl.readCustomData(name, nameSize);
  1048. } break;
  1049. case kPluginBridgeNonRtServerSetCustomData: {
  1050. // uint/size, str[], uint/size, str[], uint/size, str[]
  1051. // type
  1052. const uint32_t typeSize(fShmNonRtServerControl.readUInt());
  1053. char type[typeSize];
  1054. fShmNonRtServerControl.readCustomData(type, typeSize);
  1055. // key
  1056. const uint32_t keySize(fShmNonRtServerControl.readUInt());
  1057. char key[keySize];
  1058. fShmNonRtServerControl.readCustomData(key, keySize);
  1059. // value
  1060. const uint32_t valueSize(fShmNonRtServerControl.readUInt());
  1061. char value[valueSize];
  1062. fShmNonRtServerControl.readCustomData(value, valueSize);
  1063. } break;
  1064. case kPluginBridgeNonRtServerSetChunkDataFile: {
  1065. // uint/size, str[] (filename)
  1066. const uint32_t chunkFilePathSize(fShmNonRtServerControl.readUInt());
  1067. char chunkFilePath[chunkFilePathSize];
  1068. fShmNonRtServerControl.readCustomData(chunkFilePath, chunkFilePathSize);
  1069. } break;
  1070. case kPluginBridgeNonRtServerSetLatency:
  1071. // uint
  1072. fShmNonRtServerControl.readUInt();
  1073. break;
  1074. case kPluginBridgeNonRtServerReady:
  1075. fInitiated = true;
  1076. break;
  1077. case kPluginBridgeNonRtServerSaved:
  1078. break;
  1079. case kPluginBridgeNonRtServerUiClosed:
  1080. carla_stdout("bridge closed cleanly?");
  1081. pData->active = false;
  1082. #ifdef HAVE_LIBLO
  1083. if (pData->engine->isOscControlRegistered())
  1084. pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, 0.0f);
  1085. #endif
  1086. pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0.0f, nullptr);
  1087. fBridgeThread.stopThread(1000);
  1088. break;
  1089. case kPluginBridgeNonRtServerError: {
  1090. // error
  1091. const uint32_t errorSize(fShmNonRtServerControl.readUInt());
  1092. char error[errorSize+1];
  1093. carla_zeroChars(error, errorSize+1);
  1094. fShmNonRtServerControl.readCustomData(error, errorSize);
  1095. if (fInitiated)
  1096. {
  1097. pData->engine->callback(ENGINE_CALLBACK_ERROR, pData->id, 0, 0, 0.0f, error);
  1098. // just in case
  1099. pData->engine->setLastError(error);
  1100. fInitError = true;
  1101. }
  1102. else
  1103. {
  1104. pData->engine->setLastError(error);
  1105. fInitError = true;
  1106. fInitiated = true;
  1107. }
  1108. } break;
  1109. }
  1110. }
  1111. }
  1112. // -------------------------------------------------------------------
  1113. uintptr_t getUiBridgeProcessId() const noexcept override
  1114. {
  1115. return fBridgeThread.getProcessID();
  1116. }
  1117. // -------------------------------------------------------------------
  1118. bool init(const char* const filename, const char* const name)
  1119. {
  1120. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  1121. // ---------------------------------------------------------------
  1122. // first checks
  1123. if (pData->client != nullptr)
  1124. {
  1125. pData->engine->setLastError("Plugin client is already registered");
  1126. return false;
  1127. }
  1128. // ---------------------------------------------------------------
  1129. // set info
  1130. if (name != nullptr && name[0] != '\0')
  1131. pData->name = pData->engine->getUniquePluginName(name);
  1132. if (filename != nullptr && filename[0] != '\0')
  1133. pData->filename = carla_strdup(filename);
  1134. else
  1135. pData->filename = carla_strdup("");
  1136. std::srand(static_cast<uint>(std::time(nullptr)));
  1137. // ---------------------------------------------------------------
  1138. // init sem/shm
  1139. if (! fShmAudioPool.initializeServer())
  1140. {
  1141. carla_stderr("Failed to initialize shared memory audio pool");
  1142. return false;
  1143. }
  1144. if (! fShmRtClientControl.initializeServer())
  1145. {
  1146. carla_stderr("Failed to initialize RT client control");
  1147. fShmAudioPool.clear();
  1148. return false;
  1149. }
  1150. if (! fShmNonRtClientControl.initializeServer())
  1151. {
  1152. carla_stderr("Failed to initialize Non-RT client control");
  1153. fShmRtClientControl.clear();
  1154. fShmAudioPool.clear();
  1155. return false;
  1156. }
  1157. if (! fShmNonRtServerControl.initializeServer())
  1158. {
  1159. carla_stderr("Failed to initialize Non-RT server control");
  1160. fShmNonRtClientControl.clear();
  1161. fShmRtClientControl.clear();
  1162. fShmAudioPool.clear();
  1163. return false;
  1164. }
  1165. // ---------------------------------------------------------------
  1166. // init bridge thread
  1167. {
  1168. char shmIdsStr[6*4+1];
  1169. carla_zeroChars(shmIdsStr, 6*4+1);
  1170. std::strncpy(shmIdsStr+6*0, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  1171. std::strncpy(shmIdsStr+6*1, &fShmRtClientControl.filename[fShmRtClientControl.filename.length()-6], 6);
  1172. std::strncpy(shmIdsStr+6*2, &fShmNonRtClientControl.filename[fShmNonRtClientControl.filename.length()-6], 6);
  1173. std::strncpy(shmIdsStr+6*3, &fShmNonRtServerControl.filename[fShmNonRtServerControl.filename.length()-6], 6);
  1174. fBridgeThread.setData(shmIdsStr);
  1175. }
  1176. if (! restartBridgeThread())
  1177. return false;
  1178. // ---------------------------------------------------------------
  1179. // register client
  1180. if (pData->name == nullptr)
  1181. pData->name = pData->engine->getUniquePluginName("unknown");
  1182. pData->client = pData->engine->addClient(this);
  1183. if (pData->client == nullptr || ! pData->client->isOk())
  1184. {
  1185. pData->engine->setLastError("Failed to register plugin client");
  1186. return false;
  1187. }
  1188. return true;
  1189. }
  1190. private:
  1191. bool fInitiated;
  1192. bool fInitError;
  1193. bool fTimedOut;
  1194. bool fTimedError;
  1195. bool fProcCanceled;
  1196. uint fProcWaitTime;
  1197. int64_t fLastPongTime;
  1198. CarlaPluginJackThread fBridgeThread;
  1199. BridgeAudioPool fShmAudioPool;
  1200. BridgeRtClientControl fShmRtClientControl;
  1201. BridgeNonRtClientControl fShmNonRtClientControl;
  1202. BridgeNonRtServerControl fShmNonRtServerControl;
  1203. struct Info {
  1204. uint32_t aIns, aOuts;
  1205. uint32_t cvIns, cvOuts;
  1206. uint32_t mIns, mOuts;
  1207. PluginCategory category;
  1208. uint optionsAvailable;
  1209. CarlaString name;
  1210. CarlaString label;
  1211. const char** aInNames;
  1212. const char** aOutNames;
  1213. std::vector<uint8_t> chunk;
  1214. Info()
  1215. : aIns(0),
  1216. aOuts(0),
  1217. cvIns(0),
  1218. cvOuts(0),
  1219. mIns(0),
  1220. mOuts(0),
  1221. category(PLUGIN_CATEGORY_NONE),
  1222. optionsAvailable(0),
  1223. name(),
  1224. label(),
  1225. aInNames(nullptr),
  1226. aOutNames(nullptr),
  1227. chunk() {}
  1228. CARLA_DECLARE_NON_COPY_STRUCT(Info)
  1229. } fInfo;
  1230. void resizeAudioPool(const uint32_t bufferSize)
  1231. {
  1232. fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);
  1233. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
  1234. fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
  1235. fShmRtClientControl.commitWrite();
  1236. waitForClient("resize-pool", 5000);
  1237. }
  1238. void waitForClient(const char* const action, const uint msecs)
  1239. {
  1240. CARLA_SAFE_ASSERT_RETURN(! fTimedOut,);
  1241. CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
  1242. if (fShmRtClientControl.waitForClient(msecs))
  1243. return;
  1244. fTimedOut = true;
  1245. carla_stderr("waitForClient(%s) timed out", action);
  1246. }
  1247. bool restartBridgeThread()
  1248. {
  1249. fInitiated = false;
  1250. fInitError = false;
  1251. fTimedError = false;
  1252. // cleanup of previous data
  1253. delete[] fInfo.aInNames;
  1254. fInfo.aInNames = nullptr;
  1255. delete[] fInfo.aOutNames;
  1256. fInfo.aOutNames = nullptr;
  1257. // reset memory
  1258. fProcCanceled = false;
  1259. fShmRtClientControl.data->procFlags = 0;
  1260. carla_zeroStruct(fShmRtClientControl.data->timeInfo);
  1261. carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);
  1262. fShmRtClientControl.clearData();
  1263. fShmNonRtClientControl.clearData();
  1264. fShmNonRtServerControl.clearData();
  1265. // initial values
  1266. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientNull);
  1267. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
  1268. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
  1269. fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));
  1270. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetBufferSize);
  1271. fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
  1272. fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetSampleRate);
  1273. fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());
  1274. fShmNonRtClientControl.commitWrite();
  1275. if (fShmAudioPool.dataSize != 0)
  1276. {
  1277. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
  1278. fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
  1279. fShmRtClientControl.commitWrite();
  1280. }
  1281. else
  1282. {
  1283. // testing dummy message
  1284. fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
  1285. fShmRtClientControl.commitWrite();
  1286. }
  1287. fBridgeThread.startThread();
  1288. fLastPongTime = Time::currentTimeMillis();
  1289. CARLA_SAFE_ASSERT(fLastPongTime > 0);
  1290. static bool sFirstInit = true;
  1291. int64_t timeoutEnd = 5000;
  1292. if (sFirstInit)
  1293. timeoutEnd *= 2;
  1294. sFirstInit = false;
  1295. const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;
  1296. for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
  1297. {
  1298. pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);
  1299. if (needsEngineIdle)
  1300. pData->engine->idle();
  1301. idle();
  1302. if (fInitiated)
  1303. break;
  1304. if (pData->engine->isAboutToClose())
  1305. break;
  1306. carla_msleep(20);
  1307. }
  1308. fLastPongTime = -1;
  1309. if (fInitError || ! fInitiated)
  1310. {
  1311. fBridgeThread.stopThread(6000);
  1312. if (! fInitError)
  1313. pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n"
  1314. "(or the plugin crashed on initialization?)");
  1315. return false;
  1316. }
  1317. return true;
  1318. }
  1319. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginJack)
  1320. };
  1321. CARLA_BACKEND_END_NAMESPACE
  1322. #endif // CARLA_OS_LINUX
  1323. // -------------------------------------------------------------------------------------------------------------------
  1324. CARLA_BACKEND_START_NAMESPACE
  1325. CarlaPlugin* CarlaPlugin::newJackApp(const Initializer& init)
  1326. {
  1327. carla_debug("CarlaPlugin::newJackApp({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label);
  1328. #ifdef CARLA_OS_LINUX
  1329. CarlaPluginJack* const plugin(new CarlaPluginJack(init.engine, init.id));
  1330. if (! plugin->init(init.filename, init.name))
  1331. {
  1332. delete plugin;
  1333. return nullptr;
  1334. }
  1335. return plugin;
  1336. #else
  1337. init.engine->setLastError("JACK Application support not available");
  1338. return nullptr;
  1339. #endif
  1340. }
  1341. CARLA_BACKEND_END_NAMESPACE
  1342. // -------------------------------------------------------------------------------------------------------------------