jack.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include "jack.h"
  22. #include <array>
  23. #include <cstdlib>
  24. #include <cstdio>
  25. #include <cstring>
  26. #include <memory.h>
  27. #include <mutex>
  28. #include <thread>
  29. #include <functional>
  30. #include <vector>
  31. #include "alc/alconfig.h"
  32. #include "alnumeric.h"
  33. #include "alsem.h"
  34. #include "alstring.h"
  35. #include "althrd_setname.h"
  36. #include "core/device.h"
  37. #include "core/helpers.h"
  38. #include "core/logging.h"
  39. #include "dynload.h"
  40. #include "ringbuffer.h"
  41. #include <jack/jack.h>
  42. #include <jack/ringbuffer.h>
  43. namespace {
  44. using namespace std::string_view_literals;
  45. #ifdef HAVE_DYNLOAD
  46. #define JACK_FUNCS(MAGIC) \
  47. MAGIC(jack_client_open); \
  48. MAGIC(jack_client_close); \
  49. MAGIC(jack_client_name_size); \
  50. MAGIC(jack_get_client_name); \
  51. MAGIC(jack_connect); \
  52. MAGIC(jack_activate); \
  53. MAGIC(jack_deactivate); \
  54. MAGIC(jack_port_register); \
  55. MAGIC(jack_port_unregister); \
  56. MAGIC(jack_port_get_buffer); \
  57. MAGIC(jack_port_name); \
  58. MAGIC(jack_get_ports); \
  59. MAGIC(jack_free); \
  60. MAGIC(jack_get_sample_rate); \
  61. MAGIC(jack_set_error_function); \
  62. MAGIC(jack_set_process_callback); \
  63. MAGIC(jack_set_buffer_size_callback); \
  64. MAGIC(jack_set_buffer_size); \
  65. MAGIC(jack_get_buffer_size);
  66. void *jack_handle;
  67. #define MAKE_FUNC(f) decltype(f) * p##f
  68. JACK_FUNCS(MAKE_FUNC)
  69. decltype(jack_error_callback) * pjack_error_callback;
  70. #undef MAKE_FUNC
  71. #ifndef IN_IDE_PARSER
  72. #define jack_client_open pjack_client_open
  73. #define jack_client_close pjack_client_close
  74. #define jack_client_name_size pjack_client_name_size
  75. #define jack_get_client_name pjack_get_client_name
  76. #define jack_connect pjack_connect
  77. #define jack_activate pjack_activate
  78. #define jack_deactivate pjack_deactivate
  79. #define jack_port_register pjack_port_register
  80. #define jack_port_unregister pjack_port_unregister
  81. #define jack_port_get_buffer pjack_port_get_buffer
  82. #define jack_port_name pjack_port_name
  83. #define jack_get_ports pjack_get_ports
  84. #define jack_free pjack_free
  85. #define jack_get_sample_rate pjack_get_sample_rate
  86. #define jack_set_error_function pjack_set_error_function
  87. #define jack_set_process_callback pjack_set_process_callback
  88. #define jack_set_buffer_size_callback pjack_set_buffer_size_callback
  89. #define jack_set_buffer_size pjack_set_buffer_size
  90. #define jack_get_buffer_size pjack_get_buffer_size
  91. #define jack_error_callback (*pjack_error_callback)
  92. #endif
  93. #endif
  94. jack_options_t ClientOptions = JackNullOption;
  95. bool jack_load()
  96. {
  97. #ifdef HAVE_DYNLOAD
  98. if(!jack_handle)
  99. {
  100. #ifdef _WIN32
  101. #define JACKLIB "libjack.dll"
  102. #else
  103. #define JACKLIB "libjack.so.0"
  104. #endif
  105. jack_handle = LoadLib(JACKLIB);
  106. if(!jack_handle)
  107. {
  108. WARN("Failed to load %s\n", JACKLIB);
  109. return false;
  110. }
  111. std::string missing_funcs;
  112. #define LOAD_FUNC(f) do { \
  113. p##f = reinterpret_cast<decltype(p##f)>(GetSymbol(jack_handle, #f)); \
  114. if(p##f == nullptr) missing_funcs += "\n" #f; \
  115. } while(0)
  116. JACK_FUNCS(LOAD_FUNC);
  117. #undef LOAD_FUNC
  118. /* Optional symbols. These don't exist in all versions of JACK. */
  119. #define LOAD_SYM(f) p##f = reinterpret_cast<decltype(p##f)>(GetSymbol(jack_handle, #f))
  120. LOAD_SYM(jack_error_callback);
  121. #undef LOAD_SYM
  122. if(!missing_funcs.empty())
  123. {
  124. WARN("Missing expected functions:%s\n", missing_funcs.c_str());
  125. CloseLib(jack_handle);
  126. jack_handle = nullptr;
  127. return false;
  128. }
  129. }
  130. #endif
  131. return true;
  132. }
  133. struct JackDeleter {
  134. void operator()(void *ptr) { jack_free(ptr); }
  135. };
  136. using JackPortsPtr = std::unique_ptr<const char*[],JackDeleter>; /* NOLINT(*-avoid-c-arrays) */
  137. struct DeviceEntry {
  138. std::string mName;
  139. std::string mPattern;
  140. DeviceEntry() = default;
  141. DeviceEntry(const DeviceEntry&) = default;
  142. DeviceEntry(DeviceEntry&&) = default;
  143. template<typename T, typename U>
  144. DeviceEntry(T&& name, U&& pattern)
  145. : mName{std::forward<T>(name)}, mPattern{std::forward<U>(pattern)}
  146. { }
  147. ~DeviceEntry();
  148. DeviceEntry& operator=(const DeviceEntry&) = default;
  149. DeviceEntry& operator=(DeviceEntry&&) = default;
  150. };
  151. DeviceEntry::~DeviceEntry() = default;
  152. std::vector<DeviceEntry> PlaybackList;
  153. void EnumerateDevices(jack_client_t *client, std::vector<DeviceEntry> &list)
  154. {
  155. std::remove_reference_t<decltype(list)>{}.swap(list);
  156. if(JackPortsPtr ports{jack_get_ports(client, nullptr, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput)})
  157. {
  158. for(size_t i{0};ports[i];++i)
  159. {
  160. const std::string_view portname{ports[i]};
  161. const size_t seppos{portname.find(':')};
  162. if(seppos == 0 || seppos >= portname.size())
  163. continue;
  164. const auto portdev = portname.substr(0, seppos);
  165. auto check_name = [portdev](const DeviceEntry &entry) -> bool
  166. { return entry.mName == portdev; };
  167. if(std::find_if(list.cbegin(), list.cend(), check_name) != list.cend())
  168. continue;
  169. const auto &entry = list.emplace_back(portdev, std::string{portdev}+":");
  170. TRACE("Got device: %s = %s\n", entry.mName.c_str(), entry.mPattern.c_str());
  171. }
  172. /* There are ports but couldn't get device names from them. Add a
  173. * generic entry.
  174. */
  175. if(ports[0] && list.empty())
  176. {
  177. WARN("No device names found in available ports, adding a generic name.\n");
  178. list.emplace_back("JACK"sv, ""sv);
  179. }
  180. }
  181. if(auto listopt = ConfigValueStr({}, "jack", "custom-devices"))
  182. {
  183. for(size_t strpos{0};strpos < listopt->size();)
  184. {
  185. size_t nextpos{listopt->find(';', strpos)};
  186. size_t seppos{listopt->find('=', strpos)};
  187. if(seppos >= nextpos || seppos == strpos)
  188. {
  189. const auto entry = std::string_view{*listopt}.substr(strpos, nextpos-strpos);
  190. ERR("Invalid device entry: \"%.*s\"\n", al::sizei(entry), entry.data());
  191. if(nextpos != std::string::npos) ++nextpos;
  192. strpos = nextpos;
  193. continue;
  194. }
  195. const auto name = std::string_view{*listopt}.substr(strpos, seppos-strpos);
  196. const auto pattern = std::string_view{*listopt}.substr(seppos+1,
  197. std::min(nextpos, listopt->size())-(seppos+1));
  198. /* Check if this custom pattern already exists in the list. */
  199. auto check_pattern = [pattern](const DeviceEntry &entry) -> bool
  200. { return entry.mPattern == pattern; };
  201. auto itemmatch = std::find_if(list.begin(), list.end(), check_pattern);
  202. if(itemmatch != list.end())
  203. {
  204. /* If so, replace the name with this custom one. */
  205. itemmatch->mName = name;
  206. TRACE("Customized device name: %s = %s\n", itemmatch->mName.c_str(),
  207. itemmatch->mPattern.c_str());
  208. }
  209. else
  210. {
  211. /* Otherwise, add a new device entry. */
  212. const auto &entry = list.emplace_back(name, pattern);
  213. TRACE("Got custom device: %s = %s\n", entry.mName.c_str(), entry.mPattern.c_str());
  214. }
  215. if(nextpos != std::string::npos) ++nextpos;
  216. strpos = nextpos;
  217. }
  218. }
  219. if(list.size() > 1)
  220. {
  221. /* Rename entries that have matching names, by appending '#2', '#3',
  222. * etc, as needed.
  223. */
  224. for(auto curitem = list.begin()+1;curitem != list.end();++curitem)
  225. {
  226. auto check_match = [curitem](const DeviceEntry &entry) -> bool
  227. { return entry.mName == curitem->mName; };
  228. if(std::find_if(list.begin(), curitem, check_match) != curitem)
  229. {
  230. std::string name{curitem->mName};
  231. size_t count{1};
  232. auto check_name = [&name](const DeviceEntry &entry) -> bool
  233. { return entry.mName == name; };
  234. do {
  235. name = curitem->mName;
  236. name += " #";
  237. name += std::to_string(++count);
  238. } while(std::find_if(list.begin(), curitem, check_name) != curitem);
  239. curitem->mName = std::move(name);
  240. }
  241. }
  242. }
  243. }
  244. struct JackPlayback final : public BackendBase {
  245. JackPlayback(DeviceBase *device) noexcept : BackendBase{device} { }
  246. ~JackPlayback() override;
  247. int processRt(jack_nframes_t numframes) noexcept;
  248. static int processRtC(jack_nframes_t numframes, void *arg) noexcept
  249. { return static_cast<JackPlayback*>(arg)->processRt(numframes); }
  250. int process(jack_nframes_t numframes) noexcept;
  251. static int processC(jack_nframes_t numframes, void *arg) noexcept
  252. { return static_cast<JackPlayback*>(arg)->process(numframes); }
  253. int mixerProc();
  254. void open(std::string_view name) override;
  255. bool reset() override;
  256. void start() override;
  257. void stop() override;
  258. ClockLatency getClockLatency() override;
  259. std::string mPortPattern;
  260. jack_client_t *mClient{nullptr};
  261. std::array<jack_port_t*,MaxOutputChannels> mPort{};
  262. std::mutex mMutex;
  263. std::atomic<bool> mPlaying{false};
  264. bool mRTMixing{false};
  265. RingBufferPtr mRing;
  266. al::semaphore mSem;
  267. std::atomic<bool> mKillNow{true};
  268. std::thread mThread;
  269. };
  270. JackPlayback::~JackPlayback()
  271. {
  272. if(!mClient)
  273. return;
  274. auto unregister_port = [this](jack_port_t *port) -> void
  275. { if(port) jack_port_unregister(mClient, port); };
  276. std::for_each(mPort.begin(), mPort.end(), unregister_port);
  277. mPort.fill(nullptr);
  278. jack_client_close(mClient);
  279. mClient = nullptr;
  280. }
  281. int JackPlayback::processRt(jack_nframes_t numframes) noexcept
  282. {
  283. auto outptrs = std::array<jack_default_audio_sample_t*,MaxOutputChannels>{};
  284. auto numchans = size_t{0};
  285. for(auto port : mPort)
  286. {
  287. if(!port || numchans == mDevice->RealOut.Buffer.size())
  288. break;
  289. outptrs[numchans++] = static_cast<float*>(jack_port_get_buffer(port, numframes));
  290. }
  291. const auto dst = al::span{outptrs}.first(numchans);
  292. if(mPlaying.load(std::memory_order_acquire)) LIKELY
  293. mDevice->renderSamples(dst, static_cast<uint>(numframes));
  294. else
  295. {
  296. std::for_each(dst.begin(), dst.end(), [numframes](float *outbuf) -> void
  297. { std::fill_n(outbuf, numframes, 0.0f); });
  298. }
  299. return 0;
  300. }
  301. int JackPlayback::process(jack_nframes_t numframes) noexcept
  302. {
  303. std::array<al::span<float>,MaxOutputChannels> out;
  304. size_t numchans{0};
  305. for(auto port : mPort)
  306. {
  307. if(!port) break;
  308. out[numchans++] = {static_cast<float*>(jack_port_get_buffer(port, numframes)), numframes};
  309. }
  310. size_t total{0};
  311. if(mPlaying.load(std::memory_order_acquire)) LIKELY
  312. {
  313. auto data = mRing->getReadVector();
  314. const auto update_size = size_t{mDevice->UpdateSize};
  315. const auto outlen = size_t{numframes / update_size};
  316. const auto len1 = size_t{std::min(data.first.len/update_size, outlen)};
  317. const auto len2 = size_t{std::min(data.second.len/update_size, outlen-len1)};
  318. auto src = al::span{reinterpret_cast<float*>(data.first.buf), update_size*len1*numchans};
  319. for(size_t i{0};i < len1;++i)
  320. {
  321. for(size_t c{0};c < numchans;++c)
  322. {
  323. const auto iter = std::copy_n(src.begin(), update_size, out[c].begin());
  324. out[c] = {iter, out[c].end()};
  325. src = src.subspan(update_size);
  326. }
  327. total += update_size;
  328. }
  329. src = al::span{reinterpret_cast<float*>(data.second.buf), update_size*len2*numchans};
  330. for(size_t i{0};i < len2;++i)
  331. {
  332. for(size_t c{0};c < numchans;++c)
  333. {
  334. const auto iter = std::copy_n(src.begin(), update_size, out[c].begin());
  335. out[c] = {iter, out[c].end()};
  336. src = src.subspan(update_size);
  337. }
  338. total += update_size;
  339. }
  340. mRing->readAdvance(total);
  341. mSem.post();
  342. }
  343. if(numframes > total)
  344. {
  345. auto clear_buf = [](const al::span<float> outbuf) -> void
  346. { std::fill(outbuf.begin(), outbuf.end(), 0.0f); };
  347. std::for_each(out.begin(), out.begin()+numchans, clear_buf);
  348. }
  349. return 0;
  350. }
  351. int JackPlayback::mixerProc()
  352. {
  353. SetRTPriority();
  354. althrd_setname(GetMixerThreadName());
  355. const auto update_size = uint{mDevice->UpdateSize};
  356. const auto num_channels = size_t{mDevice->channelsFromFmt()};
  357. auto outptrs = std::vector<float*>(num_channels);
  358. while(!mKillNow.load(std::memory_order_acquire)
  359. && mDevice->Connected.load(std::memory_order_acquire))
  360. {
  361. if(mRing->writeSpace() < update_size)
  362. {
  363. mSem.wait();
  364. continue;
  365. }
  366. auto data = mRing->getWriteVector();
  367. const auto len1 = size_t{data.first.len / update_size};
  368. const auto len2 = size_t{data.second.len / update_size};
  369. std::lock_guard<std::mutex> dlock{mMutex};
  370. auto buffer = al::span{reinterpret_cast<float*>(data.first.buf),
  371. data.first.len*num_channels};
  372. auto bufiter = buffer.begin();
  373. for(size_t i{0};i < len1;++i)
  374. {
  375. std::generate_n(outptrs.begin(), outptrs.size(), [&bufiter,update_size]
  376. {
  377. auto ret = al::to_address(bufiter);
  378. bufiter += ptrdiff_t(update_size);
  379. return ret;
  380. });
  381. mDevice->renderSamples(outptrs, update_size);
  382. }
  383. if(len2 > 0)
  384. {
  385. buffer = al::span{reinterpret_cast<float*>(data.second.buf),
  386. data.second.len*num_channels};
  387. bufiter = buffer.begin();
  388. for(size_t i{0};i < len2;++i)
  389. {
  390. std::generate_n(outptrs.begin(), outptrs.size(), [&bufiter,update_size]
  391. {
  392. auto ret = al::to_address(bufiter);
  393. bufiter += ptrdiff_t(update_size);
  394. return ret;
  395. });
  396. mDevice->renderSamples(outptrs, update_size);
  397. }
  398. }
  399. mRing->writeAdvance((len1+len2) * update_size);
  400. }
  401. return 0;
  402. }
  403. void JackPlayback::open(std::string_view name)
  404. {
  405. if(!mClient)
  406. {
  407. const PathNamePair &binname = GetProcBinary();
  408. const char *client_name{binname.fname.empty() ? "alsoft" : binname.fname.c_str()};
  409. jack_status_t status{};
  410. mClient = jack_client_open(client_name, ClientOptions, &status, nullptr);
  411. if(mClient == nullptr)
  412. throw al::backend_exception{al::backend_error::DeviceError,
  413. "Failed to open client connection: 0x%02x", status};
  414. if((status&JackServerStarted))
  415. TRACE("JACK server started\n");
  416. if((status&JackNameNotUnique))
  417. {
  418. client_name = jack_get_client_name(mClient);
  419. TRACE("Client name not unique, got '%s' instead\n", client_name);
  420. }
  421. }
  422. if(PlaybackList.empty())
  423. EnumerateDevices(mClient, PlaybackList);
  424. if(name.empty() && !PlaybackList.empty())
  425. {
  426. name = PlaybackList[0].mName;
  427. mPortPattern = PlaybackList[0].mPattern;
  428. }
  429. else
  430. {
  431. auto check_name = [name](const DeviceEntry &entry) -> bool
  432. { return entry.mName == name; };
  433. auto iter = std::find_if(PlaybackList.cbegin(), PlaybackList.cend(), check_name);
  434. if(iter == PlaybackList.cend())
  435. throw al::backend_exception{al::backend_error::NoDevice,
  436. "Device name \"%.*s\" not found", al::sizei(name), name.data()};
  437. mPortPattern = iter->mPattern;
  438. }
  439. mDevice->DeviceName = name;
  440. }
  441. bool JackPlayback::reset()
  442. {
  443. auto unregister_port = [this](jack_port_t *port) -> void
  444. { if(port) jack_port_unregister(mClient, port); };
  445. std::for_each(mPort.begin(), mPort.end(), unregister_port);
  446. mPort.fill(nullptr);
  447. mRTMixing = GetConfigValueBool(mDevice->DeviceName, "jack", "rt-mix", true);
  448. jack_set_process_callback(mClient,
  449. mRTMixing ? &JackPlayback::processRtC : &JackPlayback::processC, this);
  450. /* Ignore the requested buffer metrics and just keep one JACK-sized buffer
  451. * ready for when requested.
  452. */
  453. mDevice->Frequency = jack_get_sample_rate(mClient);
  454. mDevice->UpdateSize = jack_get_buffer_size(mClient);
  455. if(mRTMixing)
  456. {
  457. /* Assume only two periods when directly mixing. Should try to query
  458. * the total port latency when connected.
  459. */
  460. mDevice->BufferSize = mDevice->UpdateSize * 2;
  461. }
  462. else
  463. {
  464. const std::string_view devname{mDevice->DeviceName};
  465. uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size").value_or(mDevice->UpdateSize)};
  466. bufsize = std::max(NextPowerOf2(bufsize), mDevice->UpdateSize);
  467. mDevice->BufferSize = bufsize + mDevice->UpdateSize;
  468. }
  469. /* Force 32-bit float output. */
  470. mDevice->FmtType = DevFmtFloat;
  471. int port_num{0};
  472. auto ports = al::span{mPort}.first(mDevice->channelsFromFmt());
  473. auto bad_port = ports.begin();
  474. while(bad_port != ports.end())
  475. {
  476. std::string name{"channel_" + std::to_string(++port_num)};
  477. *bad_port = jack_port_register(mClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE,
  478. JackPortIsOutput | JackPortIsTerminal, 0);
  479. if(!*bad_port) break;
  480. ++bad_port;
  481. }
  482. if(bad_port != ports.end())
  483. {
  484. ERR("Failed to register enough JACK ports for %s output\n",
  485. DevFmtChannelsString(mDevice->FmtChans));
  486. if(bad_port == ports.begin()) return false;
  487. if(bad_port == ports.begin()+1)
  488. mDevice->FmtChans = DevFmtMono;
  489. else
  490. {
  491. const auto ports_end = ports.begin()+2;
  492. while(bad_port != ports_end)
  493. {
  494. jack_port_unregister(mClient, *(--bad_port));
  495. *bad_port = nullptr;
  496. }
  497. mDevice->FmtChans = DevFmtStereo;
  498. }
  499. }
  500. setDefaultChannelOrder();
  501. return true;
  502. }
  503. void JackPlayback::start()
  504. {
  505. if(jack_activate(mClient))
  506. throw al::backend_exception{al::backend_error::DeviceError, "Failed to activate client"};
  507. const std::string_view devname{mDevice->DeviceName};
  508. if(ConfigValueBool(devname, "jack", "connect-ports").value_or(true))
  509. {
  510. JackPortsPtr pnames{jack_get_ports(mClient, mPortPattern.c_str(), JACK_DEFAULT_AUDIO_TYPE,
  511. JackPortIsInput)};
  512. if(!pnames)
  513. {
  514. jack_deactivate(mClient);
  515. throw al::backend_exception{al::backend_error::DeviceError, "No playback ports found"};
  516. }
  517. for(size_t i{0};i < std::size(mPort) && mPort[i];++i)
  518. {
  519. if(!pnames[i])
  520. {
  521. ERR("No physical playback port for \"%s\"\n", jack_port_name(mPort[i]));
  522. break;
  523. }
  524. if(jack_connect(mClient, jack_port_name(mPort[i]), pnames[i]))
  525. ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(mPort[i]),
  526. pnames[i]);
  527. }
  528. }
  529. /* Reconfigure buffer metrics in case the server changed it since the reset
  530. * (it won't change again after jack_activate), then allocate the ring
  531. * buffer with the appropriate size.
  532. */
  533. mDevice->Frequency = jack_get_sample_rate(mClient);
  534. mDevice->UpdateSize = jack_get_buffer_size(mClient);
  535. mDevice->BufferSize = mDevice->UpdateSize * 2;
  536. mRing = nullptr;
  537. if(mRTMixing)
  538. mPlaying.store(true, std::memory_order_release);
  539. else
  540. {
  541. uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size").value_or(mDevice->UpdateSize)};
  542. bufsize = std::max(NextPowerOf2(bufsize), mDevice->UpdateSize);
  543. mDevice->BufferSize = bufsize + mDevice->UpdateSize;
  544. mRing = RingBuffer::Create(bufsize, mDevice->frameSizeFromFmt(), true);
  545. try {
  546. mPlaying.store(true, std::memory_order_release);
  547. mKillNow.store(false, std::memory_order_release);
  548. mThread = std::thread{std::mem_fn(&JackPlayback::mixerProc), this};
  549. }
  550. catch(std::exception& e) {
  551. jack_deactivate(mClient);
  552. mPlaying.store(false, std::memory_order_release);
  553. throw al::backend_exception{al::backend_error::DeviceError,
  554. "Failed to start mixing thread: %s", e.what()};
  555. }
  556. }
  557. }
  558. void JackPlayback::stop()
  559. {
  560. if(mPlaying.load(std::memory_order_acquire))
  561. {
  562. mKillNow.store(true, std::memory_order_release);
  563. if(mThread.joinable())
  564. {
  565. mSem.post();
  566. mThread.join();
  567. }
  568. jack_deactivate(mClient);
  569. mPlaying.store(false, std::memory_order_release);
  570. }
  571. }
  572. ClockLatency JackPlayback::getClockLatency()
  573. {
  574. std::lock_guard<std::mutex> dlock{mMutex};
  575. ClockLatency ret{};
  576. ret.ClockTime = mDevice->getClockTime();
  577. ret.Latency = std::chrono::seconds{mRing ? mRing->readSpace() : mDevice->UpdateSize};
  578. ret.Latency /= mDevice->Frequency;
  579. return ret;
  580. }
  581. void jack_msg_handler(const char *message)
  582. {
  583. WARN("%s\n", message);
  584. }
  585. } // namespace
  586. bool JackBackendFactory::init()
  587. {
  588. if(!jack_load())
  589. return false;
  590. if(!GetConfigValueBool({}, "jack", "spawn-server", false))
  591. ClientOptions = static_cast<jack_options_t>(ClientOptions | JackNoStartServer);
  592. const PathNamePair &binname = GetProcBinary();
  593. const char *client_name{binname.fname.empty() ? "alsoft" : binname.fname.c_str()};
  594. void (*old_error_cb)(const char*){&jack_error_callback ? jack_error_callback : nullptr};
  595. jack_set_error_function(jack_msg_handler);
  596. jack_status_t status{};
  597. jack_client_t *client{jack_client_open(client_name, ClientOptions, &status, nullptr)};
  598. jack_set_error_function(old_error_cb);
  599. if(!client)
  600. {
  601. WARN("jack_client_open() failed, 0x%02x\n", status);
  602. if((status&JackServerFailed) && !(ClientOptions&JackNoStartServer))
  603. ERR("Unable to connect to JACK server\n");
  604. return false;
  605. }
  606. jack_client_close(client);
  607. return true;
  608. }
  609. bool JackBackendFactory::querySupport(BackendType type)
  610. { return (type == BackendType::Playback); }
  611. auto JackBackendFactory::enumerate(BackendType type) -> std::vector<std::string>
  612. {
  613. std::vector<std::string> outnames;
  614. auto append_name = [&outnames](const DeviceEntry &entry) -> void
  615. { outnames.emplace_back(entry.mName); };
  616. const PathNamePair &binname = GetProcBinary();
  617. const char *client_name{binname.fname.empty() ? "alsoft" : binname.fname.c_str()};
  618. jack_status_t status{};
  619. switch(type)
  620. {
  621. case BackendType::Playback:
  622. if(jack_client_t *client{jack_client_open(client_name, ClientOptions, &status, nullptr)})
  623. {
  624. EnumerateDevices(client, PlaybackList);
  625. jack_client_close(client);
  626. }
  627. else
  628. WARN("jack_client_open() failed, 0x%02x\n", status);
  629. outnames.reserve(PlaybackList.size());
  630. std::for_each(PlaybackList.cbegin(), PlaybackList.cend(), append_name);
  631. break;
  632. case BackendType::Capture:
  633. break;
  634. }
  635. return outnames;
  636. }
  637. BackendPtr JackBackendFactory::createBackend(DeviceBase *device, BackendType type)
  638. {
  639. if(type == BackendType::Playback)
  640. return BackendPtr{new JackPlayback{device}};
  641. return nullptr;
  642. }
  643. BackendFactory &JackBackendFactory::getFactory()
  644. {
  645. static JackBackendFactory factory{};
  646. return factory;
  647. }