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.

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