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.

970 lines
32KB

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