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.

1435 lines
51KB

  1. /*
  2. * Carla JACK API for external applications
  3. * Copyright (C) 2016-2019 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 "CarlaThread.hpp"
  19. #include "CarlaJuceUtils.hpp"
  20. #include <signal.h>
  21. #include <sys/prctl.h>
  22. #include <sys/time.h>
  23. // ---------------------------------------------------------------------------------------------------------------------
  24. CARLA_EXPORT
  25. int jack_carla_interposed_action(uint, uint, void*)
  26. {
  27. static bool printWarning = true;
  28. if (printWarning)
  29. {
  30. printWarning = false;
  31. carla_stderr2("Non-exported jack_carla_interposed_action called, this should not happen!!");
  32. carla_stderr("Printing some info:");
  33. carla_stderr("\tLD_LIBRARY_PATH: '%s'", std::getenv("LD_LIBRARY_PATH"));
  34. carla_stderr("\tLD_PRELOAD: '%s'", std::getenv("LD_PRELOAD"));
  35. std::fflush(stderr);
  36. }
  37. // ::kill(::getpid(), SIGKILL);
  38. return 1337;
  39. }
  40. // ---------------------------------------------------------------------------------------------------------------------
  41. CARLA_BACKEND_START_NAMESPACE
  42. // ---------------------------------------------------------------------------------------------------------------------
  43. static int64_t getCurrentTimeMilliseconds() noexcept
  44. {
  45. struct timeval tv;
  46. gettimeofday (&tv, nullptr);
  47. return ((int64_t) tv.tv_sec) * 1000 + tv.tv_usec / 1000;
  48. }
  49. static int carla_interposed_callback(int, void*);
  50. // ---------------------------------------------------------------------------------------------------------------------
  51. class CarlaJackRealtimeThread : public CarlaThread
  52. {
  53. public:
  54. struct Callback {
  55. Callback() {}
  56. virtual ~Callback() {};
  57. virtual void runRealtimeThread() = 0;
  58. };
  59. CarlaJackRealtimeThread(Callback* const callback)
  60. : CarlaThread("CarlaJackRealtimeThread"),
  61. fCallback(callback) {}
  62. protected:
  63. void run() override
  64. {
  65. fCallback->runRealtimeThread();
  66. }
  67. private:
  68. Callback* const fCallback;
  69. CARLA_DECLARE_NON_COPY_CLASS(CarlaJackRealtimeThread)
  70. };
  71. // --------------------------------------------------------------------------------------------------------------------
  72. class CarlaJackNonRealtimeThread : public CarlaThread
  73. {
  74. public:
  75. struct Callback {
  76. Callback() {}
  77. virtual ~Callback() {};
  78. virtual void runNonRealtimeThread() = 0;
  79. };
  80. CarlaJackNonRealtimeThread(Callback* const callback)
  81. : CarlaThread("CarlaJackNonRealtimeThread"),
  82. fCallback(callback) {}
  83. protected:
  84. void run() override
  85. {
  86. fCallback->runNonRealtimeThread();
  87. }
  88. private:
  89. Callback* const fCallback;
  90. CARLA_DECLARE_NON_COPY_CLASS(CarlaJackNonRealtimeThread)
  91. };
  92. // ---------------------------------------------------------------------------------------------------------------------
  93. class CarlaJackAppClient : public CarlaJackRealtimeThread::Callback,
  94. public CarlaJackNonRealtimeThread::Callback
  95. {
  96. public:
  97. JackServerState fServer;
  98. LinkedList<JackClientState*> fClients;
  99. LinkedList<JackClientState*> fNewClients;
  100. CarlaJackAppClient()
  101. : fServer(this),
  102. fClients(),
  103. fNewClients(),
  104. fShmAudioPool(),
  105. fShmRtClientControl(),
  106. fShmNonRtClientControl(),
  107. fShmNonRtServerControl(),
  108. fAudioPoolCopy(nullptr),
  109. fAudioTmpBuf(nullptr),
  110. fDummyMidiInBuffer(true),
  111. fDummyMidiOutBuffer(false),
  112. fMidiInBuffers(nullptr),
  113. fMidiOutBuffers(nullptr),
  114. fIsOffline(false),
  115. fIsReady(false),
  116. fLastPingTime(-1),
  117. fSessionManager(0),
  118. fSetupHints(0),
  119. fRealtimeThread(this),
  120. fNonRealtimeThread(this),
  121. fRealtimeThreadMutex()
  122. #ifdef DEBUG
  123. ,leakDetector_CarlaJackAppClient()
  124. #endif
  125. {
  126. carla_debug("CarlaJackAppClient::CarlaJackAppClient()");
  127. const char* const shmIds(std::getenv("CARLA_SHM_IDS"));
  128. CARLA_SAFE_ASSERT_INT2_RETURN(shmIds != nullptr && std::strlen(shmIds) == 6*4, std::strlen(shmIds), 6*4,);
  129. const char* const libjackSetup(std::getenv("CARLA_LIBJACK_SETUP"));
  130. CARLA_SAFE_ASSERT_RETURN(libjackSetup != nullptr && std::strlen(libjackSetup) >= 6,);
  131. // make sure we don't get loaded again
  132. carla_unsetenv("CARLA_SHM_IDS");
  133. // kill ourselves if main carla dies
  134. carla_terminateProcessOnParentExit(true);
  135. for (int i=4; --i >= 0;) {
  136. CARLA_SAFE_ASSERT_RETURN(libjackSetup[i] >= '0' && libjackSetup[i] <= '0'+64,);
  137. }
  138. CARLA_SAFE_ASSERT_RETURN(libjackSetup[4] >= '0' && libjackSetup[4] <= '0' + LIBJACK_SESSION_MANAGER_NSM,);
  139. CARLA_SAFE_ASSERT_RETURN(libjackSetup[5] >= '0' && libjackSetup[5] < '0'+0x4f,);
  140. std::memcpy(fBaseNameAudioPool, shmIds+6*0, 6);
  141. std::memcpy(fBaseNameRtClientControl, shmIds+6*1, 6);
  142. std::memcpy(fBaseNameNonRtClientControl, shmIds+6*2, 6);
  143. std::memcpy(fBaseNameNonRtServerControl, shmIds+6*3, 6);
  144. fBaseNameAudioPool[6] = '\0';
  145. fBaseNameRtClientControl[6] = '\0';
  146. fBaseNameNonRtClientControl[6] = '\0';
  147. fBaseNameNonRtServerControl[6] = '\0';
  148. fServer.numAudioIns = static_cast<uint8_t>(libjackSetup[0] - '0');
  149. fServer.numAudioOuts = static_cast<uint8_t>(libjackSetup[1] - '0');
  150. fServer.numMidiIns = static_cast<uint8_t>(libjackSetup[2] - '0');
  151. fServer.numMidiOuts = static_cast<uint8_t>(libjackSetup[3] - '0');
  152. fSessionManager = static_cast<uint>(libjackSetup[4] - '0');
  153. fSetupHints = static_cast<uint>(libjackSetup[5] - '0');
  154. if (fSetupHints & LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN)
  155. fServer.numMidiOuts = 16;
  156. jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_HINTS_AND_CALLBACK,
  157. fSetupHints,
  158. (void*)carla_interposed_callback);
  159. jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_SESSION_MANAGER,
  160. fSessionManager,
  161. nullptr);
  162. fNonRealtimeThread.startThread(false);
  163. }
  164. ~CarlaJackAppClient() noexcept override
  165. {
  166. carla_debug("CarlaJackAppClient::~CarlaJackAppClient()");
  167. fLastPingTime = -1;
  168. fNonRealtimeThread.stopThread(5000);
  169. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  170. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  171. {
  172. JackClientState* const jclient(it.getValue(nullptr));
  173. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  174. delete jclient;
  175. }
  176. fClients.clear();
  177. }
  178. JackClientState* createClient(const char* const name)
  179. {
  180. while (fNonRealtimeThread.isThreadRunning() && ! fIsReady)
  181. carla_sleep(1);
  182. return new JackClientState(fServer, name);
  183. }
  184. void destroyClient(JackClientState* const jclient)
  185. {
  186. {
  187. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  188. fClients.removeOne(jclient);
  189. }
  190. delete jclient;
  191. }
  192. bool activateClient(JackClientState* const jclient)
  193. {
  194. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  195. if (! fClients.append(jclient))
  196. return false;
  197. if (! fNewClients.append(jclient))
  198. {
  199. fClients.removeOne(jclient);
  200. return false;
  201. }
  202. jclient->activated = true;
  203. jclient->deactivated = false;
  204. return true;
  205. }
  206. bool deactivateClient(JackClientState* const jclient)
  207. {
  208. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  209. if (! fClients.removeOne(jclient))
  210. return false;
  211. jclient->activated = false;
  212. jclient->deactivated = true;
  213. return true;
  214. }
  215. pthread_t getRealtimeThreadId() const noexcept
  216. {
  217. return (pthread_t)fRealtimeThread.getThreadId();
  218. }
  219. int handleInterposerCallback(const int cb_action, void* const ptr)
  220. {
  221. carla_debug("handleInterposerCallback(%o, %p)", cb_action, ptr);
  222. switch (cb_action)
  223. {
  224. case LIBJACK_INTERPOSER_CALLBACK_UI_HIDE: {
  225. const CarlaMutexLocker cml(fShmNonRtServerControl.mutex);
  226. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
  227. fShmNonRtServerControl.commitWrite();
  228. break;
  229. }
  230. }
  231. return 0;
  232. // maybe unused
  233. (void)ptr;
  234. }
  235. // -------------------------------------------------------------------
  236. protected:
  237. void runRealtimeThread() override;
  238. void runNonRealtimeThread() override;
  239. private:
  240. bool initSharedMemmory();
  241. void clearSharedMemory() noexcept;
  242. bool handleRtData();
  243. bool handleNonRtData();
  244. BridgeAudioPool fShmAudioPool;
  245. BridgeRtClientControl fShmRtClientControl;
  246. BridgeNonRtClientControl fShmNonRtClientControl;
  247. BridgeNonRtServerControl fShmNonRtServerControl;
  248. float* fAudioPoolCopy;
  249. float* fAudioTmpBuf;
  250. JackMidiPortBufferDummy fDummyMidiInBuffer;
  251. JackMidiPortBufferDummy fDummyMidiOutBuffer;
  252. JackMidiPortBufferOnStack* fMidiInBuffers;
  253. JackMidiPortBufferOnStack* fMidiOutBuffers;
  254. char fBaseNameAudioPool[6+1];
  255. char fBaseNameRtClientControl[6+1];
  256. char fBaseNameNonRtClientControl[6+1];
  257. char fBaseNameNonRtServerControl[6+1];
  258. bool fIsOffline;
  259. volatile bool fIsReady;
  260. int64_t fLastPingTime;
  261. uint fSessionManager;
  262. uint fSetupHints;
  263. CarlaJackRealtimeThread fRealtimeThread;
  264. CarlaJackNonRealtimeThread fNonRealtimeThread;
  265. CarlaMutex fRealtimeThreadMutex;
  266. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaJackAppClient)
  267. };
  268. // ---------------------------------------------------------------------------------------------------------------------
  269. bool CarlaJackAppClient::initSharedMemmory()
  270. {
  271. if (! fShmAudioPool.attachClient(fBaseNameAudioPool))
  272. {
  273. carla_stderr("Failed to attach to audio pool shared memory");
  274. return false;
  275. }
  276. if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl))
  277. {
  278. clearSharedMemory();
  279. carla_stderr("Failed to attach to rt client control shared memory");
  280. return false;
  281. }
  282. if (! fShmRtClientControl.mapData())
  283. {
  284. clearSharedMemory();
  285. carla_stderr("Failed to map rt client control shared memory");
  286. return false;
  287. }
  288. if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl))
  289. {
  290. clearSharedMemory();
  291. carla_stderr("Failed to attach to non-rt client control shared memory");
  292. return false;
  293. }
  294. if (! fShmNonRtClientControl.mapData())
  295. {
  296. clearSharedMemory();
  297. carla_stderr("Failed to map non-rt control client shared memory");
  298. return false;
  299. }
  300. if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl))
  301. {
  302. clearSharedMemory();
  303. carla_stderr("Failed to attach to non-rt server control shared memory");
  304. return false;
  305. }
  306. if (! fShmNonRtServerControl.mapData())
  307. {
  308. clearSharedMemory();
  309. carla_stderr("Failed to map non-rt control server shared memory");
  310. return false;
  311. }
  312. PluginBridgeNonRtClientOpcode opcode;
  313. opcode = fShmNonRtClientControl.readOpcode();
  314. CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientVersion, false);
  315. const uint32_t apiVersion = fShmNonRtClientControl.readUInt();
  316. CARLA_SAFE_ASSERT_RETURN(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT, false);
  317. const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt();
  318. CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData));
  319. const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt();
  320. CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData));
  321. const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt();
  322. CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData));
  323. if (shmRtClientDataSize != sizeof(BridgeRtClientData) ||
  324. shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) ||
  325. shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
  326. {
  327. carla_stderr2("CarlaJackAppClient: data size mismatch");
  328. return false;
  329. }
  330. opcode = fShmNonRtClientControl.readOpcode();
  331. CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientInitialSetup, false);
  332. fServer.bufferSize = fShmNonRtClientControl.readUInt();
  333. fServer.sampleRate = fShmNonRtClientControl.readDouble();
  334. if (fServer.bufferSize == 0 || carla_isZero(fServer.sampleRate))
  335. {
  336. carla_stderr2("CarlaJackAppClient: invalid empty state");
  337. return false;
  338. }
  339. fAudioTmpBuf = new float[fServer.bufferSize];
  340. carla_zeroFloats(fAudioTmpBuf, fServer.bufferSize);
  341. fLastPingTime = getCurrentTimeMilliseconds();
  342. CARLA_SAFE_ASSERT(fLastPingTime > 0);
  343. {
  344. // tell backend we're live
  345. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  346. // ready!
  347. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
  348. fShmNonRtServerControl.commitWrite();
  349. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  350. }
  351. fIsReady = true;
  352. return true;
  353. }
  354. void CarlaJackAppClient::clearSharedMemory() noexcept
  355. {
  356. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  357. if (fAudioPoolCopy != nullptr)
  358. {
  359. delete[] fAudioPoolCopy;
  360. fAudioPoolCopy = nullptr;
  361. }
  362. if (fAudioTmpBuf != nullptr)
  363. {
  364. delete[] fAudioTmpBuf;
  365. fAudioTmpBuf = nullptr;
  366. }
  367. if (fMidiInBuffers != nullptr)
  368. {
  369. delete[] fMidiInBuffers;
  370. fMidiInBuffers = nullptr;
  371. }
  372. if (fMidiOutBuffers != nullptr)
  373. {
  374. delete[] fMidiOutBuffers;
  375. fMidiOutBuffers = nullptr;
  376. }
  377. fShmAudioPool.clear();
  378. fShmRtClientControl.clear();
  379. fShmNonRtClientControl.clear();
  380. fShmNonRtServerControl.clear();
  381. }
  382. bool CarlaJackAppClient::handleRtData()
  383. {
  384. if (fNewClients.count() != 0)
  385. {
  386. for (LinkedList<JackClientState*>::Itenerator it = fNewClients.begin2(); it.valid(); it.next())
  387. {
  388. JackClientState* const jclient(it.getValue(nullptr));
  389. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  390. if (jclient->threadInitCb != nullptr)
  391. jclient->threadInitCb(jclient->threadInitCbPtr);
  392. }
  393. fNewClients.clear();
  394. }
  395. const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl);
  396. if (! helper.ok)
  397. return false;
  398. bool ret = false;
  399. for (; fShmRtClientControl.isDataAvailableForReading();)
  400. {
  401. const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
  402. #ifdef DEBUG
  403. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent) {
  404. carla_debug("CarlaJackAppClientRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
  405. }
  406. #endif
  407. switch (opcode)
  408. {
  409. case kPluginBridgeRtClientNull:
  410. break;
  411. case kPluginBridgeRtClientSetAudioPool: {
  412. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  413. if (fShmAudioPool.data != nullptr)
  414. {
  415. jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data);
  416. fShmAudioPool.data = nullptr;
  417. }
  418. if (fAudioPoolCopy != nullptr)
  419. {
  420. delete[] fAudioPoolCopy;
  421. fAudioPoolCopy = nullptr;
  422. }
  423. const uint64_t poolSize(fShmRtClientControl.readULong());
  424. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  425. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  426. fAudioPoolCopy = new float[poolSize];
  427. break;
  428. }
  429. case kPluginBridgeRtClientSetBufferSize:
  430. if (const uint32_t newBufferSize = fShmRtClientControl.readUInt())
  431. {
  432. if (fServer.bufferSize != newBufferSize)
  433. {
  434. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  435. fServer.bufferSize = newBufferSize;
  436. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  437. {
  438. JackClientState* const jclient(it.getValue(nullptr));
  439. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  440. if (jclient->bufferSizeCb != nullptr)
  441. jclient->bufferSizeCb(fServer.bufferSize, jclient->bufferSizeCbPtr);
  442. }
  443. delete[] fAudioTmpBuf;
  444. fAudioTmpBuf = new float[fServer.bufferSize];
  445. carla_zeroFloats(fAudioTmpBuf, fServer.bufferSize);
  446. }
  447. }
  448. break;
  449. case kPluginBridgeRtClientSetSampleRate: {
  450. const double newSampleRate = fShmRtClientControl.readDouble();
  451. if (carla_isNotZero(newSampleRate) && carla_isNotEqual(fServer.sampleRate, newSampleRate))
  452. {
  453. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  454. fServer.sampleRate = newSampleRate;
  455. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  456. {
  457. JackClientState* const jclient(it.getValue(nullptr));
  458. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  459. if (jclient->sampleRateCb != nullptr)
  460. jclient->sampleRateCb(static_cast<uint32_t>(fServer.sampleRate), jclient->sampleRateCbPtr);
  461. }
  462. }
  463. } break;
  464. case kPluginBridgeRtClientSetOnline: {
  465. const bool offline = fShmRtClientControl.readBool();
  466. if (fIsOffline != offline)
  467. {
  468. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  469. fIsOffline = offline;
  470. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  471. {
  472. JackClientState* const jclient(it.getValue(nullptr));
  473. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  474. if (jclient->freewheelCb != nullptr)
  475. jclient->freewheelCb(offline ? 1 : 0, jclient->freewheelCbPtr);
  476. }
  477. }
  478. } break;
  479. case kPluginBridgeRtClientControlEventParameter:
  480. case kPluginBridgeRtClientControlEventMidiBank:
  481. case kPluginBridgeRtClientControlEventMidiProgram:
  482. case kPluginBridgeRtClientControlEventAllSoundOff:
  483. case kPluginBridgeRtClientControlEventAllNotesOff:
  484. break;
  485. case kPluginBridgeRtClientMidiEvent: {
  486. const uint32_t time(fShmRtClientControl.readUInt());
  487. const uint8_t port(fShmRtClientControl.readByte());
  488. const uint8_t size(fShmRtClientControl.readByte());
  489. CARLA_SAFE_ASSERT_BREAK(size > 0);
  490. if (port >= fServer.numMidiIns || size > JackMidiPortBufferBase::kMaxEventSize || ! fRealtimeThreadMutex.tryLock())
  491. {
  492. for (uint8_t i=0; i<size; ++i)
  493. fShmRtClientControl.readByte();
  494. break;
  495. }
  496. JackMidiPortBufferOnStack& midiPortBuf(fMidiInBuffers[port]);
  497. if (midiPortBuf.count < JackMidiPortBufferBase::kMaxEventCount &&
  498. midiPortBuf.bufferPoolPos + size < JackMidiPortBufferBase::kBufferPoolSize)
  499. {
  500. jack_midi_event_t& ev(midiPortBuf.events[midiPortBuf.count++]);
  501. ev.time = time;
  502. ev.size = size;
  503. ev.buffer = midiPortBuf.bufferPool + midiPortBuf.bufferPoolPos;
  504. midiPortBuf.bufferPoolPos += size;
  505. for (uint8_t i=0; i<size; ++i)
  506. ev.buffer[i] = fShmRtClientControl.readByte();
  507. }
  508. fRealtimeThreadMutex.unlock(true);
  509. break;
  510. }
  511. case kPluginBridgeRtClientProcess: {
  512. const uint32_t frames(fShmRtClientControl.readUInt());
  513. CARLA_SAFE_ASSERT_UINT2_BREAK(frames == fServer.bufferSize, frames, fServer.bufferSize);
  514. // TODO tell client of xrun in case buffersize does not match
  515. const CarlaMutexTryLocker cmtl(fRealtimeThreadMutex, fIsOffline);
  516. if (cmtl.wasLocked())
  517. {
  518. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  519. // mixdown is default, do buffer addition (for multiple clients) if requested
  520. const bool doBufferAddition = fSetupHints & LIBJACK_FLAG_AUDIO_BUFFERS_ADDITION;
  521. // mixdown midi outputs based on channel if requested
  522. const bool doMidiChanMixdown = fSetupHints & LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN;
  523. // location to start of audio outputs (shm buffer)
  524. float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fServer.numAudioIns);
  525. if (doBufferAddition && fServer.numAudioOuts > 0)
  526. carla_zeroFloats(fdataRealOuts, fServer.bufferSize*fServer.numAudioOuts);
  527. if (! fClients.isEmpty())
  528. {
  529. // save transport for all clients
  530. const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  531. const bool transportChanged = fServer.playing != bridgeTimeInfo.playing ||
  532. (bridgeTimeInfo.playing && fServer.position.frame + frames != bridgeTimeInfo.frame);
  533. fServer.playing = bridgeTimeInfo.playing;
  534. fServer.position.frame = static_cast<jack_nframes_t>(bridgeTimeInfo.frame);
  535. fServer.position.usecs = bridgeTimeInfo.usecs;
  536. fServer.position.frame_rate = static_cast<jack_nframes_t>(fServer.sampleRate);
  537. if (bridgeTimeInfo.validFlags & kPluginBridgeTimeInfoValidBBT)
  538. {
  539. fServer.position.valid = JackPositionBBT;
  540. fServer.position.bar = bridgeTimeInfo.bar;
  541. fServer.position.beat = bridgeTimeInfo.beat;
  542. fServer.position.tick = static_cast<int32_t>(bridgeTimeInfo.tick + 0.5);
  543. fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar;
  544. fServer.position.beat_type = bridgeTimeInfo.beatType;
  545. fServer.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat;
  546. fServer.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute;
  547. fServer.position.bar_start_tick = bridgeTimeInfo.barStartTick;
  548. }
  549. else
  550. {
  551. fServer.position.valid = static_cast<jack_position_bits_t>(0x0);
  552. }
  553. int numClientOutputsProcessed = 0;
  554. // now go through each client
  555. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  556. {
  557. JackClientState* const jclient(it.getValue(nullptr));
  558. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  559. const CarlaMutexTryLocker cmtl2(jclient->mutex, fIsOffline);
  560. // check if we can process
  561. if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
  562. {
  563. if (fServer.numAudioOuts > 0)
  564. carla_zeroFloats(fdataRealOuts, fServer.bufferSize*fServer.numAudioOuts);
  565. if (jclient->deactivated)
  566. fShmRtClientControl.data->procFlags = 1;
  567. }
  568. else
  569. {
  570. // report transport sync changes if needed
  571. if (transportChanged && jclient->syncCb != nullptr)
  572. {
  573. jclient->syncCb(fServer.playing ? JackTransportRolling : JackTransportStopped,
  574. &fServer.position,
  575. jclient->syncCbPtr);
  576. }
  577. uint8_t i;
  578. // direct access to shm buffer, used only for inputs
  579. float* fdataReal = fShmAudioPool.data;
  580. // safe temp location for output, mixed down to shm buffer later on
  581. float* fdataCopy = fAudioPoolCopy;
  582. // wherever we're using fAudioTmpBuf
  583. bool needsTmpBufClear = false;
  584. // set audio inputs
  585. i = 0;
  586. for (LinkedList<JackPortState*>::Itenerator it2 = jclient->audioIns.begin2(); it2.valid(); it2.next())
  587. {
  588. JackPortState* const jport = it2.getValue(nullptr);
  589. CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);
  590. if (i++ < fServer.numAudioIns)
  591. {
  592. if (numClientOutputsProcessed == 0 || ! doBufferAddition)
  593. jport->buffer = fdataReal;
  594. else
  595. jport->buffer = fdataRealOuts + (i*fServer.bufferSize);
  596. fdataReal += fServer.bufferSize;
  597. fdataCopy += fServer.bufferSize;
  598. }
  599. else
  600. {
  601. jport->buffer = fAudioTmpBuf;
  602. needsTmpBufClear = true;
  603. }
  604. }
  605. if (i < fServer.numAudioIns)
  606. {
  607. const std::size_t remainingBufferSize = fServer.bufferSize * static_cast<uint8_t>(fServer.numAudioIns - i);
  608. //fdataReal += remainingBufferSize;
  609. fdataCopy += remainingBufferSize;
  610. }
  611. // location to start of audio outputs
  612. float* const fdataCopyOuts = fdataCopy;
  613. // set audio outputs
  614. i = 0;
  615. for (LinkedList<JackPortState*>::Itenerator it2 = jclient->audioOuts.begin2(); it2.valid(); it2.next())
  616. {
  617. JackPortState* const jport = it2.getValue(nullptr);
  618. CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);
  619. if (i++ < fServer.numAudioOuts)
  620. {
  621. jport->buffer = fdataCopy;
  622. fdataCopy += fServer.bufferSize;
  623. }
  624. else
  625. {
  626. jport->buffer = fAudioTmpBuf;
  627. needsTmpBufClear = true;
  628. }
  629. }
  630. if (i < fServer.numAudioOuts)
  631. {
  632. const std::size_t remainingBufferSize = fServer.bufferSize * static_cast<uint8_t>(fServer.numAudioOuts - i);
  633. carla_zeroFloats(fdataCopy, remainingBufferSize);
  634. //fdataCopy += remainingBufferSize;
  635. }
  636. // set midi inputs
  637. i = 0;
  638. for (LinkedList<JackPortState*>::Itenerator it2 = jclient->midiIns.begin2(); it2.valid(); it2.next())
  639. {
  640. JackPortState* const jport = it2.getValue(nullptr);
  641. CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);
  642. if (i++ < fServer.numMidiIns)
  643. jport->buffer = &fMidiInBuffers[i-1];
  644. else
  645. jport->buffer = &fDummyMidiInBuffer;
  646. }
  647. // set midi outputs
  648. i = 0;
  649. for (LinkedList<JackPortState*>::Itenerator it2 = jclient->midiOuts.begin2(); it2.valid(); it2.next())
  650. {
  651. JackPortState* const jport = it2.getValue(nullptr);
  652. CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);
  653. if (i++ < fServer.numMidiOuts)
  654. jport->buffer = &fMidiOutBuffers[i-1];
  655. else
  656. jport->buffer = &fDummyMidiOutBuffer;
  657. }
  658. if (needsTmpBufClear)
  659. carla_zeroFloats(fAudioTmpBuf, fServer.bufferSize);
  660. jclient->processCb(fServer.bufferSize, jclient->processCbPtr);
  661. if (fServer.numAudioOuts > 0)
  662. {
  663. if (++numClientOutputsProcessed == 1)
  664. {
  665. // first client, we can copy stuff over
  666. carla_copyFloats(fdataRealOuts, fdataCopyOuts,
  667. fServer.bufferSize*fServer.numAudioOuts);
  668. }
  669. else
  670. {
  671. // subsequent clients, add data (then divide by number of clients later on)
  672. carla_add(fdataRealOuts, fdataCopyOuts,
  673. fServer.bufferSize*fServer.numAudioOuts);
  674. if (doBufferAddition)
  675. {
  676. // for more than 1 client addition, we need to divide buffers now
  677. carla_multiply(fdataRealOuts,
  678. 1.0f/static_cast<float>(numClientOutputsProcessed),
  679. fServer.bufferSize*fServer.numAudioOuts);
  680. }
  681. }
  682. if (jclient->audioOuts.count() == 1 && fServer.numAudioOuts > 1)
  683. {
  684. for (uint8_t j=1; j<fServer.numAudioOuts; ++j)
  685. {
  686. carla_copyFloats(fdataRealOuts+(fServer.bufferSize*j),
  687. fdataCopyOuts,
  688. fServer.bufferSize);
  689. }
  690. }
  691. }
  692. }
  693. }
  694. if (numClientOutputsProcessed > 1 && ! doBufferAddition)
  695. {
  696. // more than 1 client active, need to divide buffers
  697. carla_multiply(fdataRealOuts,
  698. 1.0f/static_cast<float>(numClientOutputsProcessed),
  699. fServer.bufferSize*fServer.numAudioOuts);
  700. }
  701. }
  702. // fClients.isEmpty()
  703. else if (fServer.numAudioOuts > 0)
  704. {
  705. carla_zeroFloats(fdataRealOuts, fServer.bufferSize*fServer.numAudioOuts);
  706. }
  707. for (uint8_t i=0; i<fServer.numMidiIns; ++i)
  708. {
  709. fMidiInBuffers[i].count = 0;
  710. fMidiInBuffers[i].bufferPoolPos = 0;
  711. }
  712. if (fServer.numMidiOuts > 0)
  713. {
  714. uint8_t* midiData = fShmRtClientControl.data->midiOut;
  715. carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
  716. std::size_t curMidiDataPos = 0;
  717. for (uint8_t i=0; i<fServer.numMidiOuts; ++i)
  718. {
  719. JackMidiPortBufferOnStack& midiPortBuf(fMidiOutBuffers[i]);
  720. for (uint16_t j=0; j<midiPortBuf.count; ++j)
  721. {
  722. jack_midi_event_t& jmevent(midiPortBuf.events[j]);
  723. if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + jmevent.size >= kBridgeRtClientDataMidiOutSize)
  724. break;
  725. if (doMidiChanMixdown && MIDI_IS_CHANNEL_MESSAGE(jmevent.buffer[0]))
  726. jmevent.buffer[0] = static_cast<jack_midi_data_t>(
  727. (jmevent.buffer[0] & MIDI_STATUS_BIT) | (i & MIDI_CHANNEL_BIT));
  728. // set time
  729. *(uint32_t*)midiData = jmevent.time;
  730. midiData += 4;
  731. // set port
  732. *midiData++ = doMidiChanMixdown ? 0 : i;
  733. // set size
  734. *midiData++ = static_cast<uint8_t>(jmevent.size);
  735. // set data
  736. std::memcpy(midiData, jmevent.buffer, jmevent.size);
  737. midiData += jmevent.size;
  738. curMidiDataPos += kBridgeBaseMidiOutHeaderSize + jmevent.size;
  739. }
  740. }
  741. // make last event null, so server stops when reaching it
  742. if (curMidiDataPos != 0 &&
  743. curMidiDataPos + kBridgeBaseMidiOutHeaderSize < kBridgeRtClientDataMidiOutSize)
  744. {
  745. carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
  746. // sort events in case of mixdown
  747. if (doMidiChanMixdown)
  748. {
  749. uint32_t time;
  750. uint8_t size, *midiDataPtr;
  751. uint8_t tmp[kBridgeBaseMidiOutHeaderSize + JackMidiPortBufferBase::kMaxEventSize];
  752. bool wasSorted = true;
  753. for (; wasSorted;)
  754. {
  755. midiDataPtr = fShmRtClientControl.data->midiOut;
  756. uint8_t* prevData = midiDataPtr;
  757. uint32_t prevTime = *(uint32_t*)midiDataPtr;
  758. uint8_t prevSize = *(midiDataPtr + 5);
  759. wasSorted = false;
  760. for (;;)
  761. {
  762. time = *(uint32_t*)midiDataPtr;
  763. size = *(midiDataPtr + 5); // time and port
  764. if (size == 0)
  765. break;
  766. if (prevTime > time)
  767. {
  768. // copy previous data to a temporary place
  769. std::memcpy(tmp, prevData, kBridgeBaseMidiOutHeaderSize + prevSize);
  770. // override previous data with new one (shifting left)
  771. std::memcpy(prevData, midiDataPtr, kBridgeBaseMidiOutHeaderSize + size);
  772. // override new data with old one
  773. std::memcpy(midiDataPtr, tmp, kBridgeBaseMidiOutHeaderSize + prevSize);
  774. // done swapping, flag it
  775. wasSorted = true;
  776. }
  777. prevTime = time;
  778. prevSize = size;
  779. prevData = midiDataPtr;
  780. midiDataPtr += 6 + size;
  781. }
  782. }
  783. }
  784. }
  785. }
  786. }
  787. else
  788. {
  789. carla_stderr2("CarlaJackAppClient: fRealtimeThreadMutex tryLock failed");
  790. }
  791. fServer.monotonic_frame += frames;
  792. break;
  793. }
  794. case kPluginBridgeRtClientQuit:
  795. ret = true;
  796. break;
  797. }
  798. #ifdef DEBUG
  799. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent) {
  800. carla_debug("CarlaJackAppClientRtThread::run() - opcode %s done", PluginBridgeRtClientOpcode2str(opcode));
  801. }
  802. #endif
  803. }
  804. return ret;
  805. }
  806. bool CarlaJackAppClient::handleNonRtData()
  807. {
  808. bool ret = false;
  809. for (; fShmNonRtClientControl.isDataAvailableForReading();)
  810. {
  811. const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode());
  812. #ifdef DEBUG
  813. if (opcode != kPluginBridgeNonRtClientPing) {
  814. carla_debug("CarlaJackAppClient::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode));
  815. }
  816. #endif
  817. if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0)
  818. fLastPingTime = getCurrentTimeMilliseconds();
  819. switch (opcode)
  820. {
  821. case kPluginBridgeNonRtClientNull:
  822. break;
  823. case kPluginBridgeNonRtClientVersion: {
  824. const uint apiVersion = fShmNonRtServerControl.readUInt();
  825. CARLA_SAFE_ASSERT_UINT2(apiVersion == CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT,
  826. apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT);
  827. } break;
  828. case kPluginBridgeNonRtClientPing: {
  829. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  830. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  831. fShmNonRtServerControl.commitWrite();
  832. } break;
  833. case kPluginBridgeNonRtClientPingOnOff: {
  834. const uint32_t onOff(fShmNonRtClientControl.readBool());
  835. fLastPingTime = onOff ? getCurrentTimeMilliseconds() : -1;
  836. } break;
  837. case kPluginBridgeNonRtClientActivate:
  838. case kPluginBridgeNonRtClientDeactivate:
  839. break;
  840. case kPluginBridgeNonRtClientInitialSetup:
  841. // should never happen!!
  842. fShmNonRtServerControl.readUInt();
  843. fShmNonRtServerControl.readDouble();
  844. break;
  845. case kPluginBridgeNonRtClientSetParameterValue:
  846. case kPluginBridgeNonRtClientSetParameterMidiChannel:
  847. case kPluginBridgeNonRtClientSetParameterMappedControlIndex:
  848. case kPluginBridgeNonRtClientSetParameterMappedRange:
  849. case kPluginBridgeNonRtClientSetProgram:
  850. case kPluginBridgeNonRtClientSetMidiProgram:
  851. case kPluginBridgeNonRtClientSetCustomData:
  852. case kPluginBridgeNonRtClientSetChunkDataFile:
  853. break;
  854. case kPluginBridgeNonRtClientSetOption:
  855. fShmNonRtClientControl.readUInt();
  856. fShmNonRtClientControl.readBool();
  857. break;
  858. case kPluginBridgeNonRtClientSetOptions:
  859. fShmNonRtClientControl.readUInt();
  860. break;
  861. case kPluginBridgeNonRtClientSetCtrlChannel:
  862. fShmNonRtClientControl.readShort();
  863. break;
  864. case kPluginBridgeNonRtClientGetParameterText:
  865. fShmNonRtClientControl.readUInt();
  866. break;
  867. case kPluginBridgeNonRtClientPrepareForSave:
  868. {
  869. if (fSessionManager == LIBJACK_SESSION_MANAGER_AUTO && std::getenv("NSM_URL") == nullptr)
  870. {
  871. struct sigaction sig;
  872. carla_zeroStruct(sig);
  873. sigaction(SIGUSR1, nullptr, &sig);
  874. if (sig.sa_handler != nullptr)
  875. fSessionManager = LIBJACK_SESSION_MANAGER_LADISH;
  876. }
  877. if (fSessionManager == LIBJACK_SESSION_MANAGER_LADISH)
  878. ::kill(::getpid(), SIGUSR1);
  879. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  880. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  881. fShmNonRtServerControl.commitWrite();
  882. }
  883. break;
  884. case kPluginBridgeNonRtClientRestoreLV2State:
  885. break;
  886. case kPluginBridgeNonRtClientShowUI:
  887. if (jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SHOW_HIDE_GUI, 1, nullptr) == 1337)
  888. {
  889. // failed, LD_PRELOAD did not work?
  890. const char* const message("Cannot show UI, LD_PRELOAD not working?");
  891. const std::size_t messageSize(std::strlen(message));
  892. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  893. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
  894. fShmNonRtServerControl.commitWrite();
  895. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  896. fShmNonRtServerControl.writeUInt(messageSize);
  897. fShmNonRtServerControl.writeCustomData(message, messageSize);
  898. fShmNonRtServerControl.commitWrite();
  899. }
  900. break;
  901. case kPluginBridgeNonRtClientHideUI:
  902. jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SHOW_HIDE_GUI, 0, nullptr);
  903. break;
  904. case kPluginBridgeNonRtClientUiParameterChange:
  905. case kPluginBridgeNonRtClientUiProgramChange:
  906. case kPluginBridgeNonRtClientUiMidiProgramChange:
  907. case kPluginBridgeNonRtClientUiNoteOn:
  908. case kPluginBridgeNonRtClientUiNoteOff:
  909. break;
  910. case kPluginBridgeNonRtClientQuit:
  911. ret = true;
  912. break;
  913. }
  914. #ifdef DEBUG
  915. if (opcode != kPluginBridgeNonRtClientPing) {
  916. carla_debug("CarlaJackAppClient::handleNonRtData() - opcode %s handled", PluginBridgeNonRtClientOpcode2str(opcode));
  917. }
  918. #endif
  919. }
  920. return ret;
  921. }
  922. void CarlaJackAppClient::runRealtimeThread()
  923. {
  924. carla_debug("CarlaJackAppClient runRealtimeThread START");
  925. #ifdef __SSE2_MATH__
  926. // Set FTZ and DAZ flags
  927. _mm_setcsr(_mm_getcsr() | 0x8040);
  928. #endif
  929. bool quitReceived = false;
  930. for (; ! fRealtimeThread.shouldThreadExit();)
  931. {
  932. if (handleRtData())
  933. {
  934. quitReceived = true;
  935. break;
  936. }
  937. }
  938. fNonRealtimeThread.signalThreadShouldExit();
  939. carla_debug("CarlaJackAppClient runRealtimeThread FINISHED");
  940. // TODO
  941. return; (void)quitReceived;
  942. }
  943. void CarlaJackAppClient::runNonRealtimeThread()
  944. {
  945. carla_debug("CarlaJackAppClient runNonRealtimeThread START");
  946. CARLA_SAFE_ASSERT_RETURN(initSharedMemmory(),);
  947. if (fServer.numMidiIns > 0)
  948. {
  949. fMidiInBuffers = new JackMidiPortBufferOnStack[fServer.numMidiIns];
  950. for (uint8_t i=0; i<fServer.numMidiIns; ++i)
  951. fMidiInBuffers[i].isInput = true;
  952. }
  953. if (fServer.numMidiOuts > 0)
  954. {
  955. fMidiOutBuffers = new JackMidiPortBufferOnStack[fServer.numMidiOuts];
  956. for (uint8_t i=0; i<fServer.numMidiOuts; ++i)
  957. fMidiOutBuffers[i].isInput = false;
  958. }
  959. fRealtimeThread.startThread(true);
  960. fLastPingTime = getCurrentTimeMilliseconds();
  961. carla_stdout("Carla Jack Client Ready!");
  962. bool quitReceived = false,
  963. timedOut = false;
  964. for (; ! fNonRealtimeThread.shouldThreadExit();)
  965. {
  966. carla_msleep(50);
  967. try {
  968. quitReceived = handleNonRtData();
  969. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  970. if (quitReceived)
  971. break;
  972. /*
  973. if (fLastPingTime > 0 && getCurrentTimeMilliseconds() > fLastPingTime + 30000)
  974. {
  975. carla_stderr("Did not receive ping message from server for 30 secs, closing...");
  976. timedOut = true;
  977. fRealtimeThread.signalThreadShouldExit();
  978. break;
  979. }
  980. */
  981. }
  982. //callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  983. if (quitReceived)
  984. {
  985. ::kill(::getpid(), SIGTERM);
  986. }
  987. else if (timedOut)
  988. {
  989. // TODO send shutdown?
  990. carla_stderr("CarlaJackAppClient error: runNonRealtimeThread ended with time out");
  991. ::kill(::getpid(), SIGTERM);
  992. }
  993. else
  994. {
  995. bool activated;
  996. {
  997. const CarlaMutexLocker cms(fRealtimeThreadMutex);
  998. if (fClients.isEmpty())
  999. {
  1000. activated = false;
  1001. }
  1002. else if (JackClientState* const jclient = fClients.getLast(nullptr))
  1003. {
  1004. const CarlaMutexLocker cms2(jclient->mutex);
  1005. activated = jclient->activated;
  1006. }
  1007. else
  1008. {
  1009. activated = true;
  1010. }
  1011. }
  1012. if (activated)
  1013. {
  1014. carla_stderr("CarlaJackAppClient error: runNonRealtimeThread ended while client is activated");
  1015. const char* const message("Plugin bridge error, process thread has stopped");
  1016. const std::size_t messageSize(std::strlen(message));
  1017. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  1018. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  1019. fShmNonRtServerControl.writeUInt(messageSize);
  1020. fShmNonRtServerControl.writeCustomData(message, messageSize);
  1021. fShmNonRtServerControl.commitWrite();
  1022. }
  1023. }
  1024. if (fRealtimeThread.isThreadRunning())
  1025. {
  1026. fRealtimeThread.signalThreadShouldExit();
  1027. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  1028. if (fShmRtClientControl.data != nullptr)
  1029. fShmRtClientControl.data->procFlags = 1;
  1030. }
  1031. clearSharedMemory();
  1032. fRealtimeThread.stopThread(5000);
  1033. carla_debug("CarlaJackAppClient runNonRealtimeThread FINISHED");
  1034. }
  1035. CARLA_BACKEND_END_NAMESPACE
  1036. // ---------------------------------------------------------------------------------------------------------------------
  1037. using CarlaBackend::CarlaJackAppClient;
  1038. using CarlaBackend::JackClientState;
  1039. static CarlaJackAppClient gClient;
  1040. CARLA_BACKEND_START_NAMESPACE
  1041. static int carla_interposed_callback(int cb_action, void* ptr)
  1042. {
  1043. return gClient.handleInterposerCallback(cb_action, ptr);
  1044. }
  1045. CARLA_BACKEND_END_NAMESPACE
  1046. // ---------------------------------------------------------------------------------------------------------------------
  1047. CARLA_EXPORT
  1048. jack_client_t* jack_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...)
  1049. {
  1050. carla_debug("%s(%s, 0x%x, %p)", __FUNCTION__, client_name, options, status);
  1051. if (JackClientState* const client = gClient.createClient(client_name))
  1052. {
  1053. if (status != nullptr)
  1054. *status = static_cast<JackStatus>(0x0);
  1055. return (jack_client_t*)client;
  1056. }
  1057. if (status != nullptr)
  1058. *status = JackServerError;
  1059. return nullptr;
  1060. // unused
  1061. (void)options;
  1062. }
  1063. CARLA_EXPORT
  1064. jack_client_t* jack_client_new(const char* client_name)
  1065. {
  1066. return jack_client_open(client_name, JackNullOption, nullptr);
  1067. }
  1068. CARLA_EXPORT
  1069. int jack_client_close(jack_client_t* client)
  1070. {
  1071. carla_debug("%s(%p)", __FUNCTION__, client);
  1072. JackClientState* const jclient = (JackClientState*)client;
  1073. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);
  1074. gClient.destroyClient(jclient);
  1075. return 0;
  1076. }
  1077. CARLA_EXPORT
  1078. int jack_activate(jack_client_t* client)
  1079. {
  1080. carla_debug("%s(%p)", __FUNCTION__, client);
  1081. JackClientState* const jclient = (JackClientState*)client;
  1082. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);
  1083. return gClient.activateClient(jclient) ? 0 : 1;
  1084. }
  1085. CARLA_EXPORT
  1086. int jack_deactivate(jack_client_t* client)
  1087. {
  1088. carla_debug("%s(%p)", __FUNCTION__, client);
  1089. JackClientState* const jclient = (JackClientState*)client;
  1090. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);
  1091. return gClient.deactivateClient(jclient) ? 0 : 1;
  1092. }
  1093. // ---------------------------------------------------------------------------------------------------------------------
  1094. CARLA_EXPORT
  1095. pthread_t jack_client_thread_id(jack_client_t* client)
  1096. {
  1097. carla_debug("%s(%p)", __FUNCTION__, client);
  1098. JackClientState* const jclient = (JackClientState*)client;
  1099. CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);
  1100. CarlaJackAppClient* const jackAppPtr = jclient->server.jackAppPtr;
  1101. CARLA_SAFE_ASSERT_RETURN(jackAppPtr != nullptr && jackAppPtr == &gClient, 0);
  1102. return jackAppPtr->getRealtimeThreadId();
  1103. }
  1104. // ---------------------------------------------------------------------------------------------------------------------
  1105. #include "jackbridge/JackBridge2.cpp"
  1106. #include "CarlaBridgeUtils.cpp"
  1107. // ---------------------------------------------------------------------------------------------------------------------
  1108. // TODO
  1109. CARLA_BACKEND_USE_NAMESPACE
  1110. CARLA_EXPORT
  1111. int jack_client_real_time_priority(jack_client_t* client)
  1112. {
  1113. carla_debug("%s(%p)", __FUNCTION__, client);
  1114. // code as used by water
  1115. const int minPriority = sched_get_priority_min(SCHED_RR);
  1116. const int maxPriority = sched_get_priority_max(SCHED_RR);
  1117. return ((maxPriority - minPriority) * 9) / 10 + minPriority;
  1118. // unused
  1119. (void)client;
  1120. }
  1121. int jack_client_create_thread(jack_client_t* client, pthread_t* thread, int priority,
  1122. int realtime, void *(*start_routine)(void*), void* arg)
  1123. {
  1124. carla_stderr2("%s(%p, %p, %i, %i, %p, %p)", __FUNCTION__, client, thread, priority, realtime, start_routine, arg);
  1125. return ENOSYS;
  1126. }
  1127. typedef void (*JackSessionCallback)(jack_session_event_t*, void*);
  1128. CARLA_EXPORT
  1129. int jack_set_session_callback(jack_client_t* client, JackSessionCallback callback, void* arg)
  1130. {
  1131. carla_stderr2("%s(%p, %p, %p)", __FUNCTION__, client, callback, arg);
  1132. return 0;
  1133. }
  1134. // ---------------------------------------------------------------------------------------------------------------------