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.

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