jack.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  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 "backends/jack.h"
  22. #include <cstdlib>
  23. #include <cstdio>
  24. #include <cstring>
  25. #include <memory.h>
  26. #include <array>
  27. #include <thread>
  28. #include <functional>
  29. #include "alcmain.h"
  30. #include "alu.h"
  31. #include "alconfig.h"
  32. #include "core/logging.h"
  33. #include "dynload.h"
  34. #include "ringbuffer.h"
  35. #include "threads.h"
  36. #include <jack/jack.h>
  37. #include <jack/ringbuffer.h>
  38. namespace {
  39. constexpr char jackDevice[] = "JACK Default";
  40. #ifdef HAVE_DYNLOAD
  41. #define JACK_FUNCS(MAGIC) \
  42. MAGIC(jack_client_open); \
  43. MAGIC(jack_client_close); \
  44. MAGIC(jack_client_name_size); \
  45. MAGIC(jack_get_client_name); \
  46. MAGIC(jack_connect); \
  47. MAGIC(jack_activate); \
  48. MAGIC(jack_deactivate); \
  49. MAGIC(jack_port_register); \
  50. MAGIC(jack_port_unregister); \
  51. MAGIC(jack_port_get_buffer); \
  52. MAGIC(jack_port_name); \
  53. MAGIC(jack_get_ports); \
  54. MAGIC(jack_free); \
  55. MAGIC(jack_get_sample_rate); \
  56. MAGIC(jack_set_error_function); \
  57. MAGIC(jack_set_process_callback); \
  58. MAGIC(jack_set_buffer_size_callback); \
  59. MAGIC(jack_set_buffer_size); \
  60. MAGIC(jack_get_buffer_size);
  61. void *jack_handle;
  62. #define MAKE_FUNC(f) decltype(f) * p##f
  63. JACK_FUNCS(MAKE_FUNC)
  64. decltype(jack_error_callback) * pjack_error_callback;
  65. #undef MAKE_FUNC
  66. #ifndef IN_IDE_PARSER
  67. #define jack_client_open pjack_client_open
  68. #define jack_client_close pjack_client_close
  69. #define jack_client_name_size pjack_client_name_size
  70. #define jack_get_client_name pjack_get_client_name
  71. #define jack_connect pjack_connect
  72. #define jack_activate pjack_activate
  73. #define jack_deactivate pjack_deactivate
  74. #define jack_port_register pjack_port_register
  75. #define jack_port_unregister pjack_port_unregister
  76. #define jack_port_get_buffer pjack_port_get_buffer
  77. #define jack_port_name pjack_port_name
  78. #define jack_get_ports pjack_get_ports
  79. #define jack_free pjack_free
  80. #define jack_get_sample_rate pjack_get_sample_rate
  81. #define jack_set_error_function pjack_set_error_function
  82. #define jack_set_process_callback pjack_set_process_callback
  83. #define jack_set_buffer_size_callback pjack_set_buffer_size_callback
  84. #define jack_set_buffer_size pjack_set_buffer_size
  85. #define jack_get_buffer_size pjack_get_buffer_size
  86. #define jack_error_callback (*pjack_error_callback)
  87. #endif
  88. #endif
  89. jack_options_t ClientOptions = JackNullOption;
  90. bool jack_load()
  91. {
  92. bool error{false};
  93. #ifdef HAVE_DYNLOAD
  94. if(!jack_handle)
  95. {
  96. std::string missing_funcs;
  97. #ifdef _WIN32
  98. #define JACKLIB "libjack.dll"
  99. #else
  100. #define JACKLIB "libjack.so.0"
  101. #endif
  102. jack_handle = LoadLib(JACKLIB);
  103. if(!jack_handle)
  104. {
  105. WARN("Failed to load %s\n", JACKLIB);
  106. return false;
  107. }
  108. error = false;
  109. #define LOAD_FUNC(f) do { \
  110. p##f = reinterpret_cast<decltype(p##f)>(GetSymbol(jack_handle, #f)); \
  111. if(p##f == nullptr) { \
  112. error = true; \
  113. missing_funcs += "\n" #f; \
  114. } \
  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(error)
  123. {
  124. WARN("Missing expected functions:%s\n", missing_funcs.c_str());
  125. CloseLib(jack_handle);
  126. jack_handle = nullptr;
  127. }
  128. }
  129. #endif
  130. return !error;
  131. }
  132. struct DeviceEntry {
  133. std::string mName;
  134. std::string mPattern;
  135. };
  136. al::vector<DeviceEntry> PlaybackList;
  137. void EnumerateDevices(al::vector<DeviceEntry> &list)
  138. {
  139. al::vector<DeviceEntry>{}.swap(list);
  140. list.emplace_back(DeviceEntry{jackDevice, ""});
  141. std::string customList{ConfigValueStr(nullptr, "jack", "custom-devices").value_or("")};
  142. size_t strpos{0};
  143. while(strpos < customList.size())
  144. {
  145. size_t nextpos{customList.find(';', strpos)};
  146. size_t seppos{customList.find('=', strpos)};
  147. if(seppos >= nextpos || seppos == strpos)
  148. {
  149. const std::string entry{customList.substr(strpos, nextpos-strpos)};
  150. ERR("Invalid device entry: \"%s\"\n", entry.c_str());
  151. if(nextpos != std::string::npos) ++nextpos;
  152. strpos = nextpos;
  153. continue;
  154. }
  155. size_t count{1};
  156. std::string name{customList.substr(strpos, seppos-strpos)};
  157. auto check_name = [&name](const DeviceEntry &entry) -> bool
  158. { return entry.mName == name; };
  159. while(std::find_if(list.cbegin(), list.cend(), check_name) != list.cend())
  160. {
  161. name = customList.substr(strpos, seppos-strpos);
  162. name += " #";
  163. name += std::to_string(++count);
  164. }
  165. ++seppos;
  166. list.emplace_back(DeviceEntry{std::move(name), customList.substr(seppos, nextpos-seppos)});
  167. const auto &entry = list.back();
  168. TRACE("Got custom device: %s = %s\n", entry.mName.c_str(), entry.mPattern.c_str());
  169. if(nextpos != std::string::npos) ++nextpos;
  170. strpos = nextpos;
  171. }
  172. }
  173. struct JackPlayback final : public BackendBase {
  174. JackPlayback(ALCdevice *device) noexcept : BackendBase{device} { }
  175. ~JackPlayback() override;
  176. int process(jack_nframes_t numframes) noexcept;
  177. static int processC(jack_nframes_t numframes, void *arg) noexcept
  178. { return static_cast<JackPlayback*>(arg)->process(numframes); }
  179. int mixerProc();
  180. void open(const char *name) override;
  181. bool reset() override;
  182. void start() override;
  183. void stop() override;
  184. ClockLatency getClockLatency() override;
  185. std::string mPortPattern;
  186. jack_client_t *mClient{nullptr};
  187. std::array<jack_port_t*,MAX_OUTPUT_CHANNELS> mPort{};
  188. std::mutex mMutex;
  189. std::atomic<bool> mPlaying{false};
  190. RingBufferPtr mRing;
  191. al::semaphore mSem;
  192. std::atomic<bool> mKillNow{true};
  193. std::thread mThread;
  194. DEF_NEWDEL(JackPlayback)
  195. };
  196. JackPlayback::~JackPlayback()
  197. {
  198. if(!mClient)
  199. return;
  200. std::for_each(mPort.begin(), mPort.end(),
  201. [this](jack_port_t *port) -> void
  202. { if(port) jack_port_unregister(mClient, port); }
  203. );
  204. mPort.fill(nullptr);
  205. jack_client_close(mClient);
  206. mClient = nullptr;
  207. }
  208. int JackPlayback::process(jack_nframes_t numframes) noexcept
  209. {
  210. std::array<jack_default_audio_sample_t*,MAX_OUTPUT_CHANNELS> out;
  211. size_t numchans{0};
  212. for(auto port : mPort)
  213. {
  214. if(!port) break;
  215. out[numchans++] = static_cast<float*>(jack_port_get_buffer(port, numframes));
  216. }
  217. jack_nframes_t total{0};
  218. if LIKELY(mPlaying.load(std::memory_order_acquire))
  219. {
  220. auto data = mRing->getReadVector();
  221. jack_nframes_t todo{minu(numframes, static_cast<uint>(data.first.len))};
  222. auto write_first = [&data,numchans,todo](float *outbuf) -> float*
  223. {
  224. const float *RESTRICT in = reinterpret_cast<float*>(data.first.buf);
  225. auto deinterlace_input = [&in,numchans]() noexcept -> float
  226. {
  227. float ret{*in};
  228. in += numchans;
  229. return ret;
  230. };
  231. std::generate_n(outbuf, todo, deinterlace_input);
  232. data.first.buf += sizeof(float);
  233. return outbuf + todo;
  234. };
  235. std::transform(out.begin(), out.begin()+numchans, out.begin(), write_first);
  236. total += todo;
  237. todo = minu(numframes-total, static_cast<uint>(data.second.len));
  238. if(todo > 0)
  239. {
  240. auto write_second = [&data,numchans,todo](float *outbuf) -> float*
  241. {
  242. const float *RESTRICT in = reinterpret_cast<float*>(data.second.buf);
  243. auto deinterlace_input = [&in,numchans]() noexcept -> float
  244. {
  245. float ret{*in};
  246. in += numchans;
  247. return ret;
  248. };
  249. std::generate_n(outbuf, todo, deinterlace_input);
  250. data.second.buf += sizeof(float);
  251. return outbuf + todo;
  252. };
  253. std::transform(out.begin(), out.begin()+numchans, out.begin(), write_second);
  254. total += todo;
  255. }
  256. mRing->readAdvance(total);
  257. mSem.post();
  258. }
  259. if(numframes > total)
  260. {
  261. const jack_nframes_t todo{numframes - total};
  262. auto clear_buf = [todo](float *outbuf) -> void { std::fill_n(outbuf, todo, 0.0f); };
  263. std::for_each(out.begin(), out.begin()+numchans, clear_buf);
  264. }
  265. return 0;
  266. }
  267. int JackPlayback::mixerProc()
  268. {
  269. SetRTPriority();
  270. althrd_setname(MIXER_THREAD_NAME);
  271. const size_t frame_step{mDevice->channelsFromFmt()};
  272. while(!mKillNow.load(std::memory_order_acquire)
  273. && mDevice->Connected.load(std::memory_order_acquire))
  274. {
  275. if(mRing->writeSpace() < mDevice->UpdateSize)
  276. {
  277. mSem.wait();
  278. continue;
  279. }
  280. auto data = mRing->getWriteVector();
  281. size_t todo{data.first.len + data.second.len};
  282. todo -= todo%mDevice->UpdateSize;
  283. const auto len1 = static_cast<uint>(minz(data.first.len, todo));
  284. const auto len2 = static_cast<uint>(minz(data.second.len, todo-len1));
  285. std::lock_guard<std::mutex> _{mMutex};
  286. mDevice->renderSamples(data.first.buf, len1, frame_step);
  287. if(len2 > 0)
  288. mDevice->renderSamples(data.second.buf, len2, frame_step);
  289. mRing->writeAdvance(todo);
  290. }
  291. return 0;
  292. }
  293. void JackPlayback::open(const char *name)
  294. {
  295. mPortPattern.clear();
  296. if(!name)
  297. name = jackDevice;
  298. else if(strcmp(name, jackDevice) != 0)
  299. {
  300. if(PlaybackList.empty())
  301. EnumerateDevices(PlaybackList);
  302. auto check_name = [name](const DeviceEntry &entry) -> bool
  303. { return entry.mName == name; };
  304. auto iter = std::find_if(PlaybackList.cbegin(), PlaybackList.cend(), check_name);
  305. if(iter == PlaybackList.cend())
  306. throw al::backend_exception{al::backend_error::NoDevice,
  307. "Device name \"%s\" not found", name};
  308. mPortPattern = iter->mPattern;
  309. }
  310. const char *client_name{"alsoft"};
  311. jack_status_t status;
  312. mClient = jack_client_open(client_name, ClientOptions, &status, nullptr);
  313. if(mClient == nullptr)
  314. throw al::backend_exception{al::backend_error::DeviceError,
  315. "Failed to open client connection: 0x%02x", status};
  316. if((status&JackServerStarted))
  317. TRACE("JACK server started\n");
  318. if((status&JackNameNotUnique))
  319. {
  320. client_name = jack_get_client_name(mClient);
  321. TRACE("Client name not unique, got '%s' instead\n", client_name);
  322. }
  323. jack_set_process_callback(mClient, &JackPlayback::processC, this);
  324. mDevice->DeviceName = name;
  325. }
  326. bool JackPlayback::reset()
  327. {
  328. std::for_each(mPort.begin(), mPort.end(),
  329. [this](jack_port_t *port) -> void
  330. { if(port) jack_port_unregister(mClient, port); });
  331. mPort.fill(nullptr);
  332. /* Ignore the requested buffer metrics and just keep one JACK-sized buffer
  333. * ready for when requested.
  334. */
  335. mDevice->Frequency = jack_get_sample_rate(mClient);
  336. mDevice->UpdateSize = jack_get_buffer_size(mClient);
  337. mDevice->BufferSize = mDevice->UpdateSize * 2;
  338. const char *devname{mDevice->DeviceName.c_str()};
  339. uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size").value_or(mDevice->UpdateSize)};
  340. bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize);
  341. mDevice->BufferSize = bufsize + mDevice->UpdateSize;
  342. /* Force 32-bit float output. */
  343. mDevice->FmtType = DevFmtFloat;
  344. auto ports_end = mPort.begin() + mDevice->channelsFromFmt();
  345. auto bad_port = std::find_if_not(mPort.begin(), ports_end,
  346. [this](jack_port_t *&port) -> bool
  347. {
  348. std::string name{"channel_" + std::to_string(&port - &mPort[0] + 1)};
  349. port = jack_port_register(mClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE,
  350. JackPortIsOutput, 0);
  351. return port != nullptr;
  352. });
  353. if(bad_port != ports_end)
  354. {
  355. ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(mDevice->FmtChans));
  356. if(bad_port == mPort.begin()) return false;
  357. if(bad_port == mPort.begin()+1)
  358. mDevice->FmtChans = DevFmtMono;
  359. else
  360. {
  361. ports_end = mPort.begin()+2;
  362. while(bad_port != ports_end)
  363. {
  364. jack_port_unregister(mClient, *(--bad_port));
  365. *bad_port = nullptr;
  366. }
  367. mDevice->FmtChans = DevFmtStereo;
  368. }
  369. }
  370. setDefaultChannelOrder();
  371. return true;
  372. }
  373. void JackPlayback::start()
  374. {
  375. if(jack_activate(mClient))
  376. throw al::backend_exception{al::backend_error::DeviceError, "Failed to activate client"};
  377. const char *devname{mDevice->DeviceName.c_str()};
  378. if(ConfigValueBool(devname, "jack", "connect-ports").value_or(true))
  379. {
  380. const char **ports{jack_get_ports(mClient, mPortPattern.c_str(), nullptr,
  381. JackPortIsPhysical|JackPortIsInput)};
  382. if(ports == nullptr)
  383. {
  384. jack_deactivate(mClient);
  385. throw al::backend_exception{al::backend_error::DeviceError,
  386. "No physical playback ports found"};
  387. }
  388. auto connect_port = [this](const jack_port_t *port, const char *pname) -> bool
  389. {
  390. if(!port) return false;
  391. if(!pname)
  392. {
  393. ERR("No physical playback port for \"%s\"\n", jack_port_name(port));
  394. return false;
  395. }
  396. if(jack_connect(mClient, jack_port_name(port), pname))
  397. ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(port),
  398. pname);
  399. return true;
  400. };
  401. std::mismatch(mPort.begin(), mPort.end(), ports, connect_port);
  402. jack_free(ports);
  403. }
  404. /* Reconfigure buffer metrics in case the server changed it since the reset
  405. * (it won't change again after jack_activate), then allocate the ring
  406. * buffer with the appropriate size.
  407. */
  408. mDevice->Frequency = jack_get_sample_rate(mClient);
  409. mDevice->UpdateSize = jack_get_buffer_size(mClient);
  410. mDevice->BufferSize = mDevice->UpdateSize * 2;
  411. uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size").value_or(mDevice->UpdateSize)};
  412. bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize);
  413. mDevice->BufferSize = bufsize + mDevice->UpdateSize;
  414. mRing = nullptr;
  415. mRing = RingBuffer::Create(bufsize, mDevice->frameSizeFromFmt(), true);
  416. try {
  417. mPlaying.store(true, std::memory_order_release);
  418. mKillNow.store(false, std::memory_order_release);
  419. mThread = std::thread{std::mem_fn(&JackPlayback::mixerProc), this};
  420. }
  421. catch(std::exception& e) {
  422. jack_deactivate(mClient);
  423. mPlaying.store(false, std::memory_order_release);
  424. throw al::backend_exception{al::backend_error::DeviceError,
  425. "Failed to start mixing thread: %s", e.what()};
  426. }
  427. }
  428. void JackPlayback::stop()
  429. {
  430. if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable())
  431. return;
  432. mSem.post();
  433. mThread.join();
  434. jack_deactivate(mClient);
  435. mPlaying.store(false, std::memory_order_release);
  436. }
  437. ClockLatency JackPlayback::getClockLatency()
  438. {
  439. ClockLatency ret;
  440. std::lock_guard<std::mutex> _{mMutex};
  441. ret.ClockTime = GetDeviceClockTime(mDevice);
  442. ret.Latency = std::chrono::seconds{mRing->readSpace()};
  443. ret.Latency /= mDevice->Frequency;
  444. return ret;
  445. }
  446. void jack_msg_handler(const char *message)
  447. {
  448. WARN("%s\n", message);
  449. }
  450. } // namespace
  451. bool JackBackendFactory::init()
  452. {
  453. if(!jack_load())
  454. return false;
  455. if(!GetConfigValueBool(nullptr, "jack", "spawn-server", 0))
  456. ClientOptions = static_cast<jack_options_t>(ClientOptions | JackNoStartServer);
  457. void (*old_error_cb)(const char*){&jack_error_callback ? jack_error_callback : nullptr};
  458. jack_set_error_function(jack_msg_handler);
  459. jack_status_t status;
  460. jack_client_t *client{jack_client_open("alsoft", ClientOptions, &status, nullptr)};
  461. jack_set_error_function(old_error_cb);
  462. if(!client)
  463. {
  464. WARN("jack_client_open() failed, 0x%02x\n", status);
  465. if((status&JackServerFailed) && !(ClientOptions&JackNoStartServer))
  466. ERR("Unable to connect to JACK server\n");
  467. return false;
  468. }
  469. jack_client_close(client);
  470. return true;
  471. }
  472. bool JackBackendFactory::querySupport(BackendType type)
  473. { return (type == BackendType::Playback); }
  474. std::string JackBackendFactory::probe(BackendType type)
  475. {
  476. std::string outnames;
  477. auto append_name = [&outnames](const DeviceEntry &entry) -> void
  478. {
  479. /* Includes null char. */
  480. outnames.append(entry.mName.c_str(), entry.mName.length()+1);
  481. };
  482. switch(type)
  483. {
  484. case BackendType::Playback:
  485. EnumerateDevices(PlaybackList);
  486. std::for_each(PlaybackList.cbegin(), PlaybackList.cend(), append_name);
  487. break;
  488. case BackendType::Capture:
  489. break;
  490. }
  491. return outnames;
  492. }
  493. BackendPtr JackBackendFactory::createBackend(ALCdevice *device, BackendType type)
  494. {
  495. if(type == BackendType::Playback)
  496. return BackendPtr{new JackPlayback{device}};
  497. return nullptr;
  498. }
  499. BackendFactory &JackBackendFactory::getFactory()
  500. {
  501. static JackBackendFactory factory{};
  502. return factory;
  503. }