pipewire.cpp 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2010 by Chris Robinson
  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 "pipewire.h"
  22. #include <algorithm>
  23. #include <array>
  24. #include <atomic>
  25. #include <bitset>
  26. #include <cinttypes>
  27. #include <cmath>
  28. #include <cstddef>
  29. #include <cstdio>
  30. #include <cstdlib>
  31. #include <cstring>
  32. #include <cerrno>
  33. #include <chrono>
  34. #include <ctime>
  35. #include <functional>
  36. #include <iterator>
  37. #include <memory>
  38. #include <mutex>
  39. #include <optional>
  40. #include <string_view>
  41. #include <thread>
  42. #include <tuple>
  43. #include <utility>
  44. #include "alc/alconfig.h"
  45. #include "alc/backends/base.h"
  46. #include "almalloc.h"
  47. #include "alspan.h"
  48. #include "alstring.h"
  49. #include "core/devformat.h"
  50. #include "core/device.h"
  51. #include "core/helpers.h"
  52. #include "core/logging.h"
  53. #include "dynload.h"
  54. #include "fmt/core.h"
  55. #include "fmt/ranges.h"
  56. #include "opthelpers.h"
  57. #include "ringbuffer.h"
  58. /* Ignore warnings caused by PipeWire headers (lots in standard C++ mode). GCC
  59. * doesn't support ignoring -Weverything, so we have the list the individual
  60. * warnings to ignore (and ignoring -Winline doesn't seem to work).
  61. */
  62. _Pragma("GCC diagnostic push")
  63. _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
  64. _Pragma("GCC diagnostic ignored \"-Wconversion\"")
  65. _Pragma("GCC diagnostic ignored \"-Wfloat-conversion\"")
  66. _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
  67. _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
  68. _Pragma("GCC diagnostic ignored \"-Wold-style-cast\"")
  69. _Pragma("GCC diagnostic ignored \"-Wsign-compare\"")
  70. _Pragma("GCC diagnostic ignored \"-Winline\"")
  71. _Pragma("GCC diagnostic ignored \"-Wpragmas\"")
  72. _Pragma("GCC diagnostic ignored \"-Weverything\"")
  73. #include "pipewire/pipewire.h"
  74. #include "pipewire/extensions/metadata.h"
  75. #include "spa/buffer/buffer.h"
  76. #include "spa/param/audio/format-utils.h"
  77. #include "spa/param/audio/raw.h"
  78. #include "spa/param/format.h"
  79. #include "spa/param/param.h"
  80. #include "spa/pod/builder.h"
  81. #include "spa/utils/json.h"
  82. /* NOLINTBEGIN : All kinds of unsafe C stuff here from PipeWire headers
  83. * (function-like macros, C style casts in macros, etc), which we can't do
  84. * anything about except wrap into inline functions.
  85. */
  86. namespace {
  87. /* Wrap some nasty macros here too... */
  88. template<typename ...Args>
  89. auto ppw_core_add_listener(pw_core *core, Args&& ...args)
  90. { return pw_core_add_listener(core, std::forward<Args>(args)...); }
  91. template<typename ...Args>
  92. auto ppw_core_sync(pw_core *core, Args&& ...args)
  93. { return pw_core_sync(core, std::forward<Args>(args)...); }
  94. template<typename ...Args>
  95. auto ppw_registry_add_listener(pw_registry *reg, Args&& ...args)
  96. { return pw_registry_add_listener(reg, std::forward<Args>(args)...); }
  97. template<typename ...Args>
  98. auto ppw_node_add_listener(pw_node *node, Args&& ...args)
  99. { return pw_node_add_listener(node, std::forward<Args>(args)...); }
  100. template<typename ...Args>
  101. auto ppw_node_subscribe_params(pw_node *node, Args&& ...args)
  102. { return pw_node_subscribe_params(node, std::forward<Args>(args)...); }
  103. template<typename ...Args>
  104. auto ppw_metadata_add_listener(pw_metadata *mdata, Args&& ...args)
  105. { return pw_metadata_add_listener(mdata, std::forward<Args>(args)...); }
  106. constexpr auto get_pod_type(const spa_pod *pod) noexcept
  107. { return SPA_POD_TYPE(pod); }
  108. template<typename T>
  109. constexpr auto get_pod_body(const spa_pod *pod, size_t count) noexcept
  110. { return al::span<T>{static_cast<T*>(SPA_POD_BODY(pod)), count}; }
  111. template<typename T, size_t N>
  112. constexpr auto get_pod_body(const spa_pod *pod) noexcept
  113. { return al::span<T,N>{static_cast<T*>(SPA_POD_BODY(pod)), N}; }
  114. constexpr auto get_array_value_type(const spa_pod *pod) noexcept
  115. { return SPA_POD_ARRAY_VALUE_TYPE(pod); }
  116. constexpr auto make_pod_builder(void *data, uint32_t size) noexcept
  117. { return SPA_POD_BUILDER_INIT(data, size); }
  118. constexpr auto PwIdAny = PW_ID_ANY;
  119. } // namespace
  120. /* NOLINTEND */
  121. _Pragma("GCC diagnostic pop")
  122. namespace {
  123. template<typename T> [[nodiscard]] constexpr
  124. auto as_const_ptr(T *ptr) noexcept -> std::add_const_t<T>* { return ptr; }
  125. struct PodDynamicBuilder {
  126. private:
  127. std::vector<std::byte> mStorage;
  128. spa_pod_builder mPod{};
  129. int overflow(uint32_t size) noexcept
  130. {
  131. try {
  132. mStorage.resize(size);
  133. }
  134. catch(...) {
  135. ERR("Failed to resize POD storage");
  136. return -ENOMEM;
  137. }
  138. mPod.data = mStorage.data();
  139. mPod.size = size;
  140. return 0;
  141. }
  142. public:
  143. explicit PodDynamicBuilder(uint32_t initSize=1024) : mStorage(initSize)
  144. , mPod{make_pod_builder(mStorage.data(), initSize)}
  145. {
  146. static constexpr auto callbacks{[]
  147. {
  148. spa_pod_builder_callbacks cb{};
  149. cb.version = SPA_VERSION_POD_BUILDER_CALLBACKS;
  150. cb.overflow = [](void *data, uint32_t size) noexcept
  151. { return static_cast<PodDynamicBuilder*>(data)->overflow(size); };
  152. return cb;
  153. }()};
  154. spa_pod_builder_set_callbacks(&mPod, &callbacks, this);
  155. }
  156. spa_pod_builder *get() noexcept { return &mPod; }
  157. };
  158. /* Added in 0.3.33, but we currently only require 0.3.23. */
  159. #ifndef PW_KEY_NODE_RATE
  160. #define PW_KEY_NODE_RATE "node.rate"
  161. #endif
  162. using namespace std::string_view_literals;
  163. using std::chrono::seconds;
  164. using std::chrono::milliseconds;
  165. using std::chrono::nanoseconds;
  166. using uint = unsigned int;
  167. bool check_version(const char *version)
  168. {
  169. /* There doesn't seem to be a function to get the version as an integer, so
  170. * instead we have to parse the string, which hopefully won't break in the
  171. * future.
  172. */
  173. int major{0}, minor{0}, revision{0};
  174. /* NOLINTNEXTLINE(cert-err34-c,cppcoreguidelines-pro-type-vararg) */
  175. int ret{sscanf(version, "%d.%d.%d", &major, &minor, &revision)};
  176. return ret == 3 && (major > PW_MAJOR || (major == PW_MAJOR && minor > PW_MINOR)
  177. || (major == PW_MAJOR && minor == PW_MINOR && revision >= PW_MICRO));
  178. }
  179. #if HAVE_DYNLOAD
  180. #define PWIRE_FUNCS(MAGIC) \
  181. MAGIC(pw_context_connect) \
  182. MAGIC(pw_context_destroy) \
  183. MAGIC(pw_context_new) \
  184. MAGIC(pw_core_disconnect) \
  185. MAGIC(pw_get_library_version) \
  186. MAGIC(pw_init) \
  187. MAGIC(pw_properties_free) \
  188. MAGIC(pw_properties_new) \
  189. MAGIC(pw_properties_set) \
  190. MAGIC(pw_properties_setf) \
  191. MAGIC(pw_proxy_add_object_listener) \
  192. MAGIC(pw_proxy_destroy) \
  193. MAGIC(pw_proxy_get_user_data) \
  194. MAGIC(pw_stream_add_listener) \
  195. MAGIC(pw_stream_connect) \
  196. MAGIC(pw_stream_dequeue_buffer) \
  197. MAGIC(pw_stream_destroy) \
  198. MAGIC(pw_stream_get_state) \
  199. MAGIC(pw_stream_new) \
  200. MAGIC(pw_stream_queue_buffer) \
  201. MAGIC(pw_stream_set_active) \
  202. MAGIC(pw_thread_loop_new) \
  203. MAGIC(pw_thread_loop_destroy) \
  204. MAGIC(pw_thread_loop_get_loop) \
  205. MAGIC(pw_thread_loop_start) \
  206. MAGIC(pw_thread_loop_stop) \
  207. MAGIC(pw_thread_loop_lock) \
  208. MAGIC(pw_thread_loop_wait) \
  209. MAGIC(pw_thread_loop_signal) \
  210. MAGIC(pw_thread_loop_unlock)
  211. #if PW_CHECK_VERSION(0,3,50)
  212. #define PWIRE_FUNCS2(MAGIC) \
  213. MAGIC(pw_stream_get_time_n)
  214. #else
  215. #define PWIRE_FUNCS2(MAGIC) \
  216. MAGIC(pw_stream_get_time)
  217. #endif
  218. void *pwire_handle;
  219. #define MAKE_FUNC(f) decltype(f) * p##f;
  220. PWIRE_FUNCS(MAKE_FUNC)
  221. PWIRE_FUNCS2(MAKE_FUNC)
  222. #undef MAKE_FUNC
  223. bool pwire_load()
  224. {
  225. if(pwire_handle)
  226. return true;
  227. const char *pwire_library{"libpipewire-0.3.so.0"};
  228. std::string missing_funcs;
  229. pwire_handle = LoadLib(pwire_library);
  230. if(!pwire_handle)
  231. {
  232. WARN("Failed to load {}", pwire_library);
  233. return false;
  234. }
  235. #define LOAD_FUNC(f) do { \
  236. p##f = reinterpret_cast<decltype(p##f)>(GetSymbol(pwire_handle, #f)); \
  237. if(p##f == nullptr) missing_funcs += "\n" #f; \
  238. } while(0);
  239. PWIRE_FUNCS(LOAD_FUNC)
  240. PWIRE_FUNCS2(LOAD_FUNC)
  241. #undef LOAD_FUNC
  242. if(!missing_funcs.empty())
  243. {
  244. WARN("Missing expected functions:{}", missing_funcs);
  245. CloseLib(pwire_handle);
  246. pwire_handle = nullptr;
  247. return false;
  248. }
  249. return true;
  250. }
  251. #ifndef IN_IDE_PARSER
  252. #define pw_context_connect ppw_context_connect
  253. #define pw_context_destroy ppw_context_destroy
  254. #define pw_context_new ppw_context_new
  255. #define pw_core_disconnect ppw_core_disconnect
  256. #define pw_get_library_version ppw_get_library_version
  257. #define pw_init ppw_init
  258. #define pw_properties_free ppw_properties_free
  259. #define pw_properties_new ppw_properties_new
  260. #define pw_properties_set ppw_properties_set
  261. #define pw_properties_setf ppw_properties_setf
  262. #define pw_proxy_add_object_listener ppw_proxy_add_object_listener
  263. #define pw_proxy_destroy ppw_proxy_destroy
  264. #define pw_proxy_get_user_data ppw_proxy_get_user_data
  265. #define pw_stream_add_listener ppw_stream_add_listener
  266. #define pw_stream_connect ppw_stream_connect
  267. #define pw_stream_dequeue_buffer ppw_stream_dequeue_buffer
  268. #define pw_stream_destroy ppw_stream_destroy
  269. #define pw_stream_get_state ppw_stream_get_state
  270. #define pw_stream_new ppw_stream_new
  271. #define pw_stream_queue_buffer ppw_stream_queue_buffer
  272. #define pw_stream_set_active ppw_stream_set_active
  273. #define pw_thread_loop_destroy ppw_thread_loop_destroy
  274. #define pw_thread_loop_get_loop ppw_thread_loop_get_loop
  275. #define pw_thread_loop_lock ppw_thread_loop_lock
  276. #define pw_thread_loop_new ppw_thread_loop_new
  277. #define pw_thread_loop_signal ppw_thread_loop_signal
  278. #define pw_thread_loop_start ppw_thread_loop_start
  279. #define pw_thread_loop_stop ppw_thread_loop_stop
  280. #define pw_thread_loop_unlock ppw_thread_loop_unlock
  281. #define pw_thread_loop_wait ppw_thread_loop_wait
  282. #if PW_CHECK_VERSION(0,3,50)
  283. #define pw_stream_get_time_n ppw_stream_get_time_n
  284. #else
  285. inline auto pw_stream_get_time_n(pw_stream *stream, pw_time *ptime, size_t /*size*/)
  286. { return ppw_stream_get_time(stream, ptime); }
  287. #endif
  288. #endif
  289. #else
  290. constexpr bool pwire_load() { return true; }
  291. #endif
  292. /* Helpers for retrieving values from params */
  293. template<uint32_t T> struct PodInfo { };
  294. template<>
  295. struct PodInfo<SPA_TYPE_Int> {
  296. using Type = int32_t;
  297. static auto get_value(const spa_pod *pod, int32_t *val)
  298. { return spa_pod_get_int(pod, val); }
  299. };
  300. template<>
  301. struct PodInfo<SPA_TYPE_Id> {
  302. using Type = uint32_t;
  303. static auto get_value(const spa_pod *pod, uint32_t *val)
  304. { return spa_pod_get_id(pod, val); }
  305. };
  306. template<uint32_t T>
  307. using Pod_t = typename PodInfo<T>::Type;
  308. template<uint32_t T>
  309. al::span<const Pod_t<T>> get_array_span(const spa_pod *pod)
  310. {
  311. uint32_t nvals{};
  312. if(void *v{spa_pod_get_array(pod, &nvals)})
  313. {
  314. if(get_array_value_type(pod) == T)
  315. return {static_cast<const Pod_t<T>*>(v), nvals};
  316. }
  317. return {};
  318. }
  319. template<uint32_t T>
  320. std::optional<Pod_t<T>> get_value(const spa_pod *value)
  321. {
  322. Pod_t<T> val{};
  323. if(PodInfo<T>::get_value(value, &val) == 0)
  324. return val;
  325. return std::nullopt;
  326. }
  327. /* Internally, PipeWire types "inherit" from each other, but this is hidden
  328. * from the API and the caller is expected to C-style cast to inherited types
  329. * as needed. It's also not made very clear what types a given type can be
  330. * casted to. To make it a bit safer, this as() method allows casting pw_*
  331. * types to known inherited types, generating a compile-time error for
  332. * unexpected/invalid casts.
  333. */
  334. template<typename To, typename From>
  335. To as(From) noexcept = delete;
  336. /* pw_proxy
  337. * - pw_registry
  338. * - pw_node
  339. * - pw_metadata
  340. */
  341. template<>
  342. pw_proxy* as(pw_registry *reg) noexcept { return reinterpret_cast<pw_proxy*>(reg); }
  343. template<>
  344. pw_proxy* as(pw_node *node) noexcept { return reinterpret_cast<pw_proxy*>(node); }
  345. template<>
  346. pw_proxy* as(pw_metadata *mdata) noexcept { return reinterpret_cast<pw_proxy*>(mdata); }
  347. struct PwContextDeleter {
  348. void operator()(pw_context *context) const { pw_context_destroy(context); }
  349. };
  350. using PwContextPtr = std::unique_ptr<pw_context,PwContextDeleter>;
  351. struct PwCoreDeleter {
  352. void operator()(pw_core *core) const { pw_core_disconnect(core); }
  353. };
  354. using PwCorePtr = std::unique_ptr<pw_core,PwCoreDeleter>;
  355. struct PwRegistryDeleter {
  356. void operator()(pw_registry *reg) const { pw_proxy_destroy(as<pw_proxy*>(reg)); }
  357. };
  358. using PwRegistryPtr = std::unique_ptr<pw_registry,PwRegistryDeleter>;
  359. struct PwNodeDeleter {
  360. void operator()(pw_node *node) const { pw_proxy_destroy(as<pw_proxy*>(node)); }
  361. };
  362. using PwNodePtr = std::unique_ptr<pw_node,PwNodeDeleter>;
  363. struct PwMetadataDeleter {
  364. void operator()(pw_metadata *mdata) const { pw_proxy_destroy(as<pw_proxy*>(mdata)); }
  365. };
  366. using PwMetadataPtr = std::unique_ptr<pw_metadata,PwMetadataDeleter>;
  367. struct PwStreamDeleter {
  368. void operator()(pw_stream *stream) const { pw_stream_destroy(stream); }
  369. };
  370. using PwStreamPtr = std::unique_ptr<pw_stream,PwStreamDeleter>;
  371. /* NOLINTBEGIN(*EnumCastOutOfRange) Enums for bitflags... again... *sigh* */
  372. constexpr pw_stream_flags operator|(pw_stream_flags lhs, pw_stream_flags rhs) noexcept
  373. { return static_cast<pw_stream_flags>(lhs | al::to_underlying(rhs)); }
  374. /* NOLINTEND(*EnumCastOutOfRange) */
  375. constexpr pw_stream_flags& operator|=(pw_stream_flags &lhs, pw_stream_flags rhs) noexcept
  376. { lhs = lhs | rhs; return lhs; }
  377. class ThreadMainloop {
  378. pw_thread_loop *mLoop{};
  379. public:
  380. ThreadMainloop() = default;
  381. ThreadMainloop(const ThreadMainloop&) = delete;
  382. ThreadMainloop(ThreadMainloop&& rhs) noexcept : mLoop{rhs.mLoop} { rhs.mLoop = nullptr; }
  383. explicit ThreadMainloop(pw_thread_loop *loop) noexcept : mLoop{loop} { }
  384. ~ThreadMainloop() { if(mLoop) pw_thread_loop_destroy(mLoop); }
  385. ThreadMainloop& operator=(const ThreadMainloop&) = delete;
  386. ThreadMainloop& operator=(ThreadMainloop&& rhs) noexcept
  387. { std::swap(mLoop, rhs.mLoop); return *this; }
  388. ThreadMainloop& operator=(std::nullptr_t) noexcept
  389. {
  390. if(mLoop)
  391. pw_thread_loop_destroy(mLoop);
  392. mLoop = nullptr;
  393. return *this;
  394. }
  395. explicit operator bool() const noexcept { return mLoop != nullptr; }
  396. [[nodiscard]]
  397. auto start() const { return pw_thread_loop_start(mLoop); }
  398. auto stop() const { return pw_thread_loop_stop(mLoop); }
  399. [[nodiscard]]
  400. auto getLoop() const { return pw_thread_loop_get_loop(mLoop); }
  401. auto lock() const { return pw_thread_loop_lock(mLoop); }
  402. auto unlock() const { return pw_thread_loop_unlock(mLoop); }
  403. auto signal(bool wait) const { return pw_thread_loop_signal(mLoop, wait); }
  404. auto newContext(pw_properties *props=nullptr, size_t user_data_size=0) const
  405. { return PwContextPtr{pw_context_new(getLoop(), props, user_data_size)}; }
  406. static auto Create(const char *name, spa_dict *props=nullptr)
  407. { return ThreadMainloop{pw_thread_loop_new(name, props)}; }
  408. friend struct MainloopUniqueLock;
  409. };
  410. struct MainloopUniqueLock : public std::unique_lock<ThreadMainloop> {
  411. using std::unique_lock<ThreadMainloop>::unique_lock;
  412. MainloopUniqueLock& operator=(MainloopUniqueLock&&) = default;
  413. auto wait() const -> void
  414. { pw_thread_loop_wait(mutex()->mLoop); }
  415. template<typename Predicate>
  416. auto wait(Predicate done_waiting) const -> void
  417. { while(!done_waiting()) wait(); }
  418. };
  419. using MainloopLockGuard = std::lock_guard<ThreadMainloop>;
  420. /* There's quite a mess here, but the purpose is to track active devices and
  421. * their default formats, so playback devices can be configured to match. The
  422. * device list is updated asynchronously, so it will have the latest list of
  423. * devices provided by the server.
  424. */
  425. /* A generic PipeWire node proxy object used to track changes to sink and
  426. * source nodes.
  427. */
  428. struct NodeProxy {
  429. static constexpr pw_node_events CreateNodeEvents()
  430. {
  431. pw_node_events ret{};
  432. ret.version = PW_VERSION_NODE_EVENTS;
  433. ret.info = infoCallback;
  434. ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept
  435. { static_cast<NodeProxy*>(object)->paramCallback(seq, id, index, next, param); };
  436. return ret;
  437. }
  438. uint32_t mId{};
  439. PwNodePtr mNode;
  440. spa_hook mListener{};
  441. NodeProxy(uint32_t id, PwNodePtr node)
  442. : mId{id}, mNode{std::move(node)}
  443. {
  444. static constexpr pw_node_events nodeEvents{CreateNodeEvents()};
  445. ppw_node_add_listener(mNode.get(), &mListener, &nodeEvents, this);
  446. /* Track changes to the enumerable and current formats (indicates the
  447. * default and active format, which is what we're interested in).
  448. */
  449. std::array<uint32_t,2> fmtids{{SPA_PARAM_EnumFormat, SPA_PARAM_Format}};
  450. ppw_node_subscribe_params(mNode.get(), fmtids.data(), fmtids.size());
  451. }
  452. ~NodeProxy()
  453. { spa_hook_remove(&mListener); }
  454. static void infoCallback(void *object, const pw_node_info *info) noexcept;
  455. void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) const noexcept;
  456. };
  457. /* A metadata proxy object used to query the default sink and source. */
  458. struct MetadataProxy {
  459. static constexpr pw_metadata_events CreateMetadataEvents()
  460. {
  461. pw_metadata_events ret{};
  462. ret.version = PW_VERSION_METADATA_EVENTS;
  463. ret.property = propertyCallback;
  464. return ret;
  465. }
  466. uint32_t mId{};
  467. PwMetadataPtr mMetadata;
  468. spa_hook mListener{};
  469. MetadataProxy(uint32_t id, PwMetadataPtr mdata)
  470. : mId{id}, mMetadata{std::move(mdata)}
  471. {
  472. static constexpr pw_metadata_events metadataEvents{CreateMetadataEvents()};
  473. ppw_metadata_add_listener(mMetadata.get(), &mListener, &metadataEvents, this);
  474. }
  475. ~MetadataProxy()
  476. { spa_hook_remove(&mListener); }
  477. static auto propertyCallback(void *object, uint32_t id, const char *key, const char *type,
  478. const char *value) noexcept -> int;
  479. };
  480. /* The global thread watching for global events. This particular class responds
  481. * to objects being added to or removed from the registry.
  482. */
  483. struct EventManager {
  484. ThreadMainloop mLoop;
  485. PwContextPtr mContext;
  486. PwCorePtr mCore;
  487. PwRegistryPtr mRegistry;
  488. spa_hook mRegistryListener{};
  489. spa_hook mCoreListener{};
  490. /* A list of proxy objects watching for events about changes to objects in
  491. * the registry.
  492. */
  493. std::vector<std::unique_ptr<NodeProxy>> mNodeList;
  494. std::optional<MetadataProxy> mDefaultMetadata;
  495. /* Initialization handling. When init() is called, mInitSeq is set to a
  496. * SequenceID that marks the end of populating the registry. As objects of
  497. * interest are found, events to parse them are generated and mInitSeq is
  498. * updated with a newer ID. When mInitSeq stops being updated and the event
  499. * corresponding to it is reached, mInitDone will be set to true.
  500. */
  501. std::atomic<bool> mInitDone{false};
  502. std::atomic<bool> mHasAudio{false};
  503. int mInitSeq{};
  504. ~EventManager() { if(mLoop) mLoop.stop(); }
  505. bool init();
  506. void kill();
  507. auto lock() const { return mLoop.lock(); }
  508. auto unlock() const { return mLoop.unlock(); }
  509. [[nodiscard]]
  510. auto initIsDone(std::memory_order m=std::memory_order_seq_cst) const noexcept -> bool
  511. { return mInitDone.load(m); }
  512. /**
  513. * Waits for initialization to finish. The event manager must *NOT* be
  514. * locked when calling this.
  515. */
  516. void waitForInit()
  517. {
  518. if(!initIsDone(std::memory_order_acquire)) UNLIKELY
  519. {
  520. MainloopUniqueLock plock{mLoop};
  521. plock.wait([this](){ return initIsDone(std::memory_order_acquire); });
  522. }
  523. }
  524. /**
  525. * Waits for audio support to be detected, or initialization to finish,
  526. * whichever is first. Returns true if audio support was detected. The
  527. * event manager must *NOT* be locked when calling this.
  528. */
  529. bool waitForAudio()
  530. {
  531. MainloopUniqueLock plock{mLoop};
  532. bool has_audio{};
  533. plock.wait([this,&has_audio]()
  534. {
  535. has_audio = mHasAudio.load(std::memory_order_acquire);
  536. return has_audio || initIsDone(std::memory_order_acquire);
  537. });
  538. return has_audio;
  539. }
  540. void syncInit()
  541. {
  542. /* If initialization isn't done, update the sequence ID so it won't
  543. * complete until after currently scheduled events.
  544. */
  545. if(!initIsDone(std::memory_order_relaxed))
  546. mInitSeq = ppw_core_sync(mCore.get(), PW_ID_CORE, mInitSeq);
  547. }
  548. void addCallback(uint32_t id, uint32_t permissions, const char *type, uint32_t version,
  549. const spa_dict *props) noexcept;
  550. void removeCallback(uint32_t id) noexcept;
  551. static constexpr pw_registry_events CreateRegistryEvents()
  552. {
  553. pw_registry_events ret{};
  554. ret.version = PW_VERSION_REGISTRY_EVENTS;
  555. ret.global = [](void *object, uint32_t id, uint32_t permissions, const char *type, uint32_t version, const spa_dict *props) noexcept
  556. { static_cast<EventManager*>(object)->addCallback(id, permissions, type, version, props); };
  557. ret.global_remove = [](void *object, uint32_t id) noexcept
  558. { static_cast<EventManager*>(object)->removeCallback(id); };
  559. return ret;
  560. }
  561. void coreCallback(uint32_t id, int seq) noexcept;
  562. static constexpr pw_core_events CreateCoreEvents()
  563. {
  564. pw_core_events ret{};
  565. ret.version = PW_VERSION_CORE_EVENTS;
  566. ret.done = [](void *object, uint32_t id, int seq) noexcept
  567. { static_cast<EventManager*>(object)->coreCallback(id, seq); };
  568. return ret;
  569. }
  570. };
  571. using EventWatcherUniqueLock = std::unique_lock<EventManager>;
  572. using EventWatcherLockGuard = std::lock_guard<EventManager>;
  573. EventManager gEventHandler;
  574. /* Enumerated devices. This is updated asynchronously as the app runs, and the
  575. * gEventHandler thread loop must be locked when accessing the list.
  576. */
  577. enum class NodeType : unsigned char {
  578. Sink, Source, Duplex
  579. };
  580. constexpr auto InvalidChannelConfig = DevFmtChannels(255);
  581. struct DeviceNode {
  582. uint32_t mId{};
  583. uint64_t mSerial{};
  584. std::string mName;
  585. std::string mDevName;
  586. NodeType mType{};
  587. bool mIsHeadphones{};
  588. bool mIs51Rear{};
  589. uint mSampleRate{};
  590. DevFmtChannels mChannels{InvalidChannelConfig};
  591. static std::vector<DeviceNode> sList;
  592. static DeviceNode &Add(uint32_t id);
  593. static DeviceNode *Find(uint32_t id);
  594. static DeviceNode *FindByDevName(std::string_view devname);
  595. static void Remove(uint32_t id);
  596. static auto GetList() noexcept { return al::span{sList}; }
  597. void parseSampleRate(const spa_pod *value, bool force_update) noexcept;
  598. void parsePositions(const spa_pod *value, bool force_update) noexcept;
  599. void parseChannelCount(const spa_pod *value, bool force_update) noexcept;
  600. void callEvent(alc::EventType type, std::string_view message) const
  601. {
  602. /* Source nodes aren't recognized for playback, only Sink and Duplex
  603. * nodes are. All node types are recognized for capture.
  604. */
  605. if(mType != NodeType::Source)
  606. alc::Event(type, alc::DeviceType::Playback, message);
  607. alc::Event(type, alc::DeviceType::Capture, message);
  608. }
  609. };
  610. std::vector<DeviceNode> DeviceNode::sList;
  611. std::string DefaultSinkDevice;
  612. std::string DefaultSourceDevice;
  613. const char *AsString(NodeType type) noexcept
  614. {
  615. switch(type)
  616. {
  617. case NodeType::Sink: return "sink";
  618. case NodeType::Source: return "source";
  619. case NodeType::Duplex: return "duplex";
  620. }
  621. return "<unknown>";
  622. }
  623. DeviceNode &DeviceNode::Add(uint32_t id)
  624. {
  625. auto match_id = [id](DeviceNode &n) noexcept -> bool
  626. { return n.mId == id; };
  627. /* If the node is already in the list, return the existing entry. */
  628. auto match = std::find_if(sList.begin(), sList.end(), match_id);
  629. if(match != sList.end()) return *match;
  630. auto &n = sList.emplace_back();
  631. n.mId = id;
  632. return n;
  633. }
  634. DeviceNode *DeviceNode::Find(uint32_t id)
  635. {
  636. auto match_id = [id](DeviceNode &n) noexcept -> bool
  637. { return n.mId == id; };
  638. auto match = std::find_if(sList.begin(), sList.end(), match_id);
  639. if(match != sList.end()) return al::to_address(match);
  640. return nullptr;
  641. }
  642. DeviceNode *DeviceNode::FindByDevName(std::string_view devname)
  643. {
  644. auto match_id = [devname](DeviceNode &n) noexcept -> bool
  645. { return n.mDevName == devname; };
  646. auto match = std::find_if(sList.begin(), sList.end(), match_id);
  647. if(match != sList.end()) return al::to_address(match);
  648. return nullptr;
  649. }
  650. void DeviceNode::Remove(uint32_t id)
  651. {
  652. auto match_id = [id](DeviceNode &n) noexcept -> bool
  653. {
  654. if(n.mId != id)
  655. return false;
  656. TRACE("Removing device \"{}\"", n.mDevName);
  657. if(gEventHandler.initIsDone(std::memory_order_relaxed))
  658. {
  659. const std::string msg{"Device removed: "+n.mName};
  660. n.callEvent(alc::EventType::DeviceRemoved, msg);
  661. }
  662. return true;
  663. };
  664. auto end = std::remove_if(sList.begin(), sList.end(), match_id);
  665. sList.erase(end, sList.end());
  666. }
  667. constexpr std::array MonoMap{
  668. SPA_AUDIO_CHANNEL_MONO
  669. };
  670. constexpr std::array StereoMap{
  671. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR
  672. };
  673. constexpr std::array QuadMap{
  674. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR
  675. };
  676. constexpr std::array X51Map{
  677. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
  678. SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
  679. };
  680. constexpr std::array X51RearMap{
  681. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
  682. SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR
  683. };
  684. constexpr std::array X61Map{
  685. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
  686. SPA_AUDIO_CHANNEL_RC, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
  687. };
  688. constexpr std::array X71Map{
  689. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
  690. SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
  691. };
  692. constexpr std::array X714Map{
  693. SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
  694. SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR,
  695. SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR
  696. };
  697. /**
  698. * Checks if every channel in 'map1' exists in 'map0' (that is, map0 is equal
  699. * to or a superset of map1).
  700. */
  701. bool MatchChannelMap(const al::span<const uint32_t> map0,
  702. const al::span<const spa_audio_channel> map1)
  703. {
  704. if(map0.size() < map1.size())
  705. return false;
  706. auto find_channel = [map0](const spa_audio_channel chid) -> bool
  707. { return std::find(map0.begin(), map0.end(), chid) != map0.end(); };
  708. return std::all_of(map1.cbegin(), map1.cend(), find_channel);
  709. }
  710. void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexcept
  711. {
  712. /* TODO: Can this be anything else? Long, Float, Double? */
  713. uint32_t nvals{}, choiceType{};
  714. value = spa_pod_get_values(value, &nvals, &choiceType);
  715. const uint podType{get_pod_type(value)};
  716. if(podType != SPA_TYPE_Int)
  717. {
  718. WARN(" Unhandled sample rate POD type: {}", podType);
  719. return;
  720. }
  721. if(choiceType == SPA_CHOICE_Range)
  722. {
  723. if(nvals != 3)
  724. {
  725. WARN(" Unexpected SPA_CHOICE_Range count: {}", nvals);
  726. return;
  727. }
  728. auto srates = get_pod_body<int32_t,3>(value);
  729. /* [0] is the default, [1] is the min, and [2] is the max. */
  730. TRACE(" sample rate: {}, range: {}", srates[0], srates.subspan<1>());
  731. if(!mSampleRate || force_update)
  732. mSampleRate = static_cast<uint>(std::clamp<int>(srates[0], MinOutputRate,
  733. MaxOutputRate));
  734. return;
  735. }
  736. if(choiceType == SPA_CHOICE_Enum)
  737. {
  738. if(nvals == 0)
  739. {
  740. WARN(" Unexpected SPA_CHOICE_Enum count: {}", nvals);
  741. return;
  742. }
  743. auto srates = get_pod_body<int32_t>(value, nvals);
  744. /* [0] is the default, [1...size()-1] are available selections. */
  745. TRACE(" sample rate: {}, list: {}", srates[0], srates.subspan(1));
  746. /* Pick the first rate listed that's within the allowed range (default
  747. * rate if possible).
  748. */
  749. for(const auto &rate : srates)
  750. {
  751. if(rate >= int{MinOutputRate} && rate <= int{MaxOutputRate})
  752. {
  753. if(!mSampleRate || force_update)
  754. mSampleRate = static_cast<uint>(rate);
  755. break;
  756. }
  757. }
  758. return;
  759. }
  760. if(choiceType == SPA_CHOICE_None)
  761. {
  762. if(nvals != 1)
  763. {
  764. WARN(" Unexpected SPA_CHOICE_None count: {}", nvals);
  765. return;
  766. }
  767. auto srates = get_pod_body<int32_t,1>(value);
  768. TRACE(" sample rate: {}", srates[0]);
  769. if(!mSampleRate || force_update)
  770. mSampleRate = static_cast<uint>(std::clamp<int>(srates[0], MinOutputRate,
  771. MaxOutputRate));
  772. return;
  773. }
  774. WARN(" Unhandled sample rate choice type: {}", choiceType);
  775. }
  776. void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcept
  777. {
  778. uint32_t choiceCount{}, choiceType{};
  779. value = spa_pod_get_values(value, &choiceCount, &choiceType);
  780. if(choiceType != SPA_CHOICE_None || choiceCount != 1)
  781. {
  782. ERR(" Unexpected positions choice: type={}, count={}", choiceType, choiceCount);
  783. return;
  784. }
  785. const auto chanmap = get_array_span<SPA_TYPE_Id>(value);
  786. if(chanmap.empty()) return;
  787. if(mChannels == InvalidChannelConfig || force_update)
  788. {
  789. mIs51Rear = false;
  790. if(MatchChannelMap(chanmap, X714Map))
  791. mChannels = DevFmtX714;
  792. else if(MatchChannelMap(chanmap, X71Map))
  793. mChannels = DevFmtX71;
  794. else if(MatchChannelMap(chanmap, X61Map))
  795. mChannels = DevFmtX61;
  796. else if(MatchChannelMap(chanmap, X51Map))
  797. mChannels = DevFmtX51;
  798. else if(MatchChannelMap(chanmap, X51RearMap))
  799. {
  800. mChannels = DevFmtX51;
  801. mIs51Rear = true;
  802. }
  803. else if(MatchChannelMap(chanmap, QuadMap))
  804. mChannels = DevFmtQuad;
  805. else if(MatchChannelMap(chanmap, StereoMap))
  806. mChannels = DevFmtStereo;
  807. else
  808. mChannels = DevFmtMono;
  809. }
  810. TRACE(" {} position{} for {}{}", chanmap.size(), (chanmap.size()==1)?"":"s",
  811. DevFmtChannelsString(mChannels), mIs51Rear?"(rear)":"");
  812. }
  813. void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noexcept
  814. {
  815. /* As a fallback with just a channel count, just assume mono or stereo. */
  816. uint32_t choiceCount{}, choiceType{};
  817. value = spa_pod_get_values(value, &choiceCount, &choiceType);
  818. if(choiceType != SPA_CHOICE_None || choiceCount != 1)
  819. {
  820. ERR(" Unexpected positions choice: type={}, count={}", choiceType, choiceCount);
  821. return;
  822. }
  823. const auto chancount = get_value<SPA_TYPE_Int>(value);
  824. if(!chancount) return;
  825. if(mChannels == InvalidChannelConfig || force_update)
  826. {
  827. mIs51Rear = false;
  828. if(*chancount >= 2)
  829. mChannels = DevFmtStereo;
  830. else if(*chancount >= 1)
  831. mChannels = DevFmtMono;
  832. }
  833. TRACE(" {} channel{} for {}", *chancount, (*chancount==1)?"":"s",
  834. DevFmtChannelsString(mChannels));
  835. }
  836. [[nodiscard]] constexpr auto GetMonitorPrefix() noexcept { return "Monitor of "sv; }
  837. [[nodiscard]] constexpr auto GetMonitorSuffix() noexcept { return ".monitor"sv; }
  838. [[nodiscard]] constexpr auto GetAudioSinkClassName() noexcept { return "Audio/Sink"sv; }
  839. [[nodiscard]] constexpr auto GetAudioSourceClassName() noexcept { return "Audio/Source"sv; }
  840. [[nodiscard]] constexpr auto GetAudioDuplexClassName() noexcept { return "Audio/Duplex"sv; }
  841. [[nodiscard]] constexpr auto GetAudioSourceVirtualClassName() noexcept
  842. { return "Audio/Source/Virtual"sv; }
  843. void NodeProxy::infoCallback(void*, const pw_node_info *info) noexcept
  844. {
  845. /* We only care about property changes here (media class, name/desc).
  846. * Format changes will automatically invoke the param callback.
  847. *
  848. * TODO: Can the media class or name/desc change without being removed and
  849. * readded?
  850. */
  851. if((info->change_mask&PW_NODE_CHANGE_MASK_PROPS))
  852. {
  853. /* Can this actually change? */
  854. const char *media_class{spa_dict_lookup(info->props, PW_KEY_MEDIA_CLASS)};
  855. if(!media_class) UNLIKELY return;
  856. const std::string_view className{media_class};
  857. NodeType ntype{};
  858. if(al::case_compare(className, GetAudioSinkClassName()) == 0)
  859. ntype = NodeType::Sink;
  860. else if(al::case_compare(className, GetAudioSourceClassName()) == 0
  861. || al::case_compare(className, GetAudioSourceVirtualClassName()) == 0)
  862. ntype = NodeType::Source;
  863. else if(al::case_compare(className, GetAudioDuplexClassName()) == 0)
  864. ntype = NodeType::Duplex;
  865. else
  866. {
  867. TRACE("Dropping device node {} which became type \"{}\"", info->id, media_class);
  868. DeviceNode::Remove(info->id);
  869. return;
  870. }
  871. const char *devName{spa_dict_lookup(info->props, PW_KEY_NODE_NAME)};
  872. const char *nodeName{spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION)};
  873. if(!nodeName || !*nodeName) nodeName = spa_dict_lookup(info->props, PW_KEY_NODE_NICK);
  874. if(!nodeName || !*nodeName) nodeName = devName;
  875. uint64_t serial_id{info->id};
  876. #ifdef PW_KEY_OBJECT_SERIAL
  877. if(const char *serial_str{spa_dict_lookup(info->props, PW_KEY_OBJECT_SERIAL)})
  878. {
  879. errno = 0;
  880. char *serial_end{};
  881. serial_id = std::strtoull(serial_str, &serial_end, 0);
  882. if(*serial_end != '\0' || errno == ERANGE)
  883. {
  884. ERR("Unexpected object serial: {}", serial_str);
  885. serial_id = info->id;
  886. }
  887. }
  888. #endif
  889. auto name = std::invoke([nodeName,info]() -> std::string
  890. {
  891. if(nodeName && *nodeName)
  892. return std::string{nodeName};
  893. return fmt::format("PipeWire node #{}", info->id);
  894. });
  895. const char *form_factor{spa_dict_lookup(info->props, PW_KEY_DEVICE_FORM_FACTOR)};
  896. TRACE("Got {} device \"{}\"{}{}{}", AsString(ntype), devName ? devName : "(nil)",
  897. form_factor?" (":"", form_factor?form_factor:"", form_factor?")":"");
  898. TRACE(" \"{}\" = ID {}", name, serial_id);
  899. DeviceNode &node = DeviceNode::Add(info->id);
  900. node.mSerial = serial_id;
  901. /* This method is called both to notify about a new sink/source node,
  902. * and update properties for the node. It's unclear what properties can
  903. * change for an existing node without being removed first, so err on
  904. * the side of caution: send a DeviceRemoved event if it had a name
  905. * that's being changed, and send a DeviceAdded event when the name
  906. * differs or it didn't have one.
  907. *
  908. * The DeviceRemoved event needs to be called before the potentially
  909. * new NodeType is set, so the removal event is called for the previous
  910. * device type, while the DeviceAdded event needs to be called after.
  911. *
  912. * This is overkill if the node type, name, and devname can't change.
  913. */
  914. bool notifyAdd{false};
  915. if(node.mName != name)
  916. {
  917. if(gEventHandler.initIsDone(std::memory_order_relaxed))
  918. {
  919. if(!node.mName.empty())
  920. {
  921. const std::string msg{"Device removed: "+node.mName};
  922. node.callEvent(alc::EventType::DeviceRemoved, msg);
  923. }
  924. notifyAdd = true;
  925. }
  926. node.mName = std::move(name);
  927. }
  928. node.mDevName = devName ? devName : "";
  929. node.mType = ntype;
  930. node.mIsHeadphones = form_factor && (al::case_compare(form_factor, "headphones"sv) == 0
  931. || al::case_compare(form_factor, "headset"sv) == 0);
  932. if(notifyAdd)
  933. {
  934. const std::string msg{"Device added: "+node.mName};
  935. node.callEvent(alc::EventType::DeviceAdded, msg);
  936. }
  937. }
  938. }
  939. void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_pod *param) const noexcept
  940. {
  941. if(id == SPA_PARAM_EnumFormat || id == SPA_PARAM_Format)
  942. {
  943. DeviceNode *node{DeviceNode::Find(mId)};
  944. if(!node) UNLIKELY return;
  945. TRACE("Device ID {} {} format{}:", node->mSerial,
  946. (id == SPA_PARAM_EnumFormat) ? "available" : "current",
  947. (id == SPA_PARAM_EnumFormat) ? "s" : "");
  948. const bool force_update{id == SPA_PARAM_Format};
  949. if(const spa_pod_prop *prop{spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_rate)})
  950. node->parseSampleRate(&prop->value, force_update);
  951. if(const spa_pod_prop *prop{spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_position)})
  952. node->parsePositions(&prop->value, force_update);
  953. else
  954. {
  955. prop = spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_channels);
  956. if(prop) node->parseChannelCount(&prop->value, force_update);
  957. }
  958. }
  959. }
  960. auto MetadataProxy::propertyCallback(void*, uint32_t id, const char *key, const char *type,
  961. const char *value) noexcept -> int
  962. {
  963. if(id != PW_ID_CORE)
  964. return 0;
  965. bool isCapture{};
  966. if("default.audio.sink"sv == key)
  967. isCapture = false;
  968. else if("default.audio.source"sv == key)
  969. isCapture = true;
  970. else
  971. return 0;
  972. if(!type)
  973. {
  974. TRACE("Default {} device cleared", isCapture ? "capture" : "playback");
  975. if(!isCapture) DefaultSinkDevice.clear();
  976. else DefaultSourceDevice.clear();
  977. return 0;
  978. }
  979. if("Spa:String:JSON"sv != type)
  980. {
  981. ERR("Unexpected {} property type: {}", key, type);
  982. return 0;
  983. }
  984. std::array<spa_json,2> it{};
  985. spa_json_init(it.data(), value, strlen(value));
  986. if(spa_json_enter_object(&std::get<0>(it), &std::get<1>(it)) <= 0)
  987. return 0;
  988. auto get_json_string = [](spa_json *iter)
  989. {
  990. std::optional<std::string> str;
  991. const char *val{};
  992. int len{spa_json_next(iter, &val)};
  993. if(len <= 0) return str;
  994. str.emplace(static_cast<uint>(len), '\0');
  995. if(spa_json_parse_string(val, len, str->data()) <= 0)
  996. str.reset();
  997. else while(!str->empty() && str->back() == '\0')
  998. str->pop_back();
  999. return str;
  1000. };
  1001. while(auto propKey = get_json_string(&std::get<1>(it)))
  1002. {
  1003. if("name"sv == *propKey)
  1004. {
  1005. auto propValue = get_json_string(&std::get<1>(it));
  1006. if(!propValue) break;
  1007. TRACE("Got default {} device \"{}\"", isCapture ? "capture" : "playback",
  1008. *propValue);
  1009. if(!isCapture && DefaultSinkDevice != *propValue)
  1010. {
  1011. if(gEventHandler.mInitDone.load(std::memory_order_relaxed))
  1012. {
  1013. auto entry = DeviceNode::FindByDevName(*propValue);
  1014. const std::string message{"Default playback device changed: "+
  1015. (entry ? entry->mName : std::string{})};
  1016. alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback,
  1017. message);
  1018. }
  1019. DefaultSinkDevice = std::move(*propValue);
  1020. }
  1021. else if(isCapture && DefaultSourceDevice != *propValue)
  1022. {
  1023. if(gEventHandler.mInitDone.load(std::memory_order_relaxed))
  1024. {
  1025. auto entry = DeviceNode::FindByDevName(*propValue);
  1026. const std::string message{"Default capture device changed: "+
  1027. (entry ? entry->mName : std::string{})};
  1028. alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture,
  1029. message);
  1030. }
  1031. DefaultSourceDevice = std::move(*propValue);
  1032. }
  1033. }
  1034. else
  1035. {
  1036. const char *v{};
  1037. if(spa_json_next(&std::get<1>(it), &v) <= 0)
  1038. break;
  1039. }
  1040. }
  1041. return 0;
  1042. }
  1043. bool EventManager::init()
  1044. {
  1045. mLoop = ThreadMainloop::Create("PWEventThread");
  1046. if(!mLoop)
  1047. {
  1048. ERR("Failed to create PipeWire event thread loop (errno: {})", errno);
  1049. return false;
  1050. }
  1051. mContext = mLoop.newContext();
  1052. if(!mContext)
  1053. {
  1054. ERR("Failed to create PipeWire event context (errno: {})", errno);
  1055. return false;
  1056. }
  1057. mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)};
  1058. if(!mCore)
  1059. {
  1060. ERR("Failed to connect PipeWire event context (errno: {})", errno);
  1061. return false;
  1062. }
  1063. mRegistry = PwRegistryPtr{pw_core_get_registry(mCore.get(), PW_VERSION_REGISTRY, 0)};
  1064. if(!mRegistry)
  1065. {
  1066. ERR("Failed to get PipeWire event registry (errno: {})", errno);
  1067. return false;
  1068. }
  1069. static constexpr pw_core_events coreEvents{CreateCoreEvents()};
  1070. static constexpr pw_registry_events registryEvents{CreateRegistryEvents()};
  1071. ppw_core_add_listener(mCore.get(), &mCoreListener, &coreEvents, this);
  1072. ppw_registry_add_listener(mRegistry.get(), &mRegistryListener, &registryEvents, this);
  1073. /* Set an initial sequence ID for initialization, to trigger after the
  1074. * registry is first populated.
  1075. */
  1076. mInitSeq = ppw_core_sync(mCore.get(), PW_ID_CORE, 0);
  1077. if(int res{mLoop.start()})
  1078. {
  1079. ERR("Failed to start PipeWire event thread loop (res: {})", res);
  1080. return false;
  1081. }
  1082. return true;
  1083. }
  1084. void EventManager::kill()
  1085. {
  1086. if(mLoop) mLoop.stop();
  1087. mDefaultMetadata.reset();
  1088. mNodeList.clear();
  1089. mRegistry = nullptr;
  1090. mCore = nullptr;
  1091. mContext = nullptr;
  1092. mLoop = nullptr;
  1093. }
  1094. void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t version,
  1095. const spa_dict *props) noexcept
  1096. {
  1097. /* We're only interested in interface nodes. */
  1098. if(std::strcmp(type, PW_TYPE_INTERFACE_Node) == 0)
  1099. {
  1100. const char *media_class{spa_dict_lookup(props, PW_KEY_MEDIA_CLASS)};
  1101. if(!media_class) return;
  1102. const std::string_view className{media_class};
  1103. /* Specifically, audio sinks and sources (and duplexes). */
  1104. const bool isGood{al::case_compare(className, GetAudioSinkClassName()) == 0
  1105. || al::case_compare(className, GetAudioSourceClassName()) == 0
  1106. || al::case_compare(className, GetAudioSourceVirtualClassName()) == 0
  1107. || al::case_compare(className, GetAudioDuplexClassName()) == 0};
  1108. if(!isGood)
  1109. {
  1110. if(!al::contains(className, "/Video"sv) && !al::starts_with(className, "Stream/"sv))
  1111. TRACE("Ignoring node class {}", media_class);
  1112. return;
  1113. }
  1114. /* Create the proxy object. */
  1115. auto node = PwNodePtr{static_cast<pw_node*>(pw_registry_bind(mRegistry.get(), id, type,
  1116. version, 0))};
  1117. if(!node)
  1118. {
  1119. ERR("Failed to create node proxy object (errno: {})", errno);
  1120. return;
  1121. }
  1122. /* Initialize the NodeProxy to hold the node object, add it to the
  1123. * active node list, and update the sync point.
  1124. */
  1125. mNodeList.emplace_back(std::make_unique<NodeProxy>(id, std::move(node)));
  1126. syncInit();
  1127. /* Signal any waiters that we have found a source or sink for audio
  1128. * support.
  1129. */
  1130. if(!mHasAudio.exchange(true, std::memory_order_acq_rel))
  1131. mLoop.signal(false);
  1132. }
  1133. else if(std::strcmp(type, PW_TYPE_INTERFACE_Metadata) == 0)
  1134. {
  1135. const char *data_class{spa_dict_lookup(props, PW_KEY_METADATA_NAME)};
  1136. if(!data_class) return;
  1137. if("default"sv != data_class)
  1138. {
  1139. TRACE("Ignoring metadata \"{}\"", data_class);
  1140. return;
  1141. }
  1142. if(mDefaultMetadata)
  1143. {
  1144. ERR("Duplicate default metadata");
  1145. return;
  1146. }
  1147. auto mdata = PwMetadataPtr{static_cast<pw_metadata*>(pw_registry_bind(mRegistry.get(), id,
  1148. type, version, 0))};
  1149. if(!mdata)
  1150. {
  1151. ERR("Failed to create metadata proxy object (errno: {})", errno);
  1152. return;
  1153. }
  1154. mDefaultMetadata.emplace(id, std::move(mdata));
  1155. syncInit();
  1156. }
  1157. }
  1158. void EventManager::removeCallback(uint32_t id) noexcept
  1159. {
  1160. DeviceNode::Remove(id);
  1161. auto clear_node = [id](std::unique_ptr<NodeProxy> &node) noexcept
  1162. { return node->mId == id; };
  1163. auto node_end = std::remove_if(mNodeList.begin(), mNodeList.end(), clear_node);
  1164. mNodeList.erase(node_end, mNodeList.end());
  1165. if(mDefaultMetadata && mDefaultMetadata->mId == id)
  1166. mDefaultMetadata.reset();
  1167. }
  1168. void EventManager::coreCallback(uint32_t id, int seq) noexcept
  1169. {
  1170. if(id == PW_ID_CORE && seq == mInitSeq)
  1171. {
  1172. /* Initialization done. Remove this callback and signal anyone that may
  1173. * be waiting.
  1174. */
  1175. spa_hook_remove(&mCoreListener);
  1176. mInitDone.store(true);
  1177. mLoop.signal(false);
  1178. }
  1179. }
  1180. enum use_f32p_e : bool { UseDevType=false, ForceF32Planar=true };
  1181. spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e use_f32p)
  1182. {
  1183. spa_audio_info_raw info{};
  1184. if(use_f32p)
  1185. {
  1186. device->FmtType = DevFmtFloat;
  1187. info.format = SPA_AUDIO_FORMAT_F32P;
  1188. }
  1189. else switch(device->FmtType)
  1190. {
  1191. case DevFmtByte: info.format = SPA_AUDIO_FORMAT_S8; break;
  1192. case DevFmtUByte: info.format = SPA_AUDIO_FORMAT_U8; break;
  1193. case DevFmtShort: info.format = SPA_AUDIO_FORMAT_S16; break;
  1194. case DevFmtUShort: info.format = SPA_AUDIO_FORMAT_U16; break;
  1195. case DevFmtInt: info.format = SPA_AUDIO_FORMAT_S32; break;
  1196. case DevFmtUInt: info.format = SPA_AUDIO_FORMAT_U32; break;
  1197. case DevFmtFloat: info.format = SPA_AUDIO_FORMAT_F32; break;
  1198. }
  1199. info.rate = device->mSampleRate;
  1200. al::span<const spa_audio_channel> map{};
  1201. switch(device->FmtChans)
  1202. {
  1203. case DevFmtMono: map = MonoMap; break;
  1204. case DevFmtStereo: map = StereoMap; break;
  1205. case DevFmtQuad: map = QuadMap; break;
  1206. case DevFmtX51:
  1207. if(is51rear) map = X51RearMap;
  1208. else map = X51Map;
  1209. break;
  1210. case DevFmtX61: map = X61Map; break;
  1211. case DevFmtX71: map = X71Map; break;
  1212. case DevFmtX714: map = X714Map; break;
  1213. case DevFmtX3D71: map = X71Map; break;
  1214. case DevFmtX7144:
  1215. case DevFmtAmbi3D:
  1216. info.flags |= SPA_AUDIO_FLAG_UNPOSITIONED;
  1217. info.channels = device->channelsFromFmt();
  1218. break;
  1219. }
  1220. if(!map.empty())
  1221. {
  1222. info.channels = static_cast<uint32_t>(map.size());
  1223. std::copy(map.begin(), map.end(), std::begin(info.position));
  1224. }
  1225. return info;
  1226. }
  1227. class PipeWirePlayback final : public BackendBase {
  1228. void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error) noexcept;
  1229. void ioChangedCallback(uint32_t id, void *area, uint32_t size) noexcept;
  1230. void outputCallback() noexcept;
  1231. void open(std::string_view name) override;
  1232. bool reset() override;
  1233. void start() override;
  1234. void stop() override;
  1235. ClockLatency getClockLatency() override;
  1236. uint64_t mTargetId{PwIdAny};
  1237. nanoseconds mTimeBase{0};
  1238. ThreadMainloop mLoop;
  1239. PwContextPtr mContext;
  1240. PwCorePtr mCore;
  1241. PwStreamPtr mStream;
  1242. spa_hook mStreamListener{};
  1243. spa_io_rate_match *mRateMatch{};
  1244. std::vector<void*> mChannelPtrs;
  1245. static constexpr pw_stream_events CreateEvents()
  1246. {
  1247. pw_stream_events ret{};
  1248. ret.version = PW_VERSION_STREAM_EVENTS;
  1249. ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) noexcept
  1250. { static_cast<PipeWirePlayback*>(data)->stateChangedCallback(old, state, error); };
  1251. ret.io_changed = [](void *data, uint32_t id, void *area, uint32_t size) noexcept
  1252. { static_cast<PipeWirePlayback*>(data)->ioChangedCallback(id, area, size); };
  1253. ret.process = [](void *data) noexcept
  1254. { static_cast<PipeWirePlayback*>(data)->outputCallback(); };
  1255. return ret;
  1256. }
  1257. public:
  1258. explicit PipeWirePlayback(DeviceBase *device) noexcept : BackendBase{device} { }
  1259. ~PipeWirePlayback() final
  1260. {
  1261. /* Stop the mainloop so the stream can be properly destroyed. */
  1262. if(mLoop) mLoop.stop();
  1263. }
  1264. };
  1265. void PipeWirePlayback::stateChangedCallback(pw_stream_state, pw_stream_state, const char*) noexcept
  1266. { mLoop.signal(false); }
  1267. void PipeWirePlayback::ioChangedCallback(uint32_t id, void *area, uint32_t size) noexcept
  1268. {
  1269. switch(id)
  1270. {
  1271. case SPA_IO_RateMatch:
  1272. if(size >= sizeof(spa_io_rate_match))
  1273. mRateMatch = static_cast<spa_io_rate_match*>(area);
  1274. else
  1275. mRateMatch = nullptr;
  1276. break;
  1277. }
  1278. }
  1279. void PipeWirePlayback::outputCallback() noexcept
  1280. {
  1281. pw_buffer *pw_buf{pw_stream_dequeue_buffer(mStream.get())};
  1282. if(!pw_buf) UNLIKELY return;
  1283. const al::span<spa_data> datas{pw_buf->buffer->datas,
  1284. std::min(mChannelPtrs.size(), size_t{pw_buf->buffer->n_datas})};
  1285. #if PW_CHECK_VERSION(0,3,49)
  1286. /* In 0.3.49, pw_buffer::requested specifies the number of samples needed
  1287. * by the resampler/graph for this audio update.
  1288. */
  1289. uint length{static_cast<uint>(pw_buf->requested)};
  1290. #else
  1291. /* In 0.3.48 and earlier, spa_io_rate_match::size apparently has the number
  1292. * of samples per update.
  1293. */
  1294. uint length{mRateMatch ? mRateMatch->size : 0u};
  1295. #endif
  1296. /* If no length is specified, use the device's update size as a fallback. */
  1297. if(!length) UNLIKELY length = mDevice->mUpdateSize;
  1298. /* For planar formats, each datas[] seems to contain one channel, so store
  1299. * the pointers in an array. Limit the render length in case the available
  1300. * buffer length in any one channel is smaller than we wanted (shouldn't
  1301. * be, but just in case).
  1302. */
  1303. auto chanptr_end = mChannelPtrs.begin();
  1304. for(const auto &data : datas)
  1305. {
  1306. length = std::min(length, data.maxsize/uint{sizeof(float)});
  1307. *chanptr_end = data.data;
  1308. ++chanptr_end;
  1309. data.chunk->offset = 0;
  1310. data.chunk->stride = sizeof(float);
  1311. data.chunk->size = length * sizeof(float);
  1312. }
  1313. mDevice->renderSamples(mChannelPtrs, length);
  1314. pw_buf->size = length;
  1315. pw_stream_queue_buffer(mStream.get(), pw_buf);
  1316. }
  1317. void PipeWirePlayback::open(std::string_view name)
  1318. {
  1319. static std::atomic<uint> OpenCount{0};
  1320. uint64_t targetid{PwIdAny};
  1321. std::string devname{};
  1322. gEventHandler.waitForInit();
  1323. if(name.empty())
  1324. {
  1325. EventWatcherLockGuard evtlock{gEventHandler};
  1326. auto&& devlist = DeviceNode::GetList();
  1327. auto match = devlist.cend();
  1328. if(!DefaultSinkDevice.empty())
  1329. {
  1330. auto match_default = [](const DeviceNode &n) -> bool
  1331. { return n.mDevName == DefaultSinkDevice; };
  1332. match = std::find_if(devlist.cbegin(), devlist.cend(), match_default);
  1333. }
  1334. if(match == devlist.cend())
  1335. {
  1336. auto match_playback = [](const DeviceNode &n) -> bool
  1337. { return n.mType != NodeType::Source; };
  1338. match = std::find_if(devlist.cbegin(), devlist.cend(), match_playback);
  1339. if(match == devlist.cend())
  1340. throw al::backend_exception{al::backend_error::NoDevice,
  1341. "No PipeWire playback device found"};
  1342. }
  1343. targetid = match->mSerial;
  1344. devname = match->mName;
  1345. }
  1346. else
  1347. {
  1348. EventWatcherLockGuard evtlock{gEventHandler};
  1349. auto&& devlist = DeviceNode::GetList();
  1350. auto match_name = [name](const DeviceNode &n) -> bool
  1351. { return n.mType != NodeType::Source && (n.mName == name || n.mDevName == name); };
  1352. auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name);
  1353. if(match == devlist.cend())
  1354. throw al::backend_exception{al::backend_error::NoDevice,
  1355. "Device name \"{}\" not found", name};
  1356. targetid = match->mSerial;
  1357. devname = match->mName;
  1358. }
  1359. if(!mLoop)
  1360. {
  1361. const auto count = OpenCount.fetch_add(1u, std::memory_order_relaxed);
  1362. const auto thread_name = fmt::format("ALSoftP{}", count);
  1363. mLoop = ThreadMainloop::Create(thread_name.c_str());
  1364. if(!mLoop)
  1365. throw al::backend_exception{al::backend_error::DeviceError,
  1366. "Failed to create PipeWire mainloop (errno: {})", errno};
  1367. if(int res{mLoop.start()})
  1368. throw al::backend_exception{al::backend_error::DeviceError,
  1369. "Failed to start PipeWire mainloop (res: {})", res};
  1370. }
  1371. MainloopUniqueLock mlock{mLoop};
  1372. if(!mContext)
  1373. {
  1374. pw_properties *cprops{pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf", nullptr)};
  1375. mContext = mLoop.newContext(cprops);
  1376. if(!mContext)
  1377. throw al::backend_exception{al::backend_error::DeviceError,
  1378. "Failed to create PipeWire event context (errno: {})\n", errno};
  1379. }
  1380. if(!mCore)
  1381. {
  1382. mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)};
  1383. if(!mCore)
  1384. throw al::backend_exception{al::backend_error::DeviceError,
  1385. "Failed to connect PipeWire event context (errno: {})\n", errno};
  1386. }
  1387. mlock.unlock();
  1388. /* TODO: Ensure the target ID is still valid/usable and accepts streams. */
  1389. mTargetId = targetid;
  1390. if(!devname.empty())
  1391. mDeviceName = std::move(devname);
  1392. else
  1393. mDeviceName = "PipeWire Output"sv;
  1394. }
  1395. bool PipeWirePlayback::reset()
  1396. {
  1397. if(mStream)
  1398. {
  1399. MainloopLockGuard looplock{mLoop};
  1400. mStream = nullptr;
  1401. }
  1402. mStreamListener = {};
  1403. mRateMatch = nullptr;
  1404. mTimeBase = mDevice->getClockTime();
  1405. /* If connecting to a specific device, update various device parameters to
  1406. * match its format.
  1407. */
  1408. bool is51rear{false};
  1409. mDevice->Flags.reset(DirectEar);
  1410. if(mTargetId != PwIdAny)
  1411. {
  1412. EventWatcherLockGuard evtlock{gEventHandler};
  1413. auto&& devlist = DeviceNode::GetList();
  1414. auto match_id = [targetid=mTargetId](const DeviceNode &n) -> bool
  1415. { return targetid == n.mSerial; };
  1416. auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_id);
  1417. if(match != devlist.cend())
  1418. {
  1419. if(!mDevice->Flags.test(FrequencyRequest) && match->mSampleRate > 0)
  1420. {
  1421. /* Scale the update size if the sample rate changes. */
  1422. const double scale{static_cast<double>(match->mSampleRate) / mDevice->mSampleRate};
  1423. const double updatesize{std::round(mDevice->mUpdateSize * scale)};
  1424. const double buffersize{std::round(mDevice->mBufferSize * scale)};
  1425. mDevice->mSampleRate = match->mSampleRate;
  1426. mDevice->mUpdateSize = static_cast<uint>(std::clamp(updatesize, 64.0, 8192.0));
  1427. mDevice->mBufferSize = static_cast<uint>(std::max(buffersize, 128.0));
  1428. }
  1429. if(!mDevice->Flags.test(ChannelsRequest) && match->mChannels != InvalidChannelConfig)
  1430. mDevice->FmtChans = match->mChannels;
  1431. if(match->mChannels == DevFmtStereo && match->mIsHeadphones)
  1432. mDevice->Flags.set(DirectEar);
  1433. is51rear = match->mIs51Rear;
  1434. }
  1435. }
  1436. /* Force planar 32-bit float output for playback. This is what PipeWire
  1437. * handles internally, and it's easier for us too.
  1438. */
  1439. auto info = spa_audio_info_raw{make_spa_info(mDevice, is51rear, ForceF32Planar)};
  1440. auto b = PodDynamicBuilder{};
  1441. auto params = as_const_ptr(spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info));
  1442. if(!params)
  1443. throw al::backend_exception{al::backend_error::DeviceError,
  1444. "Failed to set PipeWire audio format parameters"};
  1445. /* TODO: Which properties are actually needed here? Any others that could
  1446. * be useful?
  1447. */
  1448. auto&& binary = GetProcBinary();
  1449. const char *appname{!binary.fname.empty() ? binary.fname.c_str() : "OpenAL Soft"};
  1450. pw_properties *props{pw_properties_new(PW_KEY_NODE_NAME, appname,
  1451. PW_KEY_NODE_DESCRIPTION, appname,
  1452. PW_KEY_MEDIA_TYPE, "Audio",
  1453. PW_KEY_MEDIA_CATEGORY, "Playback",
  1454. PW_KEY_MEDIA_ROLE, "Game",
  1455. PW_KEY_NODE_ALWAYS_PROCESS, "true",
  1456. nullptr)};
  1457. if(!props)
  1458. throw al::backend_exception{al::backend_error::DeviceError,
  1459. "Failed to create PipeWire stream properties (errno: {})", errno};
  1460. pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", mDevice->mUpdateSize,
  1461. mDevice->mSampleRate);
  1462. pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->mSampleRate);
  1463. #ifdef PW_KEY_TARGET_OBJECT
  1464. pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%" PRIu64, mTargetId);
  1465. #else
  1466. pw_properties_setf(props, PW_KEY_NODE_TARGET, "%" PRIu64, mTargetId);
  1467. #endif
  1468. MainloopUniqueLock plock{mLoop};
  1469. /* The stream takes overship of 'props', even in the case of failure. */
  1470. mStream = PwStreamPtr{pw_stream_new(mCore.get(), "Playback Stream", props)};
  1471. if(!mStream)
  1472. throw al::backend_exception{al::backend_error::NoDevice,
  1473. "Failed to create PipeWire stream (errno: {})", errno};
  1474. static constexpr pw_stream_events streamEvents{CreateEvents()};
  1475. pw_stream_add_listener(mStream.get(), &mStreamListener, &streamEvents, this);
  1476. pw_stream_flags flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE
  1477. | PW_STREAM_FLAG_MAP_BUFFERS};
  1478. if(GetConfigValueBool(mDevice->mDeviceName, "pipewire", "rt-mix", false))
  1479. flags |= PW_STREAM_FLAG_RT_PROCESS;
  1480. if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_OUTPUT, PwIdAny, flags, &params, 1)})
  1481. throw al::backend_exception{al::backend_error::DeviceError,
  1482. "Error connecting PipeWire stream (res: {})", res};
  1483. /* Wait for the stream to become paused (ready to start streaming). */
  1484. plock.wait([stream=mStream.get()]()
  1485. {
  1486. const char *error{};
  1487. pw_stream_state state{pw_stream_get_state(stream, &error)};
  1488. if(state == PW_STREAM_STATE_ERROR)
  1489. throw al::backend_exception{al::backend_error::DeviceError,
  1490. "Error connecting PipeWire stream: \"{}\"", error};
  1491. return state == PW_STREAM_STATE_PAUSED;
  1492. });
  1493. /* TODO: Update mDevice->mUpdateSize with the stream's quantum, and
  1494. * mDevice->mBufferSize with the total known buffering delay from the head
  1495. * of this playback stream to the tail of the device output.
  1496. *
  1497. * This info is apparently not available until after the stream starts.
  1498. */
  1499. plock.unlock();
  1500. mChannelPtrs.resize(mDevice->channelsFromFmt());
  1501. setDefaultWFXChannelOrder();
  1502. return true;
  1503. }
  1504. void PipeWirePlayback::start()
  1505. {
  1506. MainloopUniqueLock plock{mLoop};
  1507. if(int res{pw_stream_set_active(mStream.get(), true)})
  1508. throw al::backend_exception{al::backend_error::DeviceError,
  1509. "Failed to start PipeWire stream (res: {})", res};
  1510. /* Wait for the stream to start playing (would be nice to not, but we need
  1511. * the actual update size which is only available after starting).
  1512. */
  1513. plock.wait([stream=mStream.get()]()
  1514. {
  1515. const char *error{};
  1516. pw_stream_state state{pw_stream_get_state(stream, &error)};
  1517. if(state == PW_STREAM_STATE_ERROR)
  1518. throw al::backend_exception{al::backend_error::DeviceError,
  1519. "PipeWire stream error: {}", error ? error : "(unknown)"};
  1520. return state == PW_STREAM_STATE_STREAMING;
  1521. });
  1522. /* HACK: Try to work out the update size and total buffering size. There's
  1523. * no actual query for this, so we have to work it out from the stream time
  1524. * info, and assume it stays accurate with future updates. The stream time
  1525. * info may also not be available right away, so we have to wait until it
  1526. * is (up to about 2 seconds).
  1527. */
  1528. int wait_count{100};
  1529. do {
  1530. pw_time ptime{};
  1531. if(int res{pw_stream_get_time_n(mStream.get(), &ptime, sizeof(ptime))})
  1532. {
  1533. ERR("Failed to get PipeWire stream time (res: {})", res);
  1534. break;
  1535. }
  1536. /* The rate match size is the update size for each buffer. */
  1537. const uint updatesize{mRateMatch ? mRateMatch->size : 0u};
  1538. #if PW_CHECK_VERSION(0,3,50)
  1539. /* Assume ptime.avail_buffers+ptime.queued_buffers is the target buffer
  1540. * queue size.
  1541. */
  1542. if(ptime.rate.denom > 0 && (ptime.avail_buffers || ptime.queued_buffers) && updatesize > 0)
  1543. {
  1544. const uint totalbuffers{ptime.avail_buffers + ptime.queued_buffers};
  1545. /* Ensure the delay is in sample frames. */
  1546. const uint64_t delay{static_cast<uint64_t>(ptime.delay) * mDevice->mSampleRate *
  1547. ptime.rate.num / ptime.rate.denom};
  1548. mDevice->mUpdateSize = updatesize;
  1549. mDevice->mBufferSize = static_cast<uint>(ptime.buffered + delay +
  1550. uint64_t{totalbuffers}*updatesize);
  1551. break;
  1552. }
  1553. #else
  1554. /* Prior to 0.3.50, we can only measure the delay with the update size,
  1555. * assuming one buffer and no resample buffering.
  1556. */
  1557. if(ptime.rate.denom > 0 && updatesize > 0)
  1558. {
  1559. /* Ensure the delay is in sample frames. */
  1560. const uint64_t delay{static_cast<uint64_t>(ptime.delay) * mDevice->mSampleRate *
  1561. ptime.rate.num / ptime.rate.denom};
  1562. mDevice->mUpdateSize = updatesize;
  1563. mDevice->mBufferSize = static_cast<uint>(delay + updatesize);
  1564. break;
  1565. }
  1566. #endif
  1567. if(!--wait_count)
  1568. {
  1569. ERR("Timeout getting PipeWire stream buffering info");
  1570. break;
  1571. }
  1572. plock.unlock();
  1573. std::this_thread::sleep_for(milliseconds{20});
  1574. plock.lock();
  1575. } while(pw_stream_get_state(mStream.get(), nullptr) == PW_STREAM_STATE_STREAMING);
  1576. }
  1577. void PipeWirePlayback::stop()
  1578. {
  1579. MainloopUniqueLock plock{mLoop};
  1580. if(int res{pw_stream_set_active(mStream.get(), false)})
  1581. ERR("Failed to stop PipeWire stream (res: {})", res);
  1582. /* Wait for the stream to stop playing. */
  1583. plock.wait([stream=mStream.get()]()
  1584. { return pw_stream_get_state(stream, nullptr) != PW_STREAM_STATE_STREAMING; });
  1585. }
  1586. ClockLatency PipeWirePlayback::getClockLatency()
  1587. {
  1588. /* Given a real-time low-latency output, this is rather complicated to get
  1589. * accurate timing. So, here we go.
  1590. */
  1591. /* First, get the stream time info (tick delay, ticks played, and the
  1592. * CLOCK_MONOTONIC time closest to when that last tick was played).
  1593. */
  1594. pw_time ptime{};
  1595. if(mStream)
  1596. {
  1597. MainloopLockGuard looplock{mLoop};
  1598. if(int res{pw_stream_get_time_n(mStream.get(), &ptime, sizeof(ptime))})
  1599. ERR("Failed to get PipeWire stream time (res: {})", res);
  1600. }
  1601. /* Now get the mixer time and the CLOCK_MONOTONIC time atomically (i.e. the
  1602. * monotonic clock closest to 'now', and the last mixer time at 'now').
  1603. */
  1604. nanoseconds mixtime{};
  1605. timespec tspec{};
  1606. uint refcount;
  1607. do {
  1608. refcount = mDevice->waitForMix();
  1609. mixtime = mDevice->getClockTime();
  1610. clock_gettime(CLOCK_MONOTONIC, &tspec);
  1611. std::atomic_thread_fence(std::memory_order_acquire);
  1612. } while(refcount != mDevice->mMixCount.load(std::memory_order_relaxed));
  1613. /* Convert the monotonic clock, stream ticks, and stream delay to
  1614. * nanoseconds.
  1615. */
  1616. nanoseconds monoclock{seconds{tspec.tv_sec} + nanoseconds{tspec.tv_nsec}};
  1617. nanoseconds curtic{}, delay{};
  1618. if(ptime.rate.denom < 1) UNLIKELY
  1619. {
  1620. /* If there's no stream rate, the stream hasn't had a chance to get
  1621. * going and return time info yet. Just use dummy values.
  1622. */
  1623. ptime.now = monoclock.count();
  1624. curtic = mixtime;
  1625. delay = nanoseconds{seconds{mDevice->mBufferSize}} / mDevice->mSampleRate;
  1626. }
  1627. else
  1628. {
  1629. /* The stream gets recreated with each reset, so include the time that
  1630. * had already passed with previous streams.
  1631. */
  1632. curtic = mTimeBase;
  1633. /* More safely scale the ticks to avoid overflowing the pre-division
  1634. * temporary as it gets larger.
  1635. */
  1636. curtic += seconds{ptime.ticks / ptime.rate.denom} * ptime.rate.num;
  1637. curtic += nanoseconds{seconds{ptime.ticks%ptime.rate.denom} * ptime.rate.num} /
  1638. ptime.rate.denom;
  1639. /* The delay should be small enough to not worry about overflow. */
  1640. delay = nanoseconds{seconds{ptime.delay} * ptime.rate.num} / ptime.rate.denom;
  1641. }
  1642. /* If the mixer time is ahead of the stream time, there's that much more
  1643. * delay relative to the stream delay.
  1644. */
  1645. if(mixtime > curtic)
  1646. delay += mixtime - curtic;
  1647. /* Reduce the delay according to how much time has passed since the known
  1648. * stream time. This isn't 100% accurate since the system monotonic clock
  1649. * doesn't tick at the exact same rate as the audio device, but it should
  1650. * be good enough with ptime.now being constantly updated every few
  1651. * milliseconds with ptime.ticks.
  1652. */
  1653. delay -= monoclock - nanoseconds{ptime.now};
  1654. /* Return the mixer time and delay. Clamp the delay to no less than 0,
  1655. * in case timer drift got that severe.
  1656. */
  1657. ClockLatency ret{};
  1658. ret.ClockTime = mixtime;
  1659. ret.Latency = std::max(delay, nanoseconds{});
  1660. return ret;
  1661. }
  1662. class PipeWireCapture final : public BackendBase {
  1663. void stateChangedCallback(pw_stream_state old, pw_stream_state state, const char *error) noexcept;
  1664. void inputCallback() noexcept;
  1665. void open(std::string_view name) override;
  1666. void start() override;
  1667. void stop() override;
  1668. void captureSamples(std::byte *buffer, uint samples) override;
  1669. uint availableSamples() override;
  1670. uint64_t mTargetId{PwIdAny};
  1671. ThreadMainloop mLoop;
  1672. PwContextPtr mContext;
  1673. PwCorePtr mCore;
  1674. PwStreamPtr mStream;
  1675. spa_hook mStreamListener{};
  1676. RingBufferPtr mRing;
  1677. static constexpr pw_stream_events CreateEvents()
  1678. {
  1679. pw_stream_events ret{};
  1680. ret.version = PW_VERSION_STREAM_EVENTS;
  1681. ret.state_changed = [](void *data, pw_stream_state old, pw_stream_state state, const char *error) noexcept
  1682. { static_cast<PipeWireCapture*>(data)->stateChangedCallback(old, state, error); };
  1683. ret.process = [](void *data) noexcept
  1684. { static_cast<PipeWireCapture*>(data)->inputCallback(); };
  1685. return ret;
  1686. }
  1687. public:
  1688. explicit PipeWireCapture(DeviceBase *device) noexcept : BackendBase{device} { }
  1689. ~PipeWireCapture() final { if(mLoop) mLoop.stop(); }
  1690. };
  1691. void PipeWireCapture::stateChangedCallback(pw_stream_state, pw_stream_state, const char*) noexcept
  1692. { mLoop.signal(false); }
  1693. void PipeWireCapture::inputCallback() noexcept
  1694. {
  1695. pw_buffer *pw_buf{pw_stream_dequeue_buffer(mStream.get())};
  1696. if(!pw_buf) UNLIKELY return;
  1697. spa_data *bufdata{pw_buf->buffer->datas};
  1698. const uint offset{bufdata->chunk->offset % bufdata->maxsize};
  1699. const auto input = al::span{static_cast<const char*>(bufdata->data), bufdata->maxsize}
  1700. .subspan(offset, std::min(bufdata->chunk->size, bufdata->maxsize - offset));
  1701. std::ignore = mRing->write(input.data(), input.size() / mRing->getElemSize());
  1702. pw_stream_queue_buffer(mStream.get(), pw_buf);
  1703. }
  1704. void PipeWireCapture::open(std::string_view name)
  1705. {
  1706. static std::atomic<uint> OpenCount{0};
  1707. uint64_t targetid{PwIdAny};
  1708. std::string devname{};
  1709. gEventHandler.waitForInit();
  1710. if(name.empty())
  1711. {
  1712. EventWatcherLockGuard evtlock{gEventHandler};
  1713. auto&& devlist = DeviceNode::GetList();
  1714. auto match = devlist.cend();
  1715. if(!DefaultSourceDevice.empty())
  1716. {
  1717. auto match_default = [](const DeviceNode &n) -> bool
  1718. { return n.mDevName == DefaultSourceDevice; };
  1719. match = std::find_if(devlist.cbegin(), devlist.cend(), match_default);
  1720. }
  1721. if(match == devlist.cend())
  1722. {
  1723. auto match_capture = [](const DeviceNode &n) -> bool
  1724. { return n.mType != NodeType::Sink; };
  1725. match = std::find_if(devlist.cbegin(), devlist.cend(), match_capture);
  1726. }
  1727. if(match == devlist.cend())
  1728. {
  1729. match = devlist.cbegin();
  1730. if(match == devlist.cend())
  1731. throw al::backend_exception{al::backend_error::NoDevice,
  1732. "No PipeWire capture device found"};
  1733. }
  1734. targetid = match->mSerial;
  1735. if(match->mType != NodeType::Sink) devname = match->mName;
  1736. else devname = std::string{GetMonitorPrefix()}+match->mName;
  1737. }
  1738. else
  1739. {
  1740. EventWatcherLockGuard evtlock{gEventHandler};
  1741. auto&& devlist = DeviceNode::GetList();
  1742. const std::string_view prefix{GetMonitorPrefix()};
  1743. const std::string_view suffix{GetMonitorSuffix()};
  1744. auto match_name = [name](const DeviceNode &n) -> bool
  1745. { return n.mType != NodeType::Sink && n.mName == name; };
  1746. auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name);
  1747. if(match == devlist.cend() && al::starts_with(name, prefix))
  1748. {
  1749. const std::string_view sinkname{name.substr(prefix.length())};
  1750. auto match_sinkname = [sinkname](const DeviceNode &n) -> bool
  1751. { return n.mType == NodeType::Sink && n.mName == sinkname; };
  1752. match = std::find_if(devlist.cbegin(), devlist.cend(), match_sinkname);
  1753. }
  1754. else if(match == devlist.cend() && al::ends_with(name, suffix))
  1755. {
  1756. const std::string_view sinkname{name.substr(0, name.size()-suffix.size())};
  1757. auto match_sinkname = [sinkname](const DeviceNode &n) -> bool
  1758. { return n.mType == NodeType::Sink && n.mDevName == sinkname; };
  1759. match = std::find_if(devlist.cbegin(), devlist.cend(), match_sinkname);
  1760. }
  1761. if(match == devlist.cend())
  1762. throw al::backend_exception{al::backend_error::NoDevice,
  1763. "Device name \"{}\" not found", name};
  1764. targetid = match->mSerial;
  1765. if(match->mType != NodeType::Sink) devname = match->mName;
  1766. else devname = std::string{GetMonitorPrefix()}+match->mName;
  1767. }
  1768. if(!mLoop)
  1769. {
  1770. const auto count = OpenCount.fetch_add(1u, std::memory_order_relaxed);
  1771. const auto thread_name = fmt::format("ALSoftC{}", count);
  1772. mLoop = ThreadMainloop::Create(thread_name.c_str());
  1773. if(!mLoop)
  1774. throw al::backend_exception{al::backend_error::DeviceError,
  1775. "Failed to create PipeWire mainloop (errno: {})", errno};
  1776. if(int res{mLoop.start()})
  1777. throw al::backend_exception{al::backend_error::DeviceError,
  1778. "Failed to start PipeWire mainloop (res: {})", res};
  1779. }
  1780. MainloopUniqueLock mlock{mLoop};
  1781. if(!mContext)
  1782. {
  1783. pw_properties *cprops{pw_properties_new(PW_KEY_CONFIG_NAME, "client-rt.conf", nullptr)};
  1784. mContext = mLoop.newContext(cprops);
  1785. if(!mContext)
  1786. throw al::backend_exception{al::backend_error::DeviceError,
  1787. "Failed to create PipeWire event context (errno: {})\n", errno};
  1788. }
  1789. if(!mCore)
  1790. {
  1791. mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)};
  1792. if(!mCore)
  1793. throw al::backend_exception{al::backend_error::DeviceError,
  1794. "Failed to connect PipeWire event context (errno: {})\n", errno};
  1795. }
  1796. mlock.unlock();
  1797. /* TODO: Ensure the target ID is still valid/usable and accepts streams. */
  1798. mTargetId = targetid;
  1799. if(!devname.empty())
  1800. mDeviceName = std::move(devname);
  1801. else
  1802. mDeviceName = "PipeWire Input"sv;
  1803. bool is51rear{false};
  1804. if(mTargetId != PwIdAny)
  1805. {
  1806. EventWatcherLockGuard evtlock{gEventHandler};
  1807. auto&& devlist = DeviceNode::GetList();
  1808. auto match_id = [targetid=mTargetId](const DeviceNode &n) -> bool
  1809. { return targetid == n.mSerial; };
  1810. auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_id);
  1811. if(match != devlist.cend())
  1812. is51rear = match->mIs51Rear;
  1813. }
  1814. auto info = spa_audio_info_raw{make_spa_info(mDevice, is51rear, UseDevType)};
  1815. auto b = PodDynamicBuilder{};
  1816. auto params = as_const_ptr(spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info));
  1817. if(!params)
  1818. throw al::backend_exception{al::backend_error::DeviceError,
  1819. "Failed to set PipeWire audio format parameters"};
  1820. auto&& binary = GetProcBinary();
  1821. const char *appname{!binary.fname.empty() ? binary.fname.c_str() : "OpenAL Soft"};
  1822. pw_properties *props{pw_properties_new(
  1823. PW_KEY_NODE_NAME, appname,
  1824. PW_KEY_NODE_DESCRIPTION, appname,
  1825. PW_KEY_MEDIA_TYPE, "Audio",
  1826. PW_KEY_MEDIA_CATEGORY, "Capture",
  1827. PW_KEY_MEDIA_ROLE, "Game",
  1828. PW_KEY_NODE_ALWAYS_PROCESS, "true",
  1829. nullptr)};
  1830. if(!props)
  1831. throw al::backend_exception{al::backend_error::DeviceError,
  1832. "Failed to create PipeWire stream properties (errno: {})", errno};
  1833. /* We don't actually care what the latency/update size is, as long as it's
  1834. * reasonable. Unfortunately, when unspecified PipeWire seems to default to
  1835. * around 40ms, which isn't great. So request 20ms instead.
  1836. */
  1837. pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", (mDevice->mSampleRate+25) / 50,
  1838. mDevice->mSampleRate);
  1839. pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->mSampleRate);
  1840. #ifdef PW_KEY_TARGET_OBJECT
  1841. pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%" PRIu64, mTargetId);
  1842. #else
  1843. pw_properties_setf(props, PW_KEY_NODE_TARGET, "%" PRIu64, mTargetId);
  1844. #endif
  1845. MainloopUniqueLock plock{mLoop};
  1846. mStream = PwStreamPtr{pw_stream_new(mCore.get(), "Capture Stream", props)};
  1847. if(!mStream)
  1848. throw al::backend_exception{al::backend_error::NoDevice,
  1849. "Failed to create PipeWire stream (errno: {})", errno};
  1850. static constexpr pw_stream_events streamEvents{CreateEvents()};
  1851. pw_stream_add_listener(mStream.get(), &mStreamListener, &streamEvents, this);
  1852. constexpr pw_stream_flags Flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE
  1853. | PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS};
  1854. if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, &params, 1)})
  1855. throw al::backend_exception{al::backend_error::DeviceError,
  1856. "Error connecting PipeWire stream (res: {})", res};
  1857. /* Wait for the stream to become paused (ready to start streaming). */
  1858. plock.wait([stream=mStream.get()]()
  1859. {
  1860. const char *error{};
  1861. pw_stream_state state{pw_stream_get_state(stream, &error)};
  1862. if(state == PW_STREAM_STATE_ERROR)
  1863. throw al::backend_exception{al::backend_error::DeviceError,
  1864. "Error connecting PipeWire stream: \"{}\"", error};
  1865. return state == PW_STREAM_STATE_PAUSED;
  1866. });
  1867. plock.unlock();
  1868. setDefaultWFXChannelOrder();
  1869. /* Ensure at least a 100ms capture buffer. */
  1870. mRing = RingBuffer::Create(std::max(mDevice->mSampleRate/10u, mDevice->mBufferSize),
  1871. mDevice->frameSizeFromFmt(), false);
  1872. }
  1873. void PipeWireCapture::start()
  1874. {
  1875. MainloopUniqueLock plock{mLoop};
  1876. if(int res{pw_stream_set_active(mStream.get(), true)})
  1877. throw al::backend_exception{al::backend_error::DeviceError,
  1878. "Failed to start PipeWire stream (res: {})", res};
  1879. plock.wait([stream=mStream.get()]()
  1880. {
  1881. const char *error{};
  1882. pw_stream_state state{pw_stream_get_state(stream, &error)};
  1883. if(state == PW_STREAM_STATE_ERROR)
  1884. throw al::backend_exception{al::backend_error::DeviceError,
  1885. "PipeWire stream error: {}", error ? error : "(unknown)"};
  1886. return state == PW_STREAM_STATE_STREAMING;
  1887. });
  1888. }
  1889. void PipeWireCapture::stop()
  1890. {
  1891. MainloopUniqueLock plock{mLoop};
  1892. if(int res{pw_stream_set_active(mStream.get(), false)})
  1893. ERR("Failed to stop PipeWire stream (res: {})", res);
  1894. plock.wait([stream=mStream.get()]()
  1895. { return pw_stream_get_state(stream, nullptr) != PW_STREAM_STATE_STREAMING; });
  1896. }
  1897. uint PipeWireCapture::availableSamples()
  1898. { return static_cast<uint>(mRing->readSpace()); }
  1899. void PipeWireCapture::captureSamples(std::byte *buffer, uint samples)
  1900. { std::ignore = mRing->read(buffer, samples); }
  1901. } // namespace
  1902. bool PipeWireBackendFactory::init()
  1903. {
  1904. if(!pwire_load())
  1905. return false;
  1906. const char *version{pw_get_library_version()};
  1907. if(!check_version(version))
  1908. {
  1909. WARN("PipeWire version \"{}\" too old ({} or newer required)", version,
  1910. pw_get_headers_version());
  1911. return false;
  1912. }
  1913. TRACE("Found PipeWire version \"{}\" ({} or newer)", version, pw_get_headers_version());
  1914. pw_init(nullptr, nullptr);
  1915. if(!gEventHandler.init())
  1916. return false;
  1917. if(!GetConfigValueBool({}, "pipewire", "assume-audio", false)
  1918. && !gEventHandler.waitForAudio())
  1919. {
  1920. gEventHandler.kill();
  1921. /* TODO: Temporary warning, until PipeWire gets a proper way to report
  1922. * audio support.
  1923. */
  1924. WARN("No audio support detected in PipeWire. See the PipeWire options in alsoftrc.sample if this is wrong.");
  1925. return false;
  1926. }
  1927. return true;
  1928. }
  1929. bool PipeWireBackendFactory::querySupport(BackendType type)
  1930. { return type == BackendType::Playback || type == BackendType::Capture; }
  1931. auto PipeWireBackendFactory::enumerate(BackendType type) -> std::vector<std::string>
  1932. {
  1933. std::vector<std::string> outnames;
  1934. gEventHandler.waitForInit();
  1935. EventWatcherLockGuard evtlock{gEventHandler};
  1936. auto&& devlist = DeviceNode::GetList();
  1937. auto match_defsink = [](const DeviceNode &n) -> bool
  1938. { return n.mDevName == DefaultSinkDevice; };
  1939. auto match_defsource = [](const DeviceNode &n) -> bool
  1940. { return n.mDevName == DefaultSourceDevice; };
  1941. auto sort_devnode = [](DeviceNode &lhs, DeviceNode &rhs) noexcept -> bool
  1942. { return lhs.mId < rhs.mId; };
  1943. std::sort(devlist.begin(), devlist.end(), sort_devnode);
  1944. auto defmatch = devlist.cbegin();
  1945. switch(type)
  1946. {
  1947. case BackendType::Playback:
  1948. defmatch = std::find_if(defmatch, devlist.cend(), match_defsink);
  1949. if(defmatch != devlist.cend())
  1950. outnames.emplace_back(defmatch->mName);
  1951. for(auto iter = devlist.cbegin();iter != devlist.cend();++iter)
  1952. {
  1953. if(iter != defmatch && iter->mType != NodeType::Source)
  1954. outnames.emplace_back(iter->mName);
  1955. }
  1956. break;
  1957. case BackendType::Capture:
  1958. outnames.reserve(devlist.size());
  1959. defmatch = std::find_if(defmatch, devlist.cend(), match_defsource);
  1960. if(defmatch != devlist.cend())
  1961. {
  1962. if(defmatch->mType == NodeType::Sink)
  1963. outnames.emplace_back(std::string{GetMonitorPrefix()}+defmatch->mName);
  1964. else
  1965. outnames.emplace_back(defmatch->mName);
  1966. }
  1967. for(auto iter = devlist.cbegin();iter != devlist.cend();++iter)
  1968. {
  1969. if(iter != defmatch)
  1970. {
  1971. if(iter->mType == NodeType::Sink)
  1972. outnames.emplace_back(std::string{GetMonitorPrefix()}+iter->mName);
  1973. else
  1974. outnames.emplace_back(iter->mName);
  1975. }
  1976. }
  1977. break;
  1978. }
  1979. return outnames;
  1980. }
  1981. BackendPtr PipeWireBackendFactory::createBackend(DeviceBase *device, BackendType type)
  1982. {
  1983. if(type == BackendType::Playback)
  1984. return BackendPtr{new PipeWirePlayback{device}};
  1985. if(type == BackendType::Capture)
  1986. return BackendPtr{new PipeWireCapture{device}};
  1987. return nullptr;
  1988. }
  1989. BackendFactory &PipeWireBackendFactory::getFactory()
  1990. {
  1991. static PipeWireBackendFactory factory{};
  1992. return factory;
  1993. }
  1994. alc::EventSupport PipeWireBackendFactory::queryEventSupport(alc::EventType eventType, BackendType)
  1995. {
  1996. switch(eventType)
  1997. {
  1998. case alc::EventType::DefaultDeviceChanged:
  1999. case alc::EventType::DeviceAdded:
  2000. case alc::EventType::DeviceRemoved:
  2001. return alc::EventSupport::FullSupport;
  2002. case alc::EventType::Count:
  2003. break;
  2004. }
  2005. return alc::EventSupport::NoSupport;
  2006. }