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.

832 lines
29KB

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