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.

971 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 == kPluginBridgeNonRtClientSetBufferSize, opcode);
  238. fServer.bufferSize = fShmNonRtClientControl.readUInt();
  239. opcode = fShmNonRtClientControl.readOpcode();
  240. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode);
  241. fServer.sampleRate = fShmNonRtClientControl.readDouble();
  242. if (fServer.bufferSize == 0 || carla_isZero(fServer.sampleRate))
  243. {
  244. carla_stderr2("CarlaJackAppClient: invalid empty state");
  245. return false;
  246. }
  247. fAudioTmpBuf = new float[fServer.bufferSize];
  248. FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);
  249. // tell backend we're live
  250. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  251. fLastPingTime = Time::currentTimeMillis();
  252. CARLA_SAFE_ASSERT(fLastPingTime > 0);
  253. // ready!
  254. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
  255. fShmNonRtServerControl.commitWrite();
  256. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  257. return true;
  258. }
  259. void CarlaJackAppClient::clearSharedMemory() noexcept
  260. {
  261. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  262. if (fAudioPoolCopy != nullptr)
  263. {
  264. delete[] fAudioPoolCopy;
  265. fAudioPoolCopy = nullptr;
  266. }
  267. if (fAudioTmpBuf != nullptr)
  268. {
  269. delete[] fAudioTmpBuf;
  270. fAudioTmpBuf = nullptr;
  271. }
  272. fShmAudioPool.clear();
  273. fShmRtClientControl.clear();
  274. fShmNonRtClientControl.clear();
  275. fShmNonRtServerControl.clear();
  276. }
  277. bool CarlaJackAppClient::handleRtData()
  278. {
  279. const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl);
  280. if (! helper.ok)
  281. return false;
  282. bool ret = false;
  283. for (; fShmRtClientControl.isDataAvailableForReading();)
  284. {
  285. const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
  286. //#ifdef DEBUG
  287. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent)
  288. {
  289. carla_stdout("CarlaJackAppClientRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
  290. }
  291. //#endif
  292. switch (opcode)
  293. {
  294. case kPluginBridgeRtClientNull:
  295. break;
  296. case kPluginBridgeRtClientSetAudioPool: {
  297. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  298. if (fShmAudioPool.data != nullptr)
  299. {
  300. jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data);
  301. fShmAudioPool.data = nullptr;
  302. }
  303. if (fAudioPoolCopy != nullptr)
  304. {
  305. delete[] fAudioPoolCopy;
  306. fAudioPoolCopy = nullptr;
  307. }
  308. const uint64_t poolSize(fShmRtClientControl.readULong());
  309. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  310. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  311. fAudioPoolCopy = new float[poolSize];
  312. break;
  313. }
  314. case kPluginBridgeRtClientControlEventParameter:
  315. case kPluginBridgeRtClientControlEventMidiBank:
  316. case kPluginBridgeRtClientControlEventMidiProgram:
  317. case kPluginBridgeRtClientControlEventAllSoundOff:
  318. case kPluginBridgeRtClientControlEventAllNotesOff:
  319. case kPluginBridgeRtClientMidiEvent:
  320. break;
  321. case kPluginBridgeRtClientProcess: {
  322. const CarlaMutexTryLocker cmtl(fRealtimeThreadMutex);
  323. if (cmtl.wasLocked())
  324. {
  325. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  326. // location to start of audio outputs (shm buffer)
  327. float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fNumPorts.audioIns);
  328. if (! fClients.isEmpty())
  329. {
  330. // save tranport for all clients
  331. const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  332. fServer.playing = bridgeTimeInfo.playing;
  333. fServer.position.frame = bridgeTimeInfo.frame;
  334. fServer.position.usecs = bridgeTimeInfo.usecs;
  335. if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */)
  336. {
  337. fServer.position.valid = JackPositionBBT;
  338. fServer.position.bar = bridgeTimeInfo.bar;
  339. fServer.position.beat = bridgeTimeInfo.beat;
  340. fServer.position.tick = bridgeTimeInfo.tick;
  341. fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar;
  342. fServer.position.beat_type = bridgeTimeInfo.beatType;
  343. fServer.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat;
  344. fServer.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute;
  345. fServer.position.bar_start_tick = bridgeTimeInfo.barStartTick;
  346. }
  347. else
  348. {
  349. fServer.position.valid = static_cast<jack_position_bits_t>(0);
  350. }
  351. int numClientOutputsProcessed = 0;
  352. // now go through each client
  353. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  354. {
  355. JackClientState* const jclient(it.getValue(nullptr));
  356. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  357. const CarlaMutexTryLocker cmtl2(jclient->mutex);
  358. // check if we can process
  359. if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
  360. {
  361. if (fNumPorts.audioOuts > 0)
  362. FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);
  363. if (jclient->deactivated)
  364. fShmRtClientControl.data->procFlags = 1;
  365. }
  366. else
  367. {
  368. uint32_t i;
  369. // direct access to shm buffer, used only for inputs
  370. float* fdataReal = fShmAudioPool.data;
  371. // safe temp location for output, mixed down to shm buffer later on
  372. float* fdataCopy = fAudioPoolCopy;
  373. // wherever we're using fAudioTmpBuf
  374. bool needsTmpBufClear = false;
  375. // set inputs
  376. i = 0;
  377. for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next())
  378. {
  379. if (JackPortState* const jport = it.getValue(nullptr))
  380. {
  381. if (i++ < fNumPorts.audioIns)
  382. {
  383. jport->buffer = fdataReal;
  384. fdataReal += fServer.bufferSize;
  385. fdataCopy += fServer.bufferSize;
  386. }
  387. else
  388. {
  389. jport->buffer = fAudioTmpBuf;
  390. needsTmpBufClear = true;
  391. }
  392. }
  393. }
  394. // FIXME one single "if"
  395. for (; i++ < fNumPorts.audioIns;)
  396. {
  397. fdataReal += fServer.bufferSize;
  398. fdataCopy += fServer.bufferSize;
  399. }
  400. // location to start of audio outputs
  401. float* const fdataCopyOuts = fdataCopy;
  402. // set ouputs
  403. i = 0;
  404. for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next())
  405. {
  406. if (JackPortState* const jport = it.getValue(nullptr))
  407. {
  408. if (i++ < fNumPorts.audioOuts)
  409. {
  410. jport->buffer = fdataCopy;
  411. fdataCopy += fServer.bufferSize;
  412. }
  413. else
  414. {
  415. jport->buffer = fAudioTmpBuf;
  416. needsTmpBufClear = true;
  417. }
  418. }
  419. }
  420. // FIXME one single "if"
  421. for (; i++ < fNumPorts.audioOuts;)
  422. {
  423. FloatVectorOperations::clear(fdataCopy, fServer.bufferSize);
  424. fdataCopy += fServer.bufferSize;
  425. }
  426. if (needsTmpBufClear)
  427. FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);
  428. jclient->processCb(fServer.bufferSize, jclient->processCbPtr);
  429. if (fNumPorts.audioOuts > 0)
  430. {
  431. if (++numClientOutputsProcessed == 1)
  432. {
  433. // first client, we can copy stuff over
  434. FloatVectorOperations::copy(fdataRealOuts, fdataCopyOuts,
  435. fServer.bufferSize*fNumPorts.audioOuts);
  436. }
  437. else
  438. {
  439. // subsequent clients, add data (then divide by number of clients later on)
  440. FloatVectorOperations::add(fdataRealOuts, fdataCopyOuts,
  441. fServer.bufferSize*fNumPorts.audioOuts);
  442. }
  443. }
  444. }
  445. }
  446. if (numClientOutputsProcessed > 1)
  447. {
  448. // more than 1 client active, need to divide buffers
  449. FloatVectorOperations::multiply(fdataRealOuts,
  450. 1.0f/static_cast<float>(numClientOutputsProcessed),
  451. fServer.bufferSize*fNumPorts.audioOuts);
  452. }
  453. }
  454. // fClients.isEmpty()
  455. else if (fNumPorts.audioOuts > 0)
  456. {
  457. FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);
  458. }
  459. if (fNumPorts.midiOuts > 0)
  460. carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);
  461. }
  462. else
  463. {
  464. carla_stderr2("CarlaJackAppClient: fRealtimeThreadMutex tryLock failed");
  465. }
  466. break;
  467. }
  468. case kPluginBridgeRtClientQuit:
  469. ret = true;
  470. break;
  471. }
  472. //#ifdef DEBUG
  473. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent)
  474. {
  475. carla_stdout("CarlaJackAppClientRtThread::run() - opcode %s done", PluginBridgeRtClientOpcode2str(opcode));
  476. }
  477. //#endif
  478. }
  479. return ret;
  480. }
  481. bool CarlaJackAppClient::handleNonRtData()
  482. {
  483. bool ret = false;
  484. for (; fShmNonRtClientControl.isDataAvailableForReading();)
  485. {
  486. const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode());
  487. // #ifdef DEBUG
  488. if (opcode != kPluginBridgeNonRtClientPing)
  489. {
  490. static int shownNull = 0;
  491. if (opcode == kPluginBridgeNonRtClientNull)
  492. {
  493. if (shownNull > 5)
  494. continue;
  495. ++shownNull;
  496. }
  497. carla_stdout("CarlaJackAppClient::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode));
  498. }
  499. // #endif
  500. if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0)
  501. fLastPingTime = Time::currentTimeMillis();
  502. switch (opcode)
  503. {
  504. case kPluginBridgeNonRtClientNull:
  505. break;
  506. case kPluginBridgeNonRtClientPing: {
  507. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  508. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  509. fShmNonRtServerControl.commitWrite();
  510. } break;
  511. case kPluginBridgeNonRtClientPingOnOff: {
  512. const uint32_t onOff(fShmNonRtClientControl.readBool());
  513. fLastPingTime = onOff ? Time::currentTimeMillis() : -1;
  514. } break;
  515. case kPluginBridgeNonRtClientActivate:
  516. case kPluginBridgeNonRtClientDeactivate:
  517. break;
  518. case kPluginBridgeNonRtClientSetBufferSize:
  519. if (const uint32_t newBufferSize = fShmNonRtClientControl.readUInt())
  520. {
  521. if (fServer.bufferSize != newBufferSize)
  522. {
  523. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  524. fServer.bufferSize = newBufferSize;
  525. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  526. {
  527. JackClientState* const jclient(it.getValue(nullptr));
  528. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  529. jclient->bufferSizeCb(fServer.bufferSize, jclient->bufferSizeCbPtr);
  530. }
  531. delete[] fAudioTmpBuf;
  532. fAudioTmpBuf = new float[fServer.bufferSize];
  533. FloatVectorOperations::clear(fAudioTmpBuf, fServer.bufferSize);
  534. }
  535. }
  536. break;
  537. case kPluginBridgeNonRtClientSetSampleRate:
  538. if (const double newSampleRate = fShmNonRtClientControl.readDouble())
  539. {
  540. if (fServer.sampleRate != newSampleRate)
  541. {
  542. const CarlaMutexLocker cml(fRealtimeThreadMutex);
  543. fServer.sampleRate = newSampleRate;
  544. for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
  545. {
  546. JackClientState* const jclient(it.getValue(nullptr));
  547. CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);
  548. jclient->sampleRateCb(fServer.sampleRate, jclient->sampleRateCbPtr);
  549. }
  550. }
  551. }
  552. break;
  553. case kPluginBridgeNonRtClientSetOffline:
  554. // TODO inform changes
  555. fIsOffline = true;
  556. //offlineModeChanged(true);
  557. break;
  558. case kPluginBridgeNonRtClientSetOnline:
  559. // TODO inform changes
  560. fIsOffline = false;
  561. //offlineModeChanged(false);
  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. // --------------------------------------------------------------------------------------------------------------------