pulseaudio.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2009 by Konstantinos Natsakis <[email protected]>
  4. * Copyright (C) 2010 by Chris Robinson <[email protected]>
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Library General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Library General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Library General Public
  16. * License along with this library; if not, write to the
  17. * Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. * Or go to http://www.gnu.org/copyleft/lgpl.html
  20. */
  21. #include "config.h"
  22. #include "backends/pulseaudio.h"
  23. #include <poll.h>
  24. #include <cstring>
  25. #include <array>
  26. #include <string>
  27. #include <vector>
  28. #include <atomic>
  29. #include <thread>
  30. #include <algorithm>
  31. #include <functional>
  32. #include <condition_variable>
  33. #include "alcmain.h"
  34. #include "alu.h"
  35. #include "alconfig.h"
  36. #include "alexcpt.h"
  37. #include "compat.h"
  38. #include "dynload.h"
  39. #include "strutils.h"
  40. #include <pulse/pulseaudio.h>
  41. namespace {
  42. #ifdef HAVE_DYNLOAD
  43. #define PULSE_FUNCS(MAGIC) \
  44. MAGIC(pa_mainloop_new); \
  45. MAGIC(pa_mainloop_free); \
  46. MAGIC(pa_mainloop_set_poll_func); \
  47. MAGIC(pa_mainloop_run); \
  48. MAGIC(pa_mainloop_quit); \
  49. MAGIC(pa_mainloop_get_api); \
  50. MAGIC(pa_context_new); \
  51. MAGIC(pa_context_unref); \
  52. MAGIC(pa_context_get_state); \
  53. MAGIC(pa_context_disconnect); \
  54. MAGIC(pa_context_set_state_callback); \
  55. MAGIC(pa_context_errno); \
  56. MAGIC(pa_context_connect); \
  57. MAGIC(pa_context_get_server_info); \
  58. MAGIC(pa_context_get_sink_info_by_name); \
  59. MAGIC(pa_context_get_sink_info_list); \
  60. MAGIC(pa_context_get_source_info_by_name); \
  61. MAGIC(pa_context_get_source_info_list); \
  62. MAGIC(pa_stream_new); \
  63. MAGIC(pa_stream_unref); \
  64. MAGIC(pa_stream_drop); \
  65. MAGIC(pa_stream_get_state); \
  66. MAGIC(pa_stream_peek); \
  67. MAGIC(pa_stream_write); \
  68. MAGIC(pa_stream_connect_record); \
  69. MAGIC(pa_stream_connect_playback); \
  70. MAGIC(pa_stream_readable_size); \
  71. MAGIC(pa_stream_writable_size); \
  72. MAGIC(pa_stream_is_corked); \
  73. MAGIC(pa_stream_cork); \
  74. MAGIC(pa_stream_is_suspended); \
  75. MAGIC(pa_stream_get_device_name); \
  76. MAGIC(pa_stream_get_latency); \
  77. MAGIC(pa_stream_set_write_callback); \
  78. MAGIC(pa_stream_set_buffer_attr); \
  79. MAGIC(pa_stream_get_buffer_attr); \
  80. MAGIC(pa_stream_get_sample_spec); \
  81. MAGIC(pa_stream_get_time); \
  82. MAGIC(pa_stream_set_read_callback); \
  83. MAGIC(pa_stream_set_state_callback); \
  84. MAGIC(pa_stream_set_moved_callback); \
  85. MAGIC(pa_stream_set_underflow_callback); \
  86. MAGIC(pa_stream_new_with_proplist); \
  87. MAGIC(pa_stream_disconnect); \
  88. MAGIC(pa_stream_set_buffer_attr_callback); \
  89. MAGIC(pa_stream_begin_write); \
  90. MAGIC(pa_channel_map_init_auto); \
  91. MAGIC(pa_channel_map_parse); \
  92. MAGIC(pa_channel_map_snprint); \
  93. MAGIC(pa_channel_map_equal); \
  94. MAGIC(pa_channel_map_superset); \
  95. MAGIC(pa_operation_get_state); \
  96. MAGIC(pa_operation_unref); \
  97. MAGIC(pa_sample_spec_valid); \
  98. MAGIC(pa_frame_size); \
  99. MAGIC(pa_strerror); \
  100. MAGIC(pa_path_get_filename); \
  101. MAGIC(pa_get_binary_name); \
  102. MAGIC(pa_xmalloc); \
  103. MAGIC(pa_xfree);
  104. void *pulse_handle;
  105. #define MAKE_FUNC(x) decltype(x) * p##x
  106. PULSE_FUNCS(MAKE_FUNC)
  107. #undef MAKE_FUNC
  108. #ifndef IN_IDE_PARSER
  109. #define pa_mainloop_new ppa_mainloop_new
  110. #define pa_mainloop_free ppa_mainloop_free
  111. #define pa_mainloop_set_poll_func ppa_mainloop_set_poll_func
  112. #define pa_mainloop_run ppa_mainloop_run
  113. #define pa_mainloop_quit ppa_mainloop_quit
  114. #define pa_mainloop_get_api ppa_mainloop_get_api
  115. #define pa_context_new ppa_context_new
  116. #define pa_context_unref ppa_context_unref
  117. #define pa_context_get_state ppa_context_get_state
  118. #define pa_context_disconnect ppa_context_disconnect
  119. #define pa_context_set_state_callback ppa_context_set_state_callback
  120. #define pa_context_errno ppa_context_errno
  121. #define pa_context_connect ppa_context_connect
  122. #define pa_context_get_server_info ppa_context_get_server_info
  123. #define pa_context_get_sink_info_by_name ppa_context_get_sink_info_by_name
  124. #define pa_context_get_sink_info_list ppa_context_get_sink_info_list
  125. #define pa_context_get_source_info_by_name ppa_context_get_source_info_by_name
  126. #define pa_context_get_source_info_list ppa_context_get_source_info_list
  127. #define pa_stream_new ppa_stream_new
  128. #define pa_stream_unref ppa_stream_unref
  129. #define pa_stream_disconnect ppa_stream_disconnect
  130. #define pa_stream_drop ppa_stream_drop
  131. #define pa_stream_set_write_callback ppa_stream_set_write_callback
  132. #define pa_stream_set_buffer_attr ppa_stream_set_buffer_attr
  133. #define pa_stream_get_buffer_attr ppa_stream_get_buffer_attr
  134. #define pa_stream_get_sample_spec ppa_stream_get_sample_spec
  135. #define pa_stream_get_time ppa_stream_get_time
  136. #define pa_stream_set_read_callback ppa_stream_set_read_callback
  137. #define pa_stream_set_state_callback ppa_stream_set_state_callback
  138. #define pa_stream_set_moved_callback ppa_stream_set_moved_callback
  139. #define pa_stream_set_underflow_callback ppa_stream_set_underflow_callback
  140. #define pa_stream_connect_record ppa_stream_connect_record
  141. #define pa_stream_connect_playback ppa_stream_connect_playback
  142. #define pa_stream_readable_size ppa_stream_readable_size
  143. #define pa_stream_writable_size ppa_stream_writable_size
  144. #define pa_stream_is_corked ppa_stream_is_corked
  145. #define pa_stream_cork ppa_stream_cork
  146. #define pa_stream_is_suspended ppa_stream_is_suspended
  147. #define pa_stream_get_device_name ppa_stream_get_device_name
  148. #define pa_stream_get_latency ppa_stream_get_latency
  149. #define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback
  150. #define pa_stream_begin_write ppa_stream_begin_write*/
  151. #define pa_channel_map_init_auto ppa_channel_map_init_auto
  152. #define pa_channel_map_parse ppa_channel_map_parse
  153. #define pa_channel_map_snprint ppa_channel_map_snprint
  154. #define pa_channel_map_equal ppa_channel_map_equal
  155. #define pa_channel_map_superset ppa_channel_map_superset
  156. #define pa_operation_get_state ppa_operation_get_state
  157. #define pa_operation_unref ppa_operation_unref
  158. #define pa_sample_spec_valid ppa_sample_spec_valid
  159. #define pa_frame_size ppa_frame_size
  160. #define pa_strerror ppa_strerror
  161. #define pa_stream_get_state ppa_stream_get_state
  162. #define pa_stream_peek ppa_stream_peek
  163. #define pa_stream_write ppa_stream_write
  164. #define pa_xfree ppa_xfree
  165. #define pa_path_get_filename ppa_path_get_filename
  166. #define pa_get_binary_name ppa_get_binary_name
  167. #define pa_xmalloc ppa_xmalloc
  168. #endif /* IN_IDE_PARSER */
  169. #endif
  170. constexpr pa_channel_map MonoChanMap{
  171. 1, {PA_CHANNEL_POSITION_MONO}
  172. }, StereoChanMap{
  173. 2, {PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT}
  174. }, QuadChanMap{
  175. 4, {
  176. PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
  177. PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT
  178. }
  179. }, X51ChanMap{
  180. 6, {
  181. PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
  182. PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
  183. PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
  184. }
  185. }, X51RearChanMap{
  186. 6, {
  187. PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
  188. PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
  189. PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT
  190. }
  191. }, X61ChanMap{
  192. 7, {
  193. PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
  194. PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
  195. PA_CHANNEL_POSITION_REAR_CENTER,
  196. PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
  197. }
  198. }, X71ChanMap{
  199. 8, {
  200. PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
  201. PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
  202. PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
  203. PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
  204. }
  205. };
  206. size_t ChannelFromPulse(pa_channel_position_t chan)
  207. {
  208. switch(chan)
  209. {
  210. case PA_CHANNEL_POSITION_INVALID: break;
  211. case PA_CHANNEL_POSITION_MONO: return FrontCenter;
  212. case PA_CHANNEL_POSITION_FRONT_LEFT: return FrontLeft;
  213. case PA_CHANNEL_POSITION_FRONT_RIGHT: return FrontRight;
  214. case PA_CHANNEL_POSITION_FRONT_CENTER: return FrontCenter;
  215. case PA_CHANNEL_POSITION_REAR_CENTER: return BackCenter;
  216. case PA_CHANNEL_POSITION_REAR_LEFT: return BackLeft;
  217. case PA_CHANNEL_POSITION_REAR_RIGHT: return BackRight;
  218. case PA_CHANNEL_POSITION_LFE: return LFE;
  219. case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: break;
  220. case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: break;
  221. case PA_CHANNEL_POSITION_SIDE_LEFT: return SideLeft;
  222. case PA_CHANNEL_POSITION_SIDE_RIGHT: return SideRight;
  223. case PA_CHANNEL_POSITION_AUX0: return Aux0;
  224. case PA_CHANNEL_POSITION_AUX1: return Aux1;
  225. case PA_CHANNEL_POSITION_AUX2: return Aux2;
  226. case PA_CHANNEL_POSITION_AUX3: return Aux3;
  227. case PA_CHANNEL_POSITION_AUX4: return Aux4;
  228. case PA_CHANNEL_POSITION_AUX5: return Aux5;
  229. case PA_CHANNEL_POSITION_AUX6: return Aux6;
  230. case PA_CHANNEL_POSITION_AUX7: return Aux7;
  231. case PA_CHANNEL_POSITION_AUX8: return Aux8;
  232. case PA_CHANNEL_POSITION_AUX9: return Aux9;
  233. case PA_CHANNEL_POSITION_AUX10: return Aux10;
  234. case PA_CHANNEL_POSITION_AUX11: return Aux11;
  235. case PA_CHANNEL_POSITION_AUX12: return Aux12;
  236. case PA_CHANNEL_POSITION_AUX13: return Aux13;
  237. case PA_CHANNEL_POSITION_AUX14: return Aux14;
  238. case PA_CHANNEL_POSITION_AUX15: return Aux15;
  239. case PA_CHANNEL_POSITION_AUX16: break;
  240. case PA_CHANNEL_POSITION_AUX17: break;
  241. case PA_CHANNEL_POSITION_AUX18: break;
  242. case PA_CHANNEL_POSITION_AUX19: break;
  243. case PA_CHANNEL_POSITION_AUX20: break;
  244. case PA_CHANNEL_POSITION_AUX21: break;
  245. case PA_CHANNEL_POSITION_AUX22: break;
  246. case PA_CHANNEL_POSITION_AUX23: break;
  247. case PA_CHANNEL_POSITION_AUX24: break;
  248. case PA_CHANNEL_POSITION_AUX25: break;
  249. case PA_CHANNEL_POSITION_AUX26: break;
  250. case PA_CHANNEL_POSITION_AUX27: break;
  251. case PA_CHANNEL_POSITION_AUX28: break;
  252. case PA_CHANNEL_POSITION_AUX29: break;
  253. case PA_CHANNEL_POSITION_AUX30: break;
  254. case PA_CHANNEL_POSITION_AUX31: break;
  255. case PA_CHANNEL_POSITION_TOP_CENTER: break;
  256. case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: return UpperFrontLeft;
  257. case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: return UpperFrontRight;
  258. case PA_CHANNEL_POSITION_TOP_FRONT_CENTER: break;
  259. case PA_CHANNEL_POSITION_TOP_REAR_LEFT: return UpperBackLeft;
  260. case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: return UpperBackRight;
  261. case PA_CHANNEL_POSITION_TOP_REAR_CENTER: break;
  262. case PA_CHANNEL_POSITION_MAX: break;
  263. }
  264. throw al::backend_exception{ALC_INVALID_VALUE, "Unexpected channel enum %d", chan};
  265. }
  266. void SetChannelOrderFromMap(ALCdevice *device, const pa_channel_map &chanmap)
  267. {
  268. device->RealOut.ChannelIndex.fill(INVALID_CHANNEL_INDEX);
  269. for(ALuint i{0};i < chanmap.channels;++i)
  270. device->RealOut.ChannelIndex[ChannelFromPulse(chanmap.map[i])] = i;
  271. }
  272. /* *grumble* Don't use enums for bitflags. */
  273. constexpr inline pa_stream_flags_t operator|(pa_stream_flags_t lhs, pa_stream_flags_t rhs)
  274. { return pa_stream_flags_t(int(lhs) | int(rhs)); }
  275. inline pa_stream_flags_t& operator|=(pa_stream_flags_t &lhs, pa_stream_flags_t rhs)
  276. {
  277. lhs = lhs | rhs;
  278. return lhs;
  279. }
  280. inline pa_stream_flags_t& operator&=(pa_stream_flags_t &lhs, int rhs)
  281. {
  282. lhs = pa_stream_flags_t(int(lhs) & rhs);
  283. return lhs;
  284. }
  285. inline pa_context_flags_t& operator|=(pa_context_flags_t &lhs, pa_context_flags_t rhs)
  286. {
  287. lhs = pa_context_flags_t(int(lhs) | int(rhs));
  288. return lhs;
  289. }
  290. /* Global flags and properties */
  291. pa_context_flags_t pulse_ctx_flags;
  292. int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) noexcept
  293. {
  294. auto plock = static_cast<std::unique_lock<std::mutex>*>(userdata);
  295. plock->unlock();
  296. int r{poll(ufds, nfds, timeout)};
  297. plock->lock();
  298. return r;
  299. }
  300. class PulseMainloop {
  301. std::thread mThread;
  302. std::mutex mMutex;
  303. std::condition_variable mCondVar;
  304. pa_mainloop *mMainloop{nullptr};
  305. public:
  306. ~PulseMainloop()
  307. {
  308. if(mThread.joinable())
  309. {
  310. pa_mainloop_quit(mMainloop, 0);
  311. mThread.join();
  312. }
  313. }
  314. int mainloop_thread()
  315. {
  316. SetRTPriority();
  317. std::unique_lock<std::mutex> plock{mMutex};
  318. mMainloop = pa_mainloop_new();
  319. pa_mainloop_set_poll_func(mMainloop, pulse_poll_func, &plock);
  320. mCondVar.notify_all();
  321. int ret{};
  322. pa_mainloop_run(mMainloop, &ret);
  323. pa_mainloop_free(mMainloop);
  324. mMainloop = nullptr;
  325. return ret;
  326. }
  327. void doLock() { mMutex.lock(); }
  328. void doUnlock() { mMutex.unlock(); }
  329. std::unique_lock<std::mutex> getLock() { return std::unique_lock<std::mutex>{mMutex}; }
  330. std::condition_variable &getCondVar() noexcept { return mCondVar; }
  331. void contextStateCallback(pa_context *context) noexcept
  332. {
  333. pa_context_state_t state{pa_context_get_state(context)};
  334. if(state == PA_CONTEXT_READY || !PA_CONTEXT_IS_GOOD(state))
  335. mCondVar.notify_all();
  336. }
  337. static void contextStateCallbackC(pa_context *context, void *pdata) noexcept
  338. { static_cast<PulseMainloop*>(pdata)->contextStateCallback(context); }
  339. void streamStateCallback(pa_stream *stream) noexcept
  340. {
  341. pa_stream_state_t state{pa_stream_get_state(stream)};
  342. if(state == PA_STREAM_READY || !PA_STREAM_IS_GOOD(state))
  343. mCondVar.notify_all();
  344. }
  345. static void streamStateCallbackC(pa_stream *stream, void *pdata) noexcept
  346. { static_cast<PulseMainloop*>(pdata)->streamStateCallback(stream); }
  347. void streamSuccessCallback(pa_stream*, int) noexcept
  348. { mCondVar.notify_all(); }
  349. static void streamSuccessCallbackC(pa_stream *stream, int success, void *pdata) noexcept
  350. { static_cast<PulseMainloop*>(pdata)->streamSuccessCallback(stream, success); }
  351. void waitForOperation(pa_operation *op, std::unique_lock<std::mutex> &plock)
  352. {
  353. if(op)
  354. {
  355. while(pa_operation_get_state(op) == PA_OPERATION_RUNNING)
  356. mCondVar.wait(plock);
  357. pa_operation_unref(op);
  358. }
  359. }
  360. pa_context *connectContext(std::unique_lock<std::mutex> &plock);
  361. pa_stream *connectStream(const char *device_name, std::unique_lock<std::mutex> &plock,
  362. pa_context *context, pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec,
  363. pa_channel_map *chanmap, BackendType type);
  364. void close(pa_context *context, pa_stream *stream);
  365. };
  366. pa_context *PulseMainloop::connectContext(std::unique_lock<std::mutex> &plock)
  367. {
  368. const char *name{"OpenAL Soft"};
  369. const PathNamePair &binname = GetProcBinary();
  370. if(!binname.fname.empty())
  371. name = binname.fname.c_str();
  372. if(!mMainloop)
  373. {
  374. mThread = std::thread{std::mem_fn(&PulseMainloop::mainloop_thread), this};
  375. while(!mMainloop) mCondVar.wait(plock);
  376. }
  377. pa_context *context{pa_context_new(pa_mainloop_get_api(mMainloop), name)};
  378. if(!context) throw al::backend_exception{ALC_OUT_OF_MEMORY, "pa_context_new() failed"};
  379. pa_context_set_state_callback(context, &contextStateCallbackC, this);
  380. int err;
  381. if((err=pa_context_connect(context, nullptr, pulse_ctx_flags, nullptr)) >= 0)
  382. {
  383. pa_context_state_t state;
  384. while((state=pa_context_get_state(context)) != PA_CONTEXT_READY)
  385. {
  386. if(!PA_CONTEXT_IS_GOOD(state))
  387. {
  388. err = pa_context_errno(context);
  389. if(err > 0) err = -err;
  390. break;
  391. }
  392. mCondVar.wait(plock);
  393. }
  394. }
  395. pa_context_set_state_callback(context, nullptr, nullptr);
  396. if(err < 0)
  397. {
  398. pa_context_unref(context);
  399. throw al::backend_exception{ALC_INVALID_VALUE, "Context did not connect (%s)",
  400. pa_strerror(err)};
  401. }
  402. return context;
  403. }
  404. pa_stream *PulseMainloop::connectStream(const char *device_name,
  405. std::unique_lock<std::mutex> &plock, pa_context *context, pa_stream_flags_t flags,
  406. pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap, BackendType type)
  407. {
  408. const char *stream_id{(type==BackendType::Playback) ? "Playback Stream" : "Capture Stream"};
  409. pa_stream *stream{pa_stream_new(context, stream_id, spec, chanmap)};
  410. if(!stream)
  411. throw al::backend_exception{ALC_OUT_OF_MEMORY, "pa_stream_new() failed (%s)",
  412. pa_strerror(pa_context_errno(context))};
  413. pa_stream_set_state_callback(stream, &streamStateCallbackC, this);
  414. int err{(type==BackendType::Playback) ?
  415. pa_stream_connect_playback(stream, device_name, attr, flags, nullptr, nullptr) :
  416. pa_stream_connect_record(stream, device_name, attr, flags)};
  417. if(err < 0)
  418. {
  419. pa_stream_unref(stream);
  420. throw al::backend_exception{ALC_INVALID_VALUE, "%s did not connect (%s)", stream_id,
  421. pa_strerror(err)};
  422. }
  423. pa_stream_state_t state;
  424. while((state=pa_stream_get_state(stream)) != PA_STREAM_READY)
  425. {
  426. if(!PA_STREAM_IS_GOOD(state))
  427. {
  428. err = pa_context_errno(context);
  429. pa_stream_unref(stream);
  430. throw al::backend_exception{ALC_INVALID_VALUE, "%s did not get ready (%s)", stream_id,
  431. pa_strerror(err)};
  432. }
  433. mCondVar.wait(plock);
  434. }
  435. pa_stream_set_state_callback(stream, nullptr, nullptr);
  436. return stream;
  437. }
  438. void PulseMainloop::close(pa_context *context, pa_stream *stream)
  439. {
  440. std::lock_guard<std::mutex> _{mMutex};
  441. if(stream)
  442. {
  443. pa_stream_set_state_callback(stream, nullptr, nullptr);
  444. pa_stream_set_moved_callback(stream, nullptr, nullptr);
  445. pa_stream_set_write_callback(stream, nullptr, nullptr);
  446. pa_stream_set_buffer_attr_callback(stream, nullptr, nullptr);
  447. pa_stream_disconnect(stream);
  448. pa_stream_unref(stream);
  449. }
  450. pa_context_disconnect(context);
  451. pa_context_unref(context);
  452. }
  453. /* Used for initial connection test and enumeration. */
  454. PulseMainloop gGlobalMainloop;
  455. struct DevMap {
  456. std::string name;
  457. std::string device_name;
  458. };
  459. bool checkName(const al::vector<DevMap> &list, const std::string &name)
  460. {
  461. auto match_name = [&name](const DevMap &entry) -> bool { return entry.name == name; };
  462. return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend();
  463. }
  464. al::vector<DevMap> PlaybackDevices;
  465. al::vector<DevMap> CaptureDevices;
  466. void device_sink_callback(pa_context*, const pa_sink_info *info, int eol, void *pdata) noexcept
  467. {
  468. if(eol)
  469. {
  470. static_cast<PulseMainloop*>(pdata)->getCondVar().notify_all();
  471. return;
  472. }
  473. /* Skip this device is if it's already in the list. */
  474. if(std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
  475. [info](const DevMap &entry) -> bool
  476. { return entry.device_name == info->name; }
  477. ) != PlaybackDevices.cend())
  478. return;
  479. /* Make sure the display name (description) is unique. Append a number
  480. * counter as needed.
  481. */
  482. int count{1};
  483. std::string newname{info->description};
  484. while(checkName(PlaybackDevices, newname))
  485. {
  486. newname = info->description;
  487. newname += " #";
  488. newname += std::to_string(++count);
  489. }
  490. PlaybackDevices.emplace_back(DevMap{std::move(newname), info->name});
  491. DevMap &newentry = PlaybackDevices.back();
  492. TRACE("Got device \"%s\", \"%s\"\n", newentry.name.c_str(), newentry.device_name.c_str());
  493. }
  494. void probePlaybackDevices(PulseMainloop &mainloop)
  495. {
  496. pa_context *context{};
  497. pa_stream *stream{};
  498. PlaybackDevices.clear();
  499. try {
  500. auto plock = mainloop.getLock();
  501. context = mainloop.connectContext(plock);
  502. constexpr pa_stream_flags_t flags{PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
  503. PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE | PA_STREAM_START_CORKED};
  504. pa_sample_spec spec{};
  505. spec.format = PA_SAMPLE_S16NE;
  506. spec.rate = 44100;
  507. spec.channels = 2;
  508. stream = mainloop.connectStream(nullptr, plock, context, flags, nullptr, &spec, nullptr,
  509. BackendType::Playback);
  510. pa_operation *op{pa_context_get_sink_info_by_name(context,
  511. pa_stream_get_device_name(stream), device_sink_callback, &mainloop)};
  512. mainloop.waitForOperation(op, plock);
  513. pa_stream_disconnect(stream);
  514. pa_stream_unref(stream);
  515. stream = nullptr;
  516. op = pa_context_get_sink_info_list(context, device_sink_callback, &mainloop);
  517. mainloop.waitForOperation(op, plock);
  518. pa_context_disconnect(context);
  519. pa_context_unref(context);
  520. context = nullptr;
  521. }
  522. catch(std::exception &e) {
  523. ERR("Error enumerating devices: %s\n", e.what());
  524. if(context) mainloop.close(context, stream);
  525. }
  526. }
  527. void device_source_callback(pa_context*, const pa_source_info *info, int eol, void *pdata) noexcept
  528. {
  529. if(eol)
  530. {
  531. static_cast<PulseMainloop*>(pdata)->getCondVar().notify_all();
  532. return;
  533. }
  534. /* Skip this device is if it's already in the list. */
  535. if(std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
  536. [info](const DevMap &entry) -> bool
  537. { return entry.device_name == info->name; }
  538. ) != CaptureDevices.cend())
  539. return;
  540. /* Make sure the display name (description) is unique. Append a number
  541. * counter as needed.
  542. */
  543. int count{1};
  544. std::string newname{info->description};
  545. while(checkName(CaptureDevices, newname))
  546. {
  547. newname = info->description;
  548. newname += " #";
  549. newname += std::to_string(++count);
  550. }
  551. CaptureDevices.emplace_back(DevMap{std::move(newname), info->name});
  552. DevMap &newentry = CaptureDevices.back();
  553. TRACE("Got device \"%s\", \"%s\"\n", newentry.name.c_str(), newentry.device_name.c_str());
  554. }
  555. void probeCaptureDevices(PulseMainloop &mainloop)
  556. {
  557. pa_context *context{};
  558. pa_stream *stream{};
  559. CaptureDevices.clear();
  560. try {
  561. auto plock = mainloop.getLock();
  562. context = mainloop.connectContext(plock);
  563. constexpr pa_stream_flags_t flags{PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
  564. PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE | PA_STREAM_START_CORKED};
  565. pa_sample_spec spec{};
  566. spec.format = PA_SAMPLE_S16NE;
  567. spec.rate = 44100;
  568. spec.channels = 1;
  569. stream = mainloop.connectStream(nullptr, plock, context, flags, nullptr, &spec, nullptr,
  570. BackendType::Capture);
  571. pa_operation *op{pa_context_get_source_info_by_name(context,
  572. pa_stream_get_device_name(stream), device_source_callback, &mainloop)};
  573. mainloop.waitForOperation(op, plock);
  574. pa_stream_disconnect(stream);
  575. pa_stream_unref(stream);
  576. stream = nullptr;
  577. op = pa_context_get_source_info_list(context, device_source_callback, &mainloop);
  578. mainloop.waitForOperation(op, plock);
  579. pa_context_disconnect(context);
  580. pa_context_unref(context);
  581. context = nullptr;
  582. }
  583. catch(std::exception &e) {
  584. ERR("Error enumerating devices: %s\n", e.what());
  585. if(context) mainloop.close(context, stream);
  586. }
  587. }
  588. struct PulsePlayback final : public BackendBase {
  589. PulsePlayback(ALCdevice *device) noexcept : BackendBase{device} { }
  590. ~PulsePlayback() override;
  591. void bufferAttrCallback(pa_stream *stream) noexcept;
  592. static void bufferAttrCallbackC(pa_stream *stream, void *pdata) noexcept
  593. { static_cast<PulsePlayback*>(pdata)->bufferAttrCallback(stream); }
  594. void streamStateCallback(pa_stream *stream) noexcept;
  595. static void streamStateCallbackC(pa_stream *stream, void *pdata) noexcept
  596. { static_cast<PulsePlayback*>(pdata)->streamStateCallback(stream); }
  597. void streamWriteCallback(pa_stream *stream, size_t nbytes) noexcept;
  598. static void streamWriteCallbackC(pa_stream *stream, size_t nbytes, void *pdata) noexcept
  599. { static_cast<PulsePlayback*>(pdata)->streamWriteCallback(stream, nbytes); }
  600. void sinkInfoCallback(pa_context *context, const pa_sink_info *info, int eol) noexcept;
  601. static void sinkInfoCallbackC(pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept
  602. { static_cast<PulsePlayback*>(pdata)->sinkInfoCallback(context, info, eol); }
  603. void sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol) noexcept;
  604. static void sinkNameCallbackC(pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept
  605. { static_cast<PulsePlayback*>(pdata)->sinkNameCallback(context, info, eol); }
  606. void streamMovedCallback(pa_stream *stream) noexcept;
  607. static void streamMovedCallbackC(pa_stream *stream, void *pdata) noexcept
  608. { static_cast<PulsePlayback*>(pdata)->streamMovedCallback(stream); }
  609. void open(const ALCchar *name) override;
  610. bool reset() override;
  611. bool start() override;
  612. void stop() override;
  613. ClockLatency getClockLatency() override;
  614. void lock() override { mMainloop.doLock(); }
  615. void unlock() override { mMainloop.doUnlock(); }
  616. PulseMainloop mMainloop;
  617. std::string mDeviceName;
  618. pa_buffer_attr mAttr;
  619. pa_sample_spec mSpec;
  620. pa_stream *mStream{nullptr};
  621. pa_context *mContext{nullptr};
  622. ALuint mFrameSize{0u};
  623. DEF_NEWDEL(PulsePlayback)
  624. };
  625. PulsePlayback::~PulsePlayback()
  626. {
  627. if(!mContext)
  628. return;
  629. mMainloop.close(mContext, mStream);
  630. mContext = nullptr;
  631. mStream = nullptr;
  632. }
  633. void PulsePlayback::bufferAttrCallback(pa_stream *stream) noexcept
  634. {
  635. /* FIXME: Update the device's UpdateSize (and/or BufferSize) using the new
  636. * buffer attributes? Changing UpdateSize will change the ALC_REFRESH
  637. * property, which probably shouldn't change between device resets. But
  638. * leaving it alone means ALC_REFRESH will be off.
  639. */
  640. mAttr = *(pa_stream_get_buffer_attr(stream));
  641. TRACE("minreq=%d, tlength=%d, prebuf=%d\n", mAttr.minreq, mAttr.tlength, mAttr.prebuf);
  642. }
  643. void PulsePlayback::streamStateCallback(pa_stream *stream) noexcept
  644. {
  645. if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
  646. {
  647. ERR("Received stream failure!\n");
  648. aluHandleDisconnect(mDevice, "Playback stream failure");
  649. }
  650. mMainloop.getCondVar().notify_all();
  651. }
  652. void PulsePlayback::streamWriteCallback(pa_stream *stream, size_t nbytes) noexcept
  653. {
  654. void *buf{pa_xmalloc(nbytes)};
  655. aluMixData(mDevice, buf, static_cast<ALuint>(nbytes/mFrameSize));
  656. int ret{pa_stream_write(stream, buf, nbytes, pa_xfree, 0, PA_SEEK_RELATIVE)};
  657. if UNLIKELY(ret != PA_OK)
  658. ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
  659. }
  660. void PulsePlayback::sinkInfoCallback(pa_context*, const pa_sink_info *info, int eol) noexcept
  661. {
  662. struct ChannelMap {
  663. DevFmtChannels fmt;
  664. pa_channel_map map;
  665. };
  666. static constexpr std::array<ChannelMap,7> chanmaps{{
  667. { DevFmtX71, X71ChanMap },
  668. { DevFmtX61, X61ChanMap },
  669. { DevFmtX51, X51ChanMap },
  670. { DevFmtX51Rear, X51RearChanMap },
  671. { DevFmtQuad, QuadChanMap },
  672. { DevFmtStereo, StereoChanMap },
  673. { DevFmtMono, MonoChanMap }
  674. }};
  675. if(eol)
  676. {
  677. mMainloop.getCondVar().notify_all();
  678. return;
  679. }
  680. auto chaniter = std::find_if(chanmaps.cbegin(), chanmaps.cend(),
  681. [info](const ChannelMap &chanmap) -> bool
  682. { return pa_channel_map_superset(&info->channel_map, &chanmap.map); }
  683. );
  684. if(chaniter != chanmaps.cend())
  685. {
  686. if(!mDevice->Flags.get<ChannelsRequest>())
  687. mDevice->FmtChans = chaniter->fmt;
  688. }
  689. else
  690. {
  691. char chanmap_str[PA_CHANNEL_MAP_SNPRINT_MAX]{};
  692. pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map);
  693. WARN("Failed to find format for channel map:\n %s\n", chanmap_str);
  694. }
  695. if(info->active_port)
  696. TRACE("Active port: %s (%s)\n", info->active_port->name, info->active_port->description);
  697. mDevice->IsHeadphones = (mDevice->FmtChans == DevFmtStereo &&
  698. info->active_port && strcmp(info->active_port->name, "analog-output-headphones") == 0);
  699. }
  700. void PulsePlayback::sinkNameCallback(pa_context*, const pa_sink_info *info, int eol) noexcept
  701. {
  702. if(eol)
  703. {
  704. mMainloop.getCondVar().notify_all();
  705. return;
  706. }
  707. mDevice->DeviceName = info->description;
  708. }
  709. void PulsePlayback::streamMovedCallback(pa_stream *stream) noexcept
  710. {
  711. mDeviceName = pa_stream_get_device_name(stream);
  712. TRACE("Stream moved to %s\n", mDeviceName.c_str());
  713. }
  714. void PulsePlayback::open(const ALCchar *name)
  715. {
  716. const char *pulse_name{nullptr};
  717. const char *dev_name{nullptr};
  718. if(name)
  719. {
  720. if(PlaybackDevices.empty())
  721. probePlaybackDevices(mMainloop);
  722. auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
  723. [name](const DevMap &entry) -> bool
  724. { return entry.name == name; }
  725. );
  726. if(iter == PlaybackDevices.cend())
  727. throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name};
  728. pulse_name = iter->device_name.c_str();
  729. dev_name = iter->name.c_str();
  730. }
  731. auto plock = mMainloop.getLock();
  732. mContext = mMainloop.connectContext(plock);
  733. pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
  734. PA_STREAM_FIX_CHANNELS};
  735. if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 1))
  736. flags |= PA_STREAM_DONT_MOVE;
  737. pa_sample_spec spec{};
  738. spec.format = PA_SAMPLE_S16NE;
  739. spec.rate = 44100;
  740. spec.channels = 2;
  741. if(!pulse_name)
  742. {
  743. static const auto defname = al::getenv("ALSOFT_PULSE_DEFAULT");
  744. if(defname) pulse_name = defname->c_str();
  745. }
  746. TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
  747. mStream = mMainloop.connectStream(pulse_name, plock, mContext, flags, nullptr, &spec, nullptr,
  748. BackendType::Playback);
  749. pa_stream_set_moved_callback(mStream, &PulsePlayback::streamMovedCallbackC, this);
  750. mFrameSize = static_cast<ALuint>(pa_frame_size(pa_stream_get_sample_spec(mStream)));
  751. mDeviceName = pa_stream_get_device_name(mStream);
  752. if(!dev_name)
  753. {
  754. pa_operation *op{pa_context_get_sink_info_by_name(mContext, mDeviceName.c_str(),
  755. &PulsePlayback::sinkNameCallbackC, this)};
  756. mMainloop.waitForOperation(op, plock);
  757. }
  758. else
  759. mDevice->DeviceName = dev_name;
  760. }
  761. bool PulsePlayback::reset()
  762. {
  763. auto plock = mMainloop.getLock();
  764. if(mStream)
  765. {
  766. pa_stream_set_state_callback(mStream, nullptr, nullptr);
  767. pa_stream_set_moved_callback(mStream, nullptr, nullptr);
  768. pa_stream_set_write_callback(mStream, nullptr, nullptr);
  769. pa_stream_set_buffer_attr_callback(mStream, nullptr, nullptr);
  770. pa_stream_disconnect(mStream);
  771. pa_stream_unref(mStream);
  772. mStream = nullptr;
  773. }
  774. pa_operation *op{pa_context_get_sink_info_by_name(mContext, mDeviceName.c_str(),
  775. &PulsePlayback::sinkInfoCallbackC, this)};
  776. mMainloop.waitForOperation(op, plock);
  777. pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING |
  778. PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS};
  779. if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 1))
  780. flags |= PA_STREAM_DONT_MOVE;
  781. if(GetConfigValueBool(mDevice->DeviceName.c_str(), "pulse", "adjust-latency", 0))
  782. {
  783. /* ADJUST_LATENCY can't be specified with EARLY_REQUESTS, for some
  784. * reason. So if the user wants to adjust the overall device latency,
  785. * we can't ask to get write signals as soon as minreq is reached.
  786. */
  787. flags &= ~PA_STREAM_EARLY_REQUESTS;
  788. flags |= PA_STREAM_ADJUST_LATENCY;
  789. }
  790. if(GetConfigValueBool(mDevice->DeviceName.c_str(), "pulse", "fix-rate", 0) ||
  791. !mDevice->Flags.get<FrequencyRequest>())
  792. flags |= PA_STREAM_FIX_RATE;
  793. pa_channel_map chanmap{};
  794. switch(mDevice->FmtChans)
  795. {
  796. case DevFmtMono:
  797. chanmap = MonoChanMap;
  798. break;
  799. case DevFmtAmbi3D:
  800. mDevice->FmtChans = DevFmtStereo;
  801. /*fall-through*/
  802. case DevFmtStereo:
  803. chanmap = StereoChanMap;
  804. break;
  805. case DevFmtQuad:
  806. chanmap = QuadChanMap;
  807. break;
  808. case DevFmtX51:
  809. chanmap = X51ChanMap;
  810. break;
  811. case DevFmtX51Rear:
  812. chanmap = X51RearChanMap;
  813. break;
  814. case DevFmtX61:
  815. chanmap = X61ChanMap;
  816. break;
  817. case DevFmtX71:
  818. chanmap = X71ChanMap;
  819. break;
  820. }
  821. SetChannelOrderFromMap(mDevice, chanmap);
  822. switch(mDevice->FmtType)
  823. {
  824. case DevFmtByte:
  825. mDevice->FmtType = DevFmtUByte;
  826. /* fall-through */
  827. case DevFmtUByte:
  828. mSpec.format = PA_SAMPLE_U8;
  829. break;
  830. case DevFmtUShort:
  831. mDevice->FmtType = DevFmtShort;
  832. /* fall-through */
  833. case DevFmtShort:
  834. mSpec.format = PA_SAMPLE_S16NE;
  835. break;
  836. case DevFmtUInt:
  837. mDevice->FmtType = DevFmtInt;
  838. /* fall-through */
  839. case DevFmtInt:
  840. mSpec.format = PA_SAMPLE_S32NE;
  841. break;
  842. case DevFmtFloat:
  843. mSpec.format = PA_SAMPLE_FLOAT32NE;
  844. break;
  845. }
  846. mSpec.rate = mDevice->Frequency;
  847. mSpec.channels = static_cast<uint8_t>(mDevice->channelsFromFmt());
  848. if(pa_sample_spec_valid(&mSpec) == 0)
  849. throw al::backend_exception{ALC_INVALID_VALUE, "Invalid sample spec"};
  850. const ALuint frame_size{static_cast<ALuint>(pa_frame_size(&mSpec))};
  851. mAttr.maxlength = ~0u;
  852. mAttr.tlength = mDevice->BufferSize * frame_size;
  853. mAttr.prebuf = 0u;
  854. mAttr.minreq = mDevice->UpdateSize * frame_size;
  855. mAttr.fragsize = ~0u;
  856. mStream = mMainloop.connectStream(mDeviceName.c_str(), plock, mContext, flags, &mAttr, &mSpec,
  857. &chanmap, BackendType::Playback);
  858. pa_stream_set_state_callback(mStream, &PulsePlayback::streamStateCallbackC, this);
  859. pa_stream_set_moved_callback(mStream, &PulsePlayback::streamMovedCallbackC, this);
  860. mSpec = *(pa_stream_get_sample_spec(mStream));
  861. mFrameSize = static_cast<ALuint>(pa_frame_size(&mSpec));
  862. if(mDevice->Frequency != mSpec.rate)
  863. {
  864. /* Server updated our playback rate, so modify the buffer attribs
  865. * accordingly.
  866. */
  867. const auto scale = static_cast<double>(mSpec.rate) / mDevice->Frequency;
  868. const ALuint perlen{static_cast<ALuint>(clampd(scale*mDevice->UpdateSize + 0.5, 64.0,
  869. 8192.0))};
  870. const ALuint buflen{static_cast<ALuint>(clampd(scale*mDevice->BufferSize + 0.5, perlen*2,
  871. std::numeric_limits<int>::max()/mFrameSize))};
  872. mAttr.maxlength = ~0u;
  873. mAttr.tlength = buflen * mFrameSize;
  874. mAttr.prebuf = 0u;
  875. mAttr.minreq = perlen * mFrameSize;
  876. op = pa_stream_set_buffer_attr(mStream, &mAttr, &PulseMainloop::streamSuccessCallbackC,
  877. &mMainloop);
  878. mMainloop.waitForOperation(op, plock);
  879. mDevice->Frequency = mSpec.rate;
  880. }
  881. pa_stream_set_buffer_attr_callback(mStream, &PulsePlayback::bufferAttrCallbackC, this);
  882. bufferAttrCallback(mStream);
  883. mDevice->BufferSize = mAttr.tlength / mFrameSize;
  884. mDevice->UpdateSize = mAttr.minreq / mFrameSize;
  885. return true;
  886. }
  887. bool PulsePlayback::start()
  888. {
  889. auto plock = mMainloop.getLock();
  890. pa_stream_set_write_callback(mStream, &PulsePlayback::streamWriteCallbackC, this);
  891. pa_operation *op{pa_stream_cork(mStream, 0, &PulseMainloop::streamSuccessCallbackC,
  892. &mMainloop)};
  893. mMainloop.waitForOperation(op, plock);
  894. return true;
  895. }
  896. void PulsePlayback::stop()
  897. {
  898. auto plock = mMainloop.getLock();
  899. pa_operation *op{pa_stream_cork(mStream, 1, &PulseMainloop::streamSuccessCallbackC,
  900. &mMainloop)};
  901. mMainloop.waitForOperation(op, plock);
  902. pa_stream_set_write_callback(mStream, nullptr, nullptr);
  903. }
  904. ClockLatency PulsePlayback::getClockLatency()
  905. {
  906. ClockLatency ret;
  907. pa_usec_t latency;
  908. int neg, err;
  909. {
  910. auto _ = mMainloop.getLock();
  911. ret.ClockTime = GetDeviceClockTime(mDevice);
  912. err = pa_stream_get_latency(mStream, &latency, &neg);
  913. }
  914. if UNLIKELY(err != 0)
  915. {
  916. /* FIXME: if err = -PA_ERR_NODATA, it means we were called too soon
  917. * after starting the stream and no timing info has been received from
  918. * the server yet. Should we wait, possibly stalling the app, or give a
  919. * dummy value? Either way, it shouldn't be 0. */
  920. if(err != -PA_ERR_NODATA)
  921. ERR("Failed to get stream latency: 0x%x\n", err);
  922. latency = 0;
  923. neg = 0;
  924. }
  925. else if UNLIKELY(neg)
  926. latency = 0;
  927. ret.Latency = std::chrono::microseconds{latency};
  928. return ret;
  929. }
  930. struct PulseCapture final : public BackendBase {
  931. PulseCapture(ALCdevice *device) noexcept : BackendBase{device} { }
  932. ~PulseCapture() override;
  933. void streamStateCallback(pa_stream *stream) noexcept;
  934. static void streamStateCallbackC(pa_stream *stream, void *pdata) noexcept
  935. { static_cast<PulseCapture*>(pdata)->streamStateCallback(stream); }
  936. void sourceNameCallback(pa_context *context, const pa_source_info *info, int eol) noexcept;
  937. static void sourceNameCallbackC(pa_context *context, const pa_source_info *info, int eol, void *pdata) noexcept
  938. { static_cast<PulseCapture*>(pdata)->sourceNameCallback(context, info, eol); }
  939. void streamMovedCallback(pa_stream *stream) noexcept;
  940. static void streamMovedCallbackC(pa_stream *stream, void *pdata) noexcept
  941. { static_cast<PulseCapture*>(pdata)->streamMovedCallback(stream); }
  942. void open(const ALCchar *name) override;
  943. bool start() override;
  944. void stop() override;
  945. ALCenum captureSamples(al::byte *buffer, ALCuint samples) override;
  946. ALCuint availableSamples() override;
  947. ClockLatency getClockLatency() override;
  948. void lock() override { mMainloop.doLock(); }
  949. void unlock() override { mMainloop.doUnlock(); }
  950. PulseMainloop mMainloop;
  951. std::string mDeviceName;
  952. ALCuint mLastReadable{0u};
  953. al::byte mSilentVal{};
  954. al::span<const al::byte> mCapBuffer;
  955. ssize_t mCapLen{0};
  956. pa_buffer_attr mAttr{};
  957. pa_sample_spec mSpec{};
  958. pa_stream *mStream{nullptr};
  959. pa_context *mContext{nullptr};
  960. DEF_NEWDEL(PulseCapture)
  961. };
  962. PulseCapture::~PulseCapture()
  963. {
  964. if(!mContext)
  965. return;
  966. mMainloop.close(mContext, mStream);
  967. mContext = nullptr;
  968. mStream = nullptr;
  969. }
  970. void PulseCapture::streamStateCallback(pa_stream *stream) noexcept
  971. {
  972. if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
  973. {
  974. ERR("Received stream failure!\n");
  975. aluHandleDisconnect(mDevice, "Capture stream failure");
  976. }
  977. mMainloop.getCondVar().notify_all();
  978. }
  979. void PulseCapture::sourceNameCallback(pa_context*, const pa_source_info *info, int eol) noexcept
  980. {
  981. if(eol)
  982. {
  983. mMainloop.getCondVar().notify_all();
  984. return;
  985. }
  986. mDevice->DeviceName = info->description;
  987. }
  988. void PulseCapture::streamMovedCallback(pa_stream *stream) noexcept
  989. {
  990. mDeviceName = pa_stream_get_device_name(stream);
  991. TRACE("Stream moved to %s\n", mDeviceName.c_str());
  992. }
  993. void PulseCapture::open(const ALCchar *name)
  994. {
  995. const char *pulse_name{nullptr};
  996. if(name)
  997. {
  998. if(CaptureDevices.empty())
  999. probeCaptureDevices(mMainloop);
  1000. auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
  1001. [name](const DevMap &entry) -> bool
  1002. { return entry.name == name; }
  1003. );
  1004. if(iter == CaptureDevices.cend())
  1005. throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name};
  1006. pulse_name = iter->device_name.c_str();
  1007. mDevice->DeviceName = iter->name;
  1008. }
  1009. auto plock = mMainloop.getLock();
  1010. mContext = mMainloop.connectContext(plock);
  1011. pa_channel_map chanmap{};
  1012. switch(mDevice->FmtChans)
  1013. {
  1014. case DevFmtMono:
  1015. chanmap = MonoChanMap;
  1016. break;
  1017. case DevFmtStereo:
  1018. chanmap = StereoChanMap;
  1019. break;
  1020. case DevFmtQuad:
  1021. chanmap = QuadChanMap;
  1022. break;
  1023. case DevFmtX51:
  1024. chanmap = X51ChanMap;
  1025. break;
  1026. case DevFmtX51Rear:
  1027. chanmap = X51RearChanMap;
  1028. break;
  1029. case DevFmtX61:
  1030. chanmap = X61ChanMap;
  1031. break;
  1032. case DevFmtX71:
  1033. chanmap = X71ChanMap;
  1034. break;
  1035. case DevFmtAmbi3D:
  1036. throw al::backend_exception{ALC_INVALID_VALUE, "%s capture not supported",
  1037. DevFmtChannelsString(mDevice->FmtChans)};
  1038. }
  1039. SetChannelOrderFromMap(mDevice, chanmap);
  1040. switch(mDevice->FmtType)
  1041. {
  1042. case DevFmtUByte:
  1043. mSilentVal = al::byte(0x80);
  1044. mSpec.format = PA_SAMPLE_U8;
  1045. break;
  1046. case DevFmtShort:
  1047. mSpec.format = PA_SAMPLE_S16NE;
  1048. break;
  1049. case DevFmtInt:
  1050. mSpec.format = PA_SAMPLE_S32NE;
  1051. break;
  1052. case DevFmtFloat:
  1053. mSpec.format = PA_SAMPLE_FLOAT32NE;
  1054. break;
  1055. case DevFmtByte:
  1056. case DevFmtUShort:
  1057. case DevFmtUInt:
  1058. throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported",
  1059. DevFmtTypeString(mDevice->FmtType)};
  1060. }
  1061. mSpec.rate = mDevice->Frequency;
  1062. mSpec.channels = static_cast<uint8_t>(mDevice->channelsFromFmt());
  1063. if(pa_sample_spec_valid(&mSpec) == 0)
  1064. throw al::backend_exception{ALC_INVALID_VALUE, "Invalid sample format"};
  1065. const ALuint frame_size{static_cast<ALuint>(pa_frame_size(&mSpec))};
  1066. const ALuint samples{maxu(mDevice->BufferSize, 100 * mDevice->Frequency / 1000)};
  1067. mAttr.minreq = ~0u;
  1068. mAttr.prebuf = ~0u;
  1069. mAttr.maxlength = samples * frame_size;
  1070. mAttr.tlength = ~0u;
  1071. mAttr.fragsize = minu(samples, 50*mDevice->Frequency/1000) * frame_size;
  1072. pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY};
  1073. if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 1))
  1074. flags |= PA_STREAM_DONT_MOVE;
  1075. TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
  1076. mStream = mMainloop.connectStream(pulse_name, plock, mContext, flags, &mAttr, &mSpec, &chanmap,
  1077. BackendType::Capture);
  1078. pa_stream_set_moved_callback(mStream, &PulseCapture::streamMovedCallbackC, this);
  1079. pa_stream_set_state_callback(mStream, &PulseCapture::streamStateCallbackC, this);
  1080. mDeviceName = pa_stream_get_device_name(mStream);
  1081. if(mDevice->DeviceName.empty())
  1082. {
  1083. pa_operation *op{pa_context_get_source_info_by_name(mContext, mDeviceName.c_str(),
  1084. &PulseCapture::sourceNameCallbackC, this)};
  1085. mMainloop.waitForOperation(op, plock);
  1086. }
  1087. }
  1088. bool PulseCapture::start()
  1089. {
  1090. auto plock = mMainloop.getLock();
  1091. pa_operation *op{pa_stream_cork(mStream, 0, &PulseMainloop::streamSuccessCallbackC,
  1092. &mMainloop)};
  1093. mMainloop.waitForOperation(op, plock);
  1094. return true;
  1095. }
  1096. void PulseCapture::stop()
  1097. {
  1098. auto plock = mMainloop.getLock();
  1099. pa_operation *op{pa_stream_cork(mStream, 1, &PulseMainloop::streamSuccessCallbackC,
  1100. &mMainloop)};
  1101. mMainloop.waitForOperation(op, plock);
  1102. }
  1103. ALCenum PulseCapture::captureSamples(al::byte *buffer, ALCuint samples)
  1104. {
  1105. al::span<al::byte> dstbuf{buffer, samples * pa_frame_size(&mSpec)};
  1106. /* Capture is done in fragment-sized chunks, so we loop until we get all
  1107. * that's available */
  1108. mLastReadable -= static_cast<ALCuint>(dstbuf.size());
  1109. while(!dstbuf.empty())
  1110. {
  1111. if(!mCapBuffer.empty())
  1112. {
  1113. const size_t rem{minz(dstbuf.size(), mCapBuffer.size())};
  1114. if UNLIKELY(mCapLen < 0)
  1115. std::fill_n(dstbuf.begin(), rem, mSilentVal);
  1116. else
  1117. std::copy_n(mCapBuffer.begin(), rem, dstbuf.begin());
  1118. dstbuf = dstbuf.subspan(rem);
  1119. mCapBuffer = mCapBuffer.subspan(rem);
  1120. continue;
  1121. }
  1122. if UNLIKELY(!mDevice->Connected.load(std::memory_order_acquire))
  1123. break;
  1124. auto plock = mMainloop.getLock();
  1125. if(mCapLen != 0)
  1126. {
  1127. pa_stream_drop(mStream);
  1128. mCapBuffer = {};
  1129. mCapLen = 0;
  1130. }
  1131. const pa_stream_state_t state{pa_stream_get_state(mStream)};
  1132. if UNLIKELY(!PA_STREAM_IS_GOOD(state))
  1133. {
  1134. aluHandleDisconnect(mDevice, "Bad capture state: %u", state);
  1135. break;
  1136. }
  1137. const void *capbuf;
  1138. size_t caplen;
  1139. if UNLIKELY(pa_stream_peek(mStream, &capbuf, &caplen) < 0)
  1140. {
  1141. aluHandleDisconnect(mDevice, "Failed retrieving capture samples: %s",
  1142. pa_strerror(pa_context_errno(mContext)));
  1143. break;
  1144. }
  1145. plock.unlock();
  1146. if(caplen == 0) break;
  1147. if UNLIKELY(!capbuf)
  1148. mCapLen = -static_cast<ssize_t>(caplen);
  1149. else
  1150. mCapLen = static_cast<ssize_t>(caplen);
  1151. mCapBuffer = {static_cast<const al::byte*>(capbuf), caplen};
  1152. }
  1153. if(!dstbuf.empty())
  1154. std::fill(dstbuf.begin(), dstbuf.end(), mSilentVal);
  1155. return ALC_NO_ERROR;
  1156. }
  1157. ALCuint PulseCapture::availableSamples()
  1158. {
  1159. size_t readable{mCapBuffer.size()};
  1160. if(mDevice->Connected.load(std::memory_order_acquire))
  1161. {
  1162. auto _ = mMainloop.getLock();
  1163. size_t got{pa_stream_readable_size(mStream)};
  1164. if UNLIKELY(static_cast<ssize_t>(got) < 0)
  1165. {
  1166. const char *err{pa_strerror(static_cast<int>(got))};
  1167. ERR("pa_stream_readable_size() failed: %s\n", err);
  1168. aluHandleDisconnect(mDevice, "Failed getting readable size: %s", err);
  1169. }
  1170. else
  1171. {
  1172. const auto caplen = static_cast<size_t>(std::abs(mCapLen));
  1173. if(got > caplen) readable += got - caplen;
  1174. }
  1175. }
  1176. readable = std::min<size_t>(readable, std::numeric_limits<ALCuint>::max());
  1177. mLastReadable = std::max(mLastReadable, static_cast<ALCuint>(readable));
  1178. return mLastReadable / static_cast<ALCuint>(pa_frame_size(&mSpec));
  1179. }
  1180. ClockLatency PulseCapture::getClockLatency()
  1181. {
  1182. ClockLatency ret;
  1183. pa_usec_t latency;
  1184. int neg, err;
  1185. {
  1186. auto _ = mMainloop.getLock();
  1187. ret.ClockTime = GetDeviceClockTime(mDevice);
  1188. err = pa_stream_get_latency(mStream, &latency, &neg);
  1189. }
  1190. if UNLIKELY(err != 0)
  1191. {
  1192. ERR("Failed to get stream latency: 0x%x\n", err);
  1193. latency = 0;
  1194. neg = 0;
  1195. }
  1196. else if UNLIKELY(neg)
  1197. latency = 0;
  1198. ret.Latency = std::chrono::microseconds{latency};
  1199. return ret;
  1200. }
  1201. } // namespace
  1202. bool PulseBackendFactory::init()
  1203. {
  1204. #ifdef HAVE_DYNLOAD
  1205. if(!pulse_handle)
  1206. {
  1207. bool ret{true};
  1208. std::string missing_funcs;
  1209. #ifdef _WIN32
  1210. #define PALIB "libpulse-0.dll"
  1211. #elif defined(__APPLE__) && defined(__MACH__)
  1212. #define PALIB "libpulse.0.dylib"
  1213. #else
  1214. #define PALIB "libpulse.so.0"
  1215. #endif
  1216. pulse_handle = LoadLib(PALIB);
  1217. if(!pulse_handle)
  1218. {
  1219. WARN("Failed to load %s\n", PALIB);
  1220. return false;
  1221. }
  1222. #define LOAD_FUNC(x) do { \
  1223. p##x = reinterpret_cast<decltype(p##x)>(GetSymbol(pulse_handle, #x)); \
  1224. if(!(p##x)) { \
  1225. ret = false; \
  1226. missing_funcs += "\n" #x; \
  1227. } \
  1228. } while(0)
  1229. PULSE_FUNCS(LOAD_FUNC)
  1230. #undef LOAD_FUNC
  1231. if(!ret)
  1232. {
  1233. WARN("Missing expected functions:%s\n", missing_funcs.c_str());
  1234. CloseLib(pulse_handle);
  1235. pulse_handle = nullptr;
  1236. return false;
  1237. }
  1238. }
  1239. #endif /* HAVE_DYNLOAD */
  1240. pulse_ctx_flags = PA_CONTEXT_NOFLAGS;
  1241. if(!GetConfigValueBool(nullptr, "pulse", "spawn-server", 1))
  1242. pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;
  1243. try {
  1244. auto plock = gGlobalMainloop.getLock();
  1245. pa_context *context{gGlobalMainloop.connectContext(plock)};
  1246. pa_context_disconnect(context);
  1247. pa_context_unref(context);
  1248. return true;
  1249. }
  1250. catch(...) {
  1251. return false;
  1252. }
  1253. }
  1254. bool PulseBackendFactory::querySupport(BackendType type)
  1255. { return type == BackendType::Playback || type == BackendType::Capture; }
  1256. void PulseBackendFactory::probe(DevProbe type, std::string *outnames)
  1257. {
  1258. auto add_device = [outnames](const DevMap &entry) -> void
  1259. {
  1260. /* +1 to also append the null char (to ensure a null-separated list and
  1261. * double-null terminated list).
  1262. */
  1263. outnames->append(entry.name.c_str(), entry.name.length()+1);
  1264. };
  1265. switch(type)
  1266. {
  1267. case DevProbe::Playback:
  1268. probePlaybackDevices(gGlobalMainloop);
  1269. std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
  1270. break;
  1271. case DevProbe::Capture:
  1272. probeCaptureDevices(gGlobalMainloop);
  1273. std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
  1274. break;
  1275. }
  1276. }
  1277. BackendPtr PulseBackendFactory::createBackend(ALCdevice *device, BackendType type)
  1278. {
  1279. if(type == BackendType::Playback)
  1280. return BackendPtr{new PulsePlayback{device}};
  1281. if(type == BackendType::Capture)
  1282. return BackendPtr{new PulseCapture{device}};
  1283. return nullptr;
  1284. }
  1285. BackendFactory &PulseBackendFactory::getFactory()
  1286. {
  1287. static PulseBackendFactory factory{};
  1288. return factory;
  1289. }