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.

936 lines
31KB

  1. /*
  2. * Carla JACK API for external applications
  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. #include "libjack.hpp"
  18. #include <sys/prctl.h>
  19. #include "CarlaThread.hpp"
  20. using juce::FloatVectorOperations;
  21. using juce::Time;
  22. CARLA_BACKEND_START_NAMESPACE
  23. // --------------------------------------------------------------------------------------------------------------------
  24. class CarlaJackRealtimeThread : public CarlaThread
  25. {
  26. public:
  27. struct Callback {
  28. Callback() {}
  29. virtual ~Callback() {};
  30. virtual void runRealtimeThread() = 0;
  31. };
  32. CarlaJackRealtimeThread(Callback* const callback)
  33. : CarlaThread("CarlaJackRealtimeThread"),
  34. fCallback(callback) {}
  35. protected:
  36. void run() override
  37. {
  38. fCallback->runRealtimeThread();
  39. }
  40. private:
  41. Callback* const fCallback;
  42. };
  43. // --------------------------------------------------------------------------------------------------------------------
  44. class CarlaJackNonRealtimeThread : public CarlaThread
  45. {
  46. public:
  47. struct Callback {
  48. Callback() {}
  49. virtual ~Callback() {};
  50. virtual void runNonRealtimeThread() = 0;
  51. };
  52. CarlaJackNonRealtimeThread(Callback* const callback)
  53. : CarlaThread("CarlaJackNonRealtimeThread"),
  54. fCallback(callback) {}
  55. protected:
  56. void run() override
  57. {
  58. fCallback->runNonRealtimeThread();
  59. }
  60. private:
  61. Callback* const fCallback;
  62. };
  63. // --------------------------------------------------------------------------------------------------------------------
  64. class CarlaJackAppClient : public CarlaJackRealtimeThread::Callback,
  65. public CarlaJackNonRealtimeThread::Callback
  66. {
  67. public:
  68. JackServerState fServer;
  69. LinkedList<JackClientState*> fClients;
  70. CarlaJackAppClient()
  71. : fServer(this),
  72. fAudioPoolCopy(nullptr),
  73. fAudioTmpBuf(nullptr),
  74. fIsOffline(false),
  75. fLastPingTime(-1),
  76. fRealtimeThread(this),
  77. fNonRealtimeThread(this)
  78. {
  79. carla_debug("CarlaJackAppClient::CarlaJackAppClient()");
  80. const char* const shmIds(std::getenv("CARLA_SHM_IDS"));
  81. CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && std::strlen(shmIds) == 6*4,);
  82. const char* const libjackSetup(std::getenv("CARLA_LIBJACK_SETUP"));
  83. CARLA_SAFE_ASSERT_RETURN(libjackSetup != nullptr && std::strlen(libjackSetup) == 5,);
  84. // make sure we don't get loaded again
  85. carla_unsetenv("CARLA_SHM_IDS");
  86. // kill ourselves if main carla dies
  87. ::prctl(PR_SET_PDEATHSIG, SIGKILL);
  88. for (int i=4; --i >= 0;) {
  89. CARLA_SAFE_ASSERT_RETURN(libjackSetup[i] >= '0' && libjackSetup[i] <= '0'+64,);
  90. }
  91. CARLA_SAFE_ASSERT_RETURN(libjackSetup[4] >= '0' && libjackSetup[4] < '0'+0x4f,);
  92. std::memcpy(fBaseNameAudioPool, shmIds+6*0, 6);
  93. std::memcpy(fBaseNameRtClientControl, shmIds+6*1, 6);
  94. std::memcpy(fBaseNameNonRtClientControl, shmIds+6*2, 6);
  95. std::memcpy(fBaseNameNonRtServerControl, shmIds+6*3, 6);
  96. fBaseNameAudioPool[6] = '\0';
  97. fBaseNameRtClientControl[6] = '\0';
  98. fBaseNameNonRtClientControl[6] = '\0';
  99. fBaseNameNonRtServerControl[6] = '\0';
  100. fNumPorts.audioIns = libjackSetup[0] - '0';
  101. fNumPorts.audioOuts = libjackSetup[1] - '0';
  102. fNumPorts.midiIns = libjackSetup[2] - '0';
  103. fNumPorts.midiOuts = libjackSetup[3] - '0';
  104. fNonRealtimeThread.startThread();
  105. }
  106. ~CarlaJackAppClient() noexcept override
  107. {
  108. carla_debug("CarlaJackAppClient::~CarlaJackAppClient()");
  109. fLastPingTime = -1;
  110. fNonRealtimeThread.stopThread(5000);
  111. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  112. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  113. {
  114. JackClientState* const jclient(it.getValue(nullptr));
  115. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  116. delete jclient;
  117. }
  118. fClients.clear();
  119. }
  120. JackClientState* addClient(const char* const name)
  121. {
  122. JackClientState* const jclient(new JackClientState(fServer, name));
  123. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  124. fClients.append(jclient);
  125. return jclient;
  126. }
  127. bool removeClient(JackClientState* const jclient)
  128. {
  129. {
  130. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  131. CARLA_SAFE_ASSERT_RETURN(fClients.removeOne(jclient), false);
  132. }
  133. delete jclient;
  134. return true;
  135. }
  136. pthread_t getRealtimeThreadId() const noexcept
  137. {
  138. return fRealtimeThread.getThreadId();
  139. }
  140. // -------------------------------------------------------------------
  141. protected:
  142. void runRealtimeThread() override;
  143. void runNonRealtimeThread() override;
  144. private:
  145. bool initSharedMemmory();
  146. void clearSharedMemory() noexcept;
  147. bool handleRtData();
  148. bool handleNonRtData();
  149. BridgeAudioPool fShmAudioPool;
  150. BridgeRtClientControl fShmRtClientControl;
  151. BridgeNonRtClientControl fShmNonRtClientControl;
  152. BridgeNonRtServerControl fShmNonRtServerControl;
  153. float* fAudioPoolCopy;
  154. float* fAudioTmpBuf;
  155. char fBaseNameAudioPool[6+1];
  156. char fBaseNameRtClientControl[6+1];
  157. char fBaseNameNonRtClientControl[6+1];
  158. char fBaseNameNonRtServerControl[6+1];
  159. bool fIsOffline;
  160. int64_t fLastPingTime;
  161. struct NumPorts {
  162. uint32_t audioIns;
  163. uint32_t audioOuts;
  164. uint32_t midiIns;
  165. uint32_t midiOuts;
  166. NumPorts()
  167. : audioIns(0),
  168. audioOuts(0),
  169. midiIns(0),
  170. midiOuts(0) {}
  171. } fNumPorts;
  172. CarlaJackRealtimeThread fRealtimeThread;
  173. CarlaJackNonRealtimeThread fNonRealtimeThread;
  174. CarlaMutex fRealtimeThreadMutex;
  175. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaJackAppClient)
  176. };
  177. // --------------------------------------------------------------------------------------------------------------------
  178. bool CarlaJackAppClient::initSharedMemmory()
  179. {
  180. if (! fShmAudioPool.attachClient(fBaseNameAudioPool))
  181. {
  182. carla_stderr("Failed to attach to audio pool shared memory");
  183. return false;
  184. }
  185. if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl))
  186. {
  187. clearSharedMemory();
  188. carla_stderr("Failed to attach to rt client control shared memory");
  189. return false;
  190. }
  191. if (! fShmRtClientControl.mapData())
  192. {
  193. clearSharedMemory();
  194. carla_stderr("Failed to map rt client control shared memory");
  195. return false;
  196. }
  197. if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl))
  198. {
  199. clearSharedMemory();
  200. carla_stderr("Failed to attach to non-rt client control shared memory");
  201. return false;
  202. }
  203. if (! fShmNonRtClientControl.mapData())
  204. {
  205. clearSharedMemory();
  206. carla_stderr("Failed to map non-rt control client shared memory");
  207. return false;
  208. }
  209. if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl))
  210. {
  211. clearSharedMemory();
  212. carla_stderr("Failed to attach to non-rt server control shared memory");
  213. return false;
  214. }
  215. if (! fShmNonRtServerControl.mapData())
  216. {
  217. clearSharedMemory();
  218. carla_stderr("Failed to map non-rt control server shared memory");
  219. return false;
  220. }
  221. PluginBridgeNonRtClientOpcode opcode;
  222. opcode = fShmNonRtClientControl.readOpcode();
  223. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientNull, opcode);
  224. const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt();
  225. CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData));
  226. const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt();
  227. CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData));
  228. const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt();
  229. CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData));
  230. if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
  231. {
  232. carla_stderr2("CarlaJackAppClient: data size mismatch");
  233. return false;
  234. }
  235. opcode = fShmNonRtClientControl.readOpcode();
  236. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode);
  237. fServer.bufferSize = fShmNonRtClientControl.readUInt();
  238. opcode = fShmNonRtClientControl.readOpcode();
  239. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode);
  240. fServer.sampleRate = fShmNonRtClientControl.readDouble();
  241. if (fServer.bufferSize == 0 || carla_isZero(fServer.sampleRate))
  242. {
  243. carla_stderr2("CarlaJackAppClient: invalid empty state");
  244. return false;
  245. }
  246. fAudioTmpBuf = new float[fServer.bufferSize];
  247. FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);
  248. // tell backend we're live
  249. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  250. fLastPingTime = Time::currentTimeMillis();
  251. CARLA_SAFE_ASSERT(fLastPingTime > 0);
  252. // ready!
  253. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
  254. fShmNonRtServerControl.commitWrite();
  255. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  256. return true;
  257. }
  258. void CarlaJackAppClient::clearSharedMemory() noexcept
  259. {
  260. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  261. if (fAudioPoolCopy != nullptr)
  262. {
  263. delete[] fAudioPoolCopy;
  264. fAudioPoolCopy = nullptr;
  265. }
  266. if (fAudioTmpBuf != nullptr)
  267. {
  268. delete[] fAudioTmpBuf;
  269. fAudioTmpBuf = nullptr;
  270. }
  271. fShmAudioPool.clear();
  272. fShmRtClientControl.clear();
  273. fShmNonRtClientControl.clear();
  274. fShmNonRtServerControl.clear();
  275. }
  276. bool CarlaJackAppClient::handleRtData()
  277. {
  278. const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl);
  279. if (! helper.ok)
  280. return false;
  281. bool ret = false;
  282. for (; fShmRtClientControl.isDataAvailableForReading();)
  283. {
  284. const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
  285. //#ifdef DEBUG
  286. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent)
  287. {
  288. carla_stdout("CarlaJackAppClientRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
  289. }
  290. //#endif
  291. switch (opcode)
  292. {
  293. case kPluginBridgeRtClientNull:
  294. break;
  295. case kPluginBridgeRtClientSetAudioPool: {
  296. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  297. if (fShmAudioPool.data != nullptr)
  298. {
  299. jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data);
  300. fShmAudioPool.data = nullptr;
  301. }
  302. if (fAudioPoolCopy != nullptr)
  303. {
  304. delete[] fAudioPoolCopy;
  305. fAudioPoolCopy = nullptr;
  306. }
  307. const uint64_t poolSize(fShmRtClientControl.readULong());
  308. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  309. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  310. fAudioPoolCopy = new float[poolSize];
  311. break;
  312. }
  313. case kPluginBridgeRtClientControlEventParameter:
  314. case kPluginBridgeRtClientControlEventMidiBank:
  315. case kPluginBridgeRtClientControlEventMidiProgram:
  316. case kPluginBridgeRtClientControlEventAllSoundOff:
  317. case kPluginBridgeRtClientControlEventAllNotesOff:
  318. case kPluginBridgeRtClientMidiEvent:
  319. break;
  320. case kPluginBridgeRtClientProcess: {
  321. const CarlaMutexTryLocker cmtl(fRealtimeThreadMutex);
  322. if (cmtl.wasLocked())
  323. {
  324. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  325. // location to start of audio outputs (shm buffer)
  326. float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fNumPorts.audioIns);
  327. // silence outputs first
  328. if (fNumPorts.audioOuts > 0)
  329. FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);
  330. // see if there's any clients
  331. if (! fClients.isEmpty())
  332. {
  333. // save tranport for all clients
  334. const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  335. fServer.playing = bridgeTimeInfo.playing;
  336. fServer.position.frame = bridgeTimeInfo.frame;
  337. fServer.position.usecs = bridgeTimeInfo.usecs;
  338. if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */)
  339. {
  340. fServer.position.valid = JackPositionBBT;
  341. fServer.position.bar = bridgeTimeInfo.bar;
  342. fServer.position.beat = bridgeTimeInfo.beat;
  343. fServer.position.tick = bridgeTimeInfo.tick;
  344. fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar;
  345. fServer.position.beat_type = bridgeTimeInfo.beatType;
  346. fServer.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat;
  347. fServer.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute;
  348. fServer.position.bar_start_tick = bridgeTimeInfo.barStartTick;
  349. }
  350. else
  351. {
  352. fServer.position.valid = static_cast<jack_position_bits_t>(0);
  353. }
  354. // clear audio buffer for unused ports
  355. FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);
  356. // now go through each client
  357. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  358. {
  359. JackClientState* const jclient(it.getValue(nullptr));
  360. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  361. int numClientOutputsProcessed = 0;
  362. const CarlaMutexTryLocker cmtl2(jclient->mutex);
  363. // check if we can process
  364. if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
  365. {
  366. if (jclient->deactivated)
  367. {
  368. fShmRtClientControl.data->procFlags = 1;
  369. }
  370. }
  371. else
  372. {
  373. uint32_t i;
  374. // direct access to shm buffer, used only for inputs
  375. float* fdataReal = fShmAudioPool.data;
  376. // safe temp location for output, mixed down to shm buffer later on
  377. float* fdataCopy = fAudioPoolCopy;
  378. // set inputs
  379. i = 0;
  380. for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next())
  381. {
  382. if (JackPortState* const jport = it.getValue(nullptr))
  383. {
  384. if (i++ < fNumPorts.audioIns)
  385. {
  386. jport->buffer = fdataReal;
  387. fdataReal += fServer.bufferSize;
  388. fdataCopy += fServer.bufferSize;
  389. }
  390. else
  391. {
  392. jport->buffer = fAudioTmpBuf;
  393. }
  394. }
  395. }
  396. // FIXME one single "if"
  397. for (; i++ < fNumPorts.audioIns;)
  398. {
  399. fdataReal += fServer.bufferSize;
  400. fdataCopy += fServer.bufferSize;
  401. }
  402. // location to start of audio outputs
  403. float* const fdataCopyOuts = fdataCopy;
  404. // set ouputs
  405. i = 0;
  406. for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next())
  407. {
  408. if (JackPortState* const jport = it.getValue(nullptr))
  409. {
  410. if (i++ < fNumPorts.audioOuts)
  411. {
  412. jport->buffer = fdataCopy;
  413. fdataCopy += fServer.bufferSize;
  414. }
  415. else
  416. {
  417. jport->buffer = fAudioTmpBuf;
  418. }
  419. }
  420. }
  421. // FIXME one single "if"
  422. for (; i++ < fNumPorts.audioOuts;)
  423. {
  424. FloatVectorOperations::clear(fdataCopy, fServer.bufferSize);
  425. fdataCopy += fServer.bufferSize;
  426. }
  427. jclient->processCb(fServer.bufferSize, jclient->processCbPtr);
  428. if (fNumPorts.audioOuts > 0)
  429. {
  430. ++numClientOutputsProcessed;
  431. FloatVectorOperations::add(fdataRealOuts, fdataCopyOuts,
  432. fServer.bufferSize*fNumPorts.audioOuts);
  433. }
  434. }
  435. if (numClientOutputsProcessed > 1)
  436. {
  437. FloatVectorOperations::multiply(fdataRealOuts,
  438. 1.0f/static_cast<float>(numClientOutputsProcessed),
  439. fServer.bufferSize*fNumPorts.audioOuts);
  440. }
  441. }
  442. }
  443. carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);
  444. }
  445. else
  446. {
  447. carla_stderr2("CarlaJackAppClient: fRealtimeThreadMutex tryLock failed");
  448. }
  449. break;
  450. }
  451. case kPluginBridgeRtClientQuit:
  452. ret = true;
  453. break;
  454. }
  455. //#ifdef DEBUG
  456. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent)
  457. {
  458. carla_stdout("CarlaJackAppClientRtThread::run() - opcode %s done", PluginBridgeRtClientOpcode2str(opcode));
  459. }
  460. //#endif
  461. }
  462. return ret;
  463. }
  464. bool CarlaJackAppClient::handleNonRtData()
  465. {
  466. bool ret = false;
  467. for (; fShmNonRtClientControl.isDataAvailableForReading();)
  468. {
  469. const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode());
  470. // #ifdef DEBUG
  471. if (opcode != kPluginBridgeNonRtClientPing)
  472. {
  473. static int shownNull = 0;
  474. if (opcode == kPluginBridgeNonRtClientNull)
  475. {
  476. if (shownNull > 5)
  477. continue;
  478. ++shownNull;
  479. }
  480. carla_stdout("CarlaJackAppClient::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode));
  481. }
  482. // #endif
  483. if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0)
  484. fLastPingTime = Time::currentTimeMillis();
  485. switch (opcode)
  486. {
  487. case kPluginBridgeNonRtClientNull:
  488. break;
  489. case kPluginBridgeNonRtClientPing: {
  490. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  491. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  492. fShmNonRtServerControl.commitWrite();
  493. } break;
  494. case kPluginBridgeNonRtClientPingOnOff: {
  495. const uint32_t onOff(fShmNonRtClientControl.readBool());
  496. fLastPingTime = onOff ? Time::currentTimeMillis() : -1;
  497. } break;
  498. case kPluginBridgeNonRtClientActivate:
  499. case kPluginBridgeNonRtClientDeactivate:
  500. break;
  501. case kPluginBridgeNonRtClientSetBufferSize:
  502. if (const uint32_t newBufferSize = fShmNonRtClientControl.readUInt())
  503. {
  504. if (fServer.bufferSize != newBufferSize)
  505. {
  506. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  507. fServer.bufferSize = newBufferSize;
  508. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  509. {
  510. JackClientState* const jclient(it.getValue(nullptr));
  511. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  512. jclient->bufferSizeCb(fServer.bufferSize, jclient->bufferSizeCbPtr);
  513. }
  514. delete[] fAudioTmpBuf;
  515. fAudioTmpBuf = new float[fServer.bufferSize];
  516. FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);
  517. }
  518. }
  519. break;
  520. case kPluginBridgeNonRtClientSetSampleRate:
  521. if (const double newSampleRate = fShmNonRtClientControl.readDouble())
  522. {
  523. if (fServer.sampleRate != newSampleRate)
  524. {
  525. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  526. fServer.sampleRate = newSampleRate;
  527. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  528. {
  529. JackClientState* const jclient(it.getValue(nullptr));
  530. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  531. jclient->sampleRateCb(fServer.sampleRate, jclient->sampleRateCbPtr);
  532. }
  533. }
  534. }
  535. break;
  536. case kPluginBridgeNonRtClientSetOffline:
  537. // TODO inform changes
  538. fIsOffline = true;
  539. //offlineModeChanged(true);
  540. break;
  541. case kPluginBridgeNonRtClientSetOnline:
  542. // TODO inform changes
  543. fIsOffline = false;
  544. //offlineModeChanged(false);
  545. break;
  546. case kPluginBridgeNonRtClientSetParameterValue:
  547. case kPluginBridgeNonRtClientSetParameterMidiChannel:
  548. case kPluginBridgeNonRtClientSetParameterMidiCC:
  549. case kPluginBridgeNonRtClientSetProgram:
  550. case kPluginBridgeNonRtClientSetMidiProgram:
  551. case kPluginBridgeNonRtClientSetCustomData:
  552. case kPluginBridgeNonRtClientSetChunkDataFile:
  553. break;
  554. case kPluginBridgeNonRtClientSetOption:
  555. fShmNonRtClientControl.readUInt();
  556. fShmNonRtClientControl.readBool();
  557. break;
  558. case kPluginBridgeNonRtClientSetCtrlChannel:
  559. fShmNonRtClientControl.readShort();
  560. break;
  561. case kPluginBridgeNonRtClientPrepareForSave:
  562. {
  563. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  564. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  565. fShmNonRtServerControl.commitWrite();
  566. }
  567. break;
  568. case kPluginBridgeNonRtClientShowUI:
  569. case kPluginBridgeNonRtClientHideUI:
  570. case kPluginBridgeNonRtClientUiParameterChange:
  571. case kPluginBridgeNonRtClientUiProgramChange:
  572. case kPluginBridgeNonRtClientUiMidiProgramChange:
  573. case kPluginBridgeNonRtClientUiNoteOn:
  574. case kPluginBridgeNonRtClientUiNoteOff:
  575. break;
  576. case kPluginBridgeNonRtClientQuit:
  577. ret = true;
  578. break;
  579. }
  580. if (opcode != kPluginBridgeNonRtClientPing)
  581. {
  582. static int shownNull = 0;
  583. if (opcode == kPluginBridgeNonRtClientNull)
  584. {
  585. if (shownNull > 5)
  586. continue;
  587. ++shownNull;
  588. }
  589. carla_stdout("CarlaJackAppClient::handleNonRtData() - opcode %s handled", PluginBridgeNonRtClientOpcode2str(opcode));
  590. }
  591. }
  592. return ret;
  593. }
  594. void CarlaJackAppClient::runRealtimeThread()
  595. {
  596. carla_stderr("CarlaJackAppClient runRealtimeThread START");
  597. #ifdef __SSE2_MATH__
  598. // Set FTZ and DAZ flags
  599. _mm_setcsr(_mm_getcsr() | 0x8040);
  600. #endif
  601. bool quitReceived = false;
  602. for (; ! fRealtimeThread.shouldThreadExit();)
  603. {
  604. if (handleRtData())
  605. {
  606. quitReceived = true;
  607. break;
  608. }
  609. }
  610. fNonRealtimeThread.signalThreadShouldExit();
  611. carla_stderr("CarlaJackAppClient runRealtimeThread FINISHED");
  612. }
  613. void CarlaJackAppClient::runNonRealtimeThread()
  614. {
  615. carla_stderr("CarlaJackAppClient runNonRealtimeThread START");
  616. if (! initSharedMemmory())
  617. return;
  618. fRealtimeThread.startThread();
  619. fLastPingTime = Time::currentTimeMillis();
  620. carla_stdout("Carla Jack Client Ready!");
  621. bool quitReceived = false;
  622. for (; ! fNonRealtimeThread.shouldThreadExit();)
  623. {
  624. carla_msleep(50);
  625. if (handleNonRtData())
  626. {
  627. quitReceived = true;
  628. break;
  629. }
  630. }
  631. //callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  632. if (quitReceived)
  633. {
  634. carla_stderr("CarlaJackAppClient runNonRealtimeThread END - quit by carla");
  635. ::kill(::getpid(), SIGTERM);
  636. }
  637. else
  638. {
  639. const char* const message("Plugin bridge error, process thread has stopped");
  640. const std::size_t messageSize(std::strlen(message));
  641. bool activated;
  642. {
  643. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  644. if (fClients.isEmpty())
  645. {
  646. activated = false;
  647. }
  648. else if (JackClientState* const jclient = fClients.getLast(nullptr))
  649. {
  650. const CarlaMutexLocker cms(jclient->mutex);
  651. activated = jclient->activated;
  652. }
  653. else
  654. {
  655. activated = true;
  656. }
  657. }
  658. if (activated)
  659. {
  660. carla_stderr("CarlaJackAppClient runNonRealtimeThread END - quit error");
  661. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  662. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  663. fShmNonRtServerControl.writeUInt(messageSize);
  664. fShmNonRtServerControl.writeCustomData(message, messageSize);
  665. fShmNonRtServerControl.commitWrite();
  666. }
  667. else
  668. {
  669. carla_stderr("CarlaJackAppClient runNonRealtimeThread END - quit itself");
  670. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  671. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
  672. fShmNonRtServerControl.commitWrite();
  673. }
  674. /*
  675. if (activated)
  676. {
  677. // TODO infoShutdown
  678. if (fClient.shutdownCb != nullptr)
  679. fClient.shutdownCb(fClient.shutdownCbPtr);
  680. }
  681. */
  682. }
  683. fRealtimeThread.signalThreadShouldExit();
  684. clearSharedMemory();
  685. fRealtimeThread.stopThread(5000);
  686. carla_stderr("CarlaJackAppClient run FINISHED");
  687. }
  688. // --------------------------------------------------------------------------------------------------------------------
  689. static CarlaJackAppClient gClient;
  690. CARLA_EXPORT
  691. jack_client_t* jack_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...)
  692. {
  693. carla_stdout("%s(%s, 0x%x, %p)", __FUNCTION__, client_name, options, status);
  694. if (JackClientState* const client = gClient.addClient(client_name))
  695. return (jack_client_t*)client;
  696. if (status != nullptr)
  697. *status = JackServerError;
  698. return nullptr;
  699. }
  700. CARLA_EXPORT
  701. jack_client_t* jack_client_new(const char* client_name)
  702. {
  703. return jack_client_open(client_name, JackNullOption, nullptr);
  704. }
  705. CARLA_EXPORT
  706. int jack_client_close(jack_client_t* client)
  707. {
  708. carla_stdout("%s(%p)", __FUNCTION__, client);
  709. JackClientState* const jclient = (JackClientState*)client;
  710. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);
  711. gClient.removeClient(jclient);
  712. return 0;
  713. }
  714. CARLA_EXPORT
  715. pthread_t jack_client_thread_id(jack_client_t* client)
  716. {
  717. carla_stdout("%s(%p)", __FUNCTION__, client);
  718. JackClientState* const jclient = (JackClientState*)client;
  719. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);
  720. CarlaJackAppClient* const jackAppPtr = jclient->server.jackAppPtr;
  721. CARLA_SAFE_ASSERT_RETURN(jackAppPtr != nullptr && jackAppPtr == &gClient, 0);
  722. return jackAppPtr->getRealtimeThreadId();
  723. }
  724. CARLA_BACKEND_END_NAMESPACE
  725. // --------------------------------------------------------------------------------------------------------------------
  726. #include "jackbridge/JackBridge2.cpp"
  727. #include "CarlaBridgeUtils.cpp"
  728. // --------------------------------------------------------------------------------------------------------------------
  729. // TODO
  730. CARLA_BACKEND_USE_NAMESPACE
  731. CARLA_EXPORT
  732. int jack_client_real_time_priority(jack_client_t* client)
  733. {
  734. carla_stdout("%s(%p)", __FUNCTION__, client);
  735. return -1;
  736. }
  737. typedef void (*JackSessionCallback)(jack_session_event_t*, void*);
  738. CARLA_EXPORT
  739. int jack_set_session_callback(jack_client_t* client, JackSessionCallback callback, void* arg)
  740. {
  741. carla_stdout("%s(%p, %p, %p)", __FUNCTION__, client, callback, arg);
  742. return 0;
  743. }
  744. // --------------------------------------------------------------------------------------------------------------------