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.

798 lines
27KB

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