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.

1024 lines
34KB

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