alsa.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include "backends/alsa.h"
  22. #include <algorithm>
  23. #include <atomic>
  24. #include <cassert>
  25. #include <cerrno>
  26. #include <chrono>
  27. #include <cstring>
  28. #include <exception>
  29. #include <functional>
  30. #include <memory>
  31. #include <string>
  32. #include <thread>
  33. #include <utility>
  34. #include "albyte.h"
  35. #include "alcmain.h"
  36. #include "alconfig.h"
  37. #include "almalloc.h"
  38. #include "alnumeric.h"
  39. #include "aloptional.h"
  40. #include "alu.h"
  41. #include "core/logging.h"
  42. #include "dynload.h"
  43. #include "ringbuffer.h"
  44. #include "threads.h"
  45. #include "vector.h"
  46. #include <alsa/asoundlib.h>
  47. namespace {
  48. constexpr char alsaDevice[] = "ALSA Default";
  49. #ifdef HAVE_DYNLOAD
  50. #define ALSA_FUNCS(MAGIC) \
  51. MAGIC(snd_strerror); \
  52. MAGIC(snd_pcm_open); \
  53. MAGIC(snd_pcm_close); \
  54. MAGIC(snd_pcm_nonblock); \
  55. MAGIC(snd_pcm_frames_to_bytes); \
  56. MAGIC(snd_pcm_bytes_to_frames); \
  57. MAGIC(snd_pcm_hw_params_malloc); \
  58. MAGIC(snd_pcm_hw_params_free); \
  59. MAGIC(snd_pcm_hw_params_any); \
  60. MAGIC(snd_pcm_hw_params_current); \
  61. MAGIC(snd_pcm_hw_params_set_access); \
  62. MAGIC(snd_pcm_hw_params_set_format); \
  63. MAGIC(snd_pcm_hw_params_set_channels); \
  64. MAGIC(snd_pcm_hw_params_set_periods_near); \
  65. MAGIC(snd_pcm_hw_params_set_rate_near); \
  66. MAGIC(snd_pcm_hw_params_set_rate); \
  67. MAGIC(snd_pcm_hw_params_set_rate_resample); \
  68. MAGIC(snd_pcm_hw_params_set_buffer_time_near); \
  69. MAGIC(snd_pcm_hw_params_set_period_time_near); \
  70. MAGIC(snd_pcm_hw_params_set_buffer_size_near); \
  71. MAGIC(snd_pcm_hw_params_set_period_size_near); \
  72. MAGIC(snd_pcm_hw_params_set_buffer_size_min); \
  73. MAGIC(snd_pcm_hw_params_get_buffer_time_min); \
  74. MAGIC(snd_pcm_hw_params_get_buffer_time_max); \
  75. MAGIC(snd_pcm_hw_params_get_period_time_min); \
  76. MAGIC(snd_pcm_hw_params_get_period_time_max); \
  77. MAGIC(snd_pcm_hw_params_get_buffer_size); \
  78. MAGIC(snd_pcm_hw_params_get_period_size); \
  79. MAGIC(snd_pcm_hw_params_get_access); \
  80. MAGIC(snd_pcm_hw_params_get_periods); \
  81. MAGIC(snd_pcm_hw_params_test_format); \
  82. MAGIC(snd_pcm_hw_params_test_channels); \
  83. MAGIC(snd_pcm_hw_params); \
  84. MAGIC(snd_pcm_sw_params_malloc); \
  85. MAGIC(snd_pcm_sw_params_current); \
  86. MAGIC(snd_pcm_sw_params_set_avail_min); \
  87. MAGIC(snd_pcm_sw_params_set_stop_threshold); \
  88. MAGIC(snd_pcm_sw_params); \
  89. MAGIC(snd_pcm_sw_params_free); \
  90. MAGIC(snd_pcm_prepare); \
  91. MAGIC(snd_pcm_start); \
  92. MAGIC(snd_pcm_resume); \
  93. MAGIC(snd_pcm_reset); \
  94. MAGIC(snd_pcm_wait); \
  95. MAGIC(snd_pcm_delay); \
  96. MAGIC(snd_pcm_state); \
  97. MAGIC(snd_pcm_avail_update); \
  98. MAGIC(snd_pcm_areas_silence); \
  99. MAGIC(snd_pcm_mmap_begin); \
  100. MAGIC(snd_pcm_mmap_commit); \
  101. MAGIC(snd_pcm_readi); \
  102. MAGIC(snd_pcm_writei); \
  103. MAGIC(snd_pcm_drain); \
  104. MAGIC(snd_pcm_drop); \
  105. MAGIC(snd_pcm_recover); \
  106. MAGIC(snd_pcm_info_malloc); \
  107. MAGIC(snd_pcm_info_free); \
  108. MAGIC(snd_pcm_info_set_device); \
  109. MAGIC(snd_pcm_info_set_subdevice); \
  110. MAGIC(snd_pcm_info_set_stream); \
  111. MAGIC(snd_pcm_info_get_name); \
  112. MAGIC(snd_ctl_pcm_next_device); \
  113. MAGIC(snd_ctl_pcm_info); \
  114. MAGIC(snd_ctl_open); \
  115. MAGIC(snd_ctl_close); \
  116. MAGIC(snd_ctl_card_info_malloc); \
  117. MAGIC(snd_ctl_card_info_free); \
  118. MAGIC(snd_ctl_card_info); \
  119. MAGIC(snd_ctl_card_info_get_name); \
  120. MAGIC(snd_ctl_card_info_get_id); \
  121. MAGIC(snd_card_next); \
  122. MAGIC(snd_config_update_free_global)
  123. static void *alsa_handle;
  124. #define MAKE_FUNC(f) decltype(f) * p##f
  125. ALSA_FUNCS(MAKE_FUNC);
  126. #undef MAKE_FUNC
  127. #ifndef IN_IDE_PARSER
  128. #define snd_strerror psnd_strerror
  129. #define snd_pcm_open psnd_pcm_open
  130. #define snd_pcm_close psnd_pcm_close
  131. #define snd_pcm_nonblock psnd_pcm_nonblock
  132. #define snd_pcm_frames_to_bytes psnd_pcm_frames_to_bytes
  133. #define snd_pcm_bytes_to_frames psnd_pcm_bytes_to_frames
  134. #define snd_pcm_hw_params_malloc psnd_pcm_hw_params_malloc
  135. #define snd_pcm_hw_params_free psnd_pcm_hw_params_free
  136. #define snd_pcm_hw_params_any psnd_pcm_hw_params_any
  137. #define snd_pcm_hw_params_current psnd_pcm_hw_params_current
  138. #define snd_pcm_hw_params_set_access psnd_pcm_hw_params_set_access
  139. #define snd_pcm_hw_params_set_format psnd_pcm_hw_params_set_format
  140. #define snd_pcm_hw_params_set_channels psnd_pcm_hw_params_set_channels
  141. #define snd_pcm_hw_params_set_periods_near psnd_pcm_hw_params_set_periods_near
  142. #define snd_pcm_hw_params_set_rate_near psnd_pcm_hw_params_set_rate_near
  143. #define snd_pcm_hw_params_set_rate psnd_pcm_hw_params_set_rate
  144. #define snd_pcm_hw_params_set_rate_resample psnd_pcm_hw_params_set_rate_resample
  145. #define snd_pcm_hw_params_set_buffer_time_near psnd_pcm_hw_params_set_buffer_time_near
  146. #define snd_pcm_hw_params_set_period_time_near psnd_pcm_hw_params_set_period_time_near
  147. #define snd_pcm_hw_params_set_buffer_size_near psnd_pcm_hw_params_set_buffer_size_near
  148. #define snd_pcm_hw_params_set_period_size_near psnd_pcm_hw_params_set_period_size_near
  149. #define snd_pcm_hw_params_set_buffer_size_min psnd_pcm_hw_params_set_buffer_size_min
  150. #define snd_pcm_hw_params_get_buffer_time_min psnd_pcm_hw_params_get_buffer_time_min
  151. #define snd_pcm_hw_params_get_buffer_time_max psnd_pcm_hw_params_get_buffer_time_max
  152. #define snd_pcm_hw_params_get_period_time_min psnd_pcm_hw_params_get_period_time_min
  153. #define snd_pcm_hw_params_get_period_time_max psnd_pcm_hw_params_get_period_time_max
  154. #define snd_pcm_hw_params_get_buffer_size psnd_pcm_hw_params_get_buffer_size
  155. #define snd_pcm_hw_params_get_period_size psnd_pcm_hw_params_get_period_size
  156. #define snd_pcm_hw_params_get_access psnd_pcm_hw_params_get_access
  157. #define snd_pcm_hw_params_get_periods psnd_pcm_hw_params_get_periods
  158. #define snd_pcm_hw_params_test_format psnd_pcm_hw_params_test_format
  159. #define snd_pcm_hw_params_test_channels psnd_pcm_hw_params_test_channels
  160. #define snd_pcm_hw_params psnd_pcm_hw_params
  161. #define snd_pcm_sw_params_malloc psnd_pcm_sw_params_malloc
  162. #define snd_pcm_sw_params_current psnd_pcm_sw_params_current
  163. #define snd_pcm_sw_params_set_avail_min psnd_pcm_sw_params_set_avail_min
  164. #define snd_pcm_sw_params_set_stop_threshold psnd_pcm_sw_params_set_stop_threshold
  165. #define snd_pcm_sw_params psnd_pcm_sw_params
  166. #define snd_pcm_sw_params_free psnd_pcm_sw_params_free
  167. #define snd_pcm_prepare psnd_pcm_prepare
  168. #define snd_pcm_start psnd_pcm_start
  169. #define snd_pcm_resume psnd_pcm_resume
  170. #define snd_pcm_reset psnd_pcm_reset
  171. #define snd_pcm_wait psnd_pcm_wait
  172. #define snd_pcm_delay psnd_pcm_delay
  173. #define snd_pcm_state psnd_pcm_state
  174. #define snd_pcm_avail_update psnd_pcm_avail_update
  175. #define snd_pcm_areas_silence psnd_pcm_areas_silence
  176. #define snd_pcm_mmap_begin psnd_pcm_mmap_begin
  177. #define snd_pcm_mmap_commit psnd_pcm_mmap_commit
  178. #define snd_pcm_readi psnd_pcm_readi
  179. #define snd_pcm_writei psnd_pcm_writei
  180. #define snd_pcm_drain psnd_pcm_drain
  181. #define snd_pcm_drop psnd_pcm_drop
  182. #define snd_pcm_recover psnd_pcm_recover
  183. #define snd_pcm_info_malloc psnd_pcm_info_malloc
  184. #define snd_pcm_info_free psnd_pcm_info_free
  185. #define snd_pcm_info_set_device psnd_pcm_info_set_device
  186. #define snd_pcm_info_set_subdevice psnd_pcm_info_set_subdevice
  187. #define snd_pcm_info_set_stream psnd_pcm_info_set_stream
  188. #define snd_pcm_info_get_name psnd_pcm_info_get_name
  189. #define snd_ctl_pcm_next_device psnd_ctl_pcm_next_device
  190. #define snd_ctl_pcm_info psnd_ctl_pcm_info
  191. #define snd_ctl_open psnd_ctl_open
  192. #define snd_ctl_close psnd_ctl_close
  193. #define snd_ctl_card_info_malloc psnd_ctl_card_info_malloc
  194. #define snd_ctl_card_info_free psnd_ctl_card_info_free
  195. #define snd_ctl_card_info psnd_ctl_card_info
  196. #define snd_ctl_card_info_get_name psnd_ctl_card_info_get_name
  197. #define snd_ctl_card_info_get_id psnd_ctl_card_info_get_id
  198. #define snd_card_next psnd_card_next
  199. #define snd_config_update_free_global psnd_config_update_free_global
  200. #endif
  201. #endif
  202. struct HwParamsDeleter {
  203. void operator()(snd_pcm_hw_params_t *ptr) { snd_pcm_hw_params_free(ptr); }
  204. };
  205. using HwParamsPtr = std::unique_ptr<snd_pcm_hw_params_t,HwParamsDeleter>;
  206. HwParamsPtr CreateHwParams()
  207. {
  208. snd_pcm_hw_params_t *hp{};
  209. snd_pcm_hw_params_malloc(&hp);
  210. return HwParamsPtr{hp};
  211. }
  212. struct SwParamsDeleter {
  213. void operator()(snd_pcm_sw_params_t *ptr) { snd_pcm_sw_params_free(ptr); }
  214. };
  215. using SwParamsPtr = std::unique_ptr<snd_pcm_sw_params_t,SwParamsDeleter>;
  216. SwParamsPtr CreateSwParams()
  217. {
  218. snd_pcm_sw_params_t *sp{};
  219. snd_pcm_sw_params_malloc(&sp);
  220. return SwParamsPtr{sp};
  221. }
  222. struct DevMap {
  223. std::string name;
  224. std::string device_name;
  225. };
  226. al::vector<DevMap> PlaybackDevices;
  227. al::vector<DevMap> CaptureDevices;
  228. const char *prefix_name(snd_pcm_stream_t stream)
  229. {
  230. assert(stream == SND_PCM_STREAM_PLAYBACK || stream == SND_PCM_STREAM_CAPTURE);
  231. return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix";
  232. }
  233. al::vector<DevMap> probe_devices(snd_pcm_stream_t stream)
  234. {
  235. al::vector<DevMap> devlist;
  236. snd_ctl_card_info_t *info;
  237. snd_ctl_card_info_malloc(&info);
  238. snd_pcm_info_t *pcminfo;
  239. snd_pcm_info_malloc(&pcminfo);
  240. devlist.emplace_back(DevMap{alsaDevice,
  241. GetConfigValue(nullptr, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? "device" : "capture",
  242. "default")});
  243. const char *customdevs{GetConfigValue(nullptr, "alsa",
  244. (stream == SND_PCM_STREAM_PLAYBACK) ? "custom-devices" : "custom-captures", "")};
  245. while(const char *curdev{customdevs})
  246. {
  247. if(!curdev[0]) break;
  248. customdevs = strchr(curdev, ';');
  249. const char *sep{strchr(curdev, '=')};
  250. if(!sep)
  251. {
  252. std::string spec{customdevs ? std::string(curdev, customdevs++) : std::string(curdev)};
  253. ERR("Invalid ALSA device specification \"%s\"\n", spec.c_str());
  254. continue;
  255. }
  256. const char *oldsep{sep++};
  257. devlist.emplace_back(DevMap{std::string(curdev, oldsep),
  258. customdevs ? std::string(sep, customdevs++) : std::string(sep)});
  259. const auto &entry = devlist.back();
  260. TRACE("Got device \"%s\", \"%s\"\n", entry.name.c_str(), entry.device_name.c_str());
  261. }
  262. const std::string main_prefix{
  263. ConfigValueStr(nullptr, "alsa", prefix_name(stream)).value_or("plughw:")};
  264. int card{-1};
  265. int err{snd_card_next(&card)};
  266. for(;err >= 0 && card >= 0;err = snd_card_next(&card))
  267. {
  268. std::string name{"hw:" + std::to_string(card)};
  269. snd_ctl_t *handle;
  270. if((err=snd_ctl_open(&handle, name.c_str(), 0)) < 0)
  271. {
  272. ERR("control open (hw:%d): %s\n", card, snd_strerror(err));
  273. continue;
  274. }
  275. if((err=snd_ctl_card_info(handle, info)) < 0)
  276. {
  277. ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err));
  278. snd_ctl_close(handle);
  279. continue;
  280. }
  281. const char *cardname{snd_ctl_card_info_get_name(info)};
  282. const char *cardid{snd_ctl_card_info_get_id(info)};
  283. name = prefix_name(stream);
  284. name += '-';
  285. name += cardid;
  286. const std::string card_prefix{
  287. ConfigValueStr(nullptr, "alsa", name.c_str()).value_or(main_prefix)};
  288. int dev{-1};
  289. while(1)
  290. {
  291. if(snd_ctl_pcm_next_device(handle, &dev) < 0)
  292. ERR("snd_ctl_pcm_next_device failed\n");
  293. if(dev < 0) break;
  294. snd_pcm_info_set_device(pcminfo, static_cast<uint>(dev));
  295. snd_pcm_info_set_subdevice(pcminfo, 0);
  296. snd_pcm_info_set_stream(pcminfo, stream);
  297. if((err=snd_ctl_pcm_info(handle, pcminfo)) < 0)
  298. {
  299. if(err != -ENOENT)
  300. ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err));
  301. continue;
  302. }
  303. /* "prefix-cardid-dev" */
  304. name = prefix_name(stream);
  305. name += '-';
  306. name += cardid;
  307. name += '-';
  308. name += std::to_string(dev);
  309. const std::string device_prefix{
  310. ConfigValueStr(nullptr, "alsa", name.c_str()).value_or(card_prefix)};
  311. /* "CardName, PcmName (CARD=cardid,DEV=dev)" */
  312. name = cardname;
  313. name += ", ";
  314. name += snd_pcm_info_get_name(pcminfo);
  315. name += " (CARD=";
  316. name += cardid;
  317. name += ",DEV=";
  318. name += std::to_string(dev);
  319. name += ')';
  320. /* "devprefixCARD=cardid,DEV=dev" */
  321. std::string device{device_prefix};
  322. device += "CARD=";
  323. device += cardid;
  324. device += ",DEV=";
  325. device += std::to_string(dev);
  326. devlist.emplace_back(DevMap{std::move(name), std::move(device)});
  327. const auto &entry = devlist.back();
  328. TRACE("Got device \"%s\", \"%s\"\n", entry.name.c_str(), entry.device_name.c_str());
  329. }
  330. snd_ctl_close(handle);
  331. }
  332. if(err < 0)
  333. ERR("snd_card_next failed: %s\n", snd_strerror(err));
  334. snd_pcm_info_free(pcminfo);
  335. snd_ctl_card_info_free(info);
  336. return devlist;
  337. }
  338. int verify_state(snd_pcm_t *handle)
  339. {
  340. snd_pcm_state_t state{snd_pcm_state(handle)};
  341. int err;
  342. switch(state)
  343. {
  344. case SND_PCM_STATE_OPEN:
  345. case SND_PCM_STATE_SETUP:
  346. case SND_PCM_STATE_PREPARED:
  347. case SND_PCM_STATE_RUNNING:
  348. case SND_PCM_STATE_DRAINING:
  349. case SND_PCM_STATE_PAUSED:
  350. /* All Okay */
  351. break;
  352. case SND_PCM_STATE_XRUN:
  353. if((err=snd_pcm_recover(handle, -EPIPE, 1)) < 0)
  354. return err;
  355. break;
  356. case SND_PCM_STATE_SUSPENDED:
  357. if((err=snd_pcm_recover(handle, -ESTRPIPE, 1)) < 0)
  358. return err;
  359. break;
  360. case SND_PCM_STATE_DISCONNECTED:
  361. return -ENODEV;
  362. }
  363. return state;
  364. }
  365. struct AlsaPlayback final : public BackendBase {
  366. AlsaPlayback(ALCdevice *device) noexcept : BackendBase{device} { }
  367. ~AlsaPlayback() override;
  368. int mixerProc();
  369. int mixerNoMMapProc();
  370. void open(const char *name) override;
  371. bool reset() override;
  372. void start() override;
  373. void stop() override;
  374. ClockLatency getClockLatency() override;
  375. snd_pcm_t *mPcmHandle{nullptr};
  376. std::mutex mMutex;
  377. al::vector<al::byte> mBuffer;
  378. std::atomic<bool> mKillNow{true};
  379. std::thread mThread;
  380. DEF_NEWDEL(AlsaPlayback)
  381. };
  382. AlsaPlayback::~AlsaPlayback()
  383. {
  384. if(mPcmHandle)
  385. snd_pcm_close(mPcmHandle);
  386. mPcmHandle = nullptr;
  387. }
  388. int AlsaPlayback::mixerProc()
  389. {
  390. SetRTPriority();
  391. althrd_setname(MIXER_THREAD_NAME);
  392. const size_t samplebits{mDevice->bytesFromFmt() * 8};
  393. const snd_pcm_uframes_t update_size{mDevice->UpdateSize};
  394. const snd_pcm_uframes_t buffer_size{mDevice->BufferSize};
  395. while(!mKillNow.load(std::memory_order_acquire))
  396. {
  397. int state{verify_state(mPcmHandle)};
  398. if(state < 0)
  399. {
  400. ERR("Invalid state detected: %s\n", snd_strerror(state));
  401. mDevice->handleDisconnect("Bad state: %s", snd_strerror(state));
  402. break;
  403. }
  404. snd_pcm_sframes_t avails{snd_pcm_avail_update(mPcmHandle)};
  405. if(avails < 0)
  406. {
  407. ERR("available update failed: %s\n", snd_strerror(static_cast<int>(avails)));
  408. continue;
  409. }
  410. snd_pcm_uframes_t avail{static_cast<snd_pcm_uframes_t>(avails)};
  411. if(avail > buffer_size)
  412. {
  413. WARN("available samples exceeds the buffer size\n");
  414. snd_pcm_reset(mPcmHandle);
  415. continue;
  416. }
  417. // make sure there's frames to process
  418. if(avail < update_size)
  419. {
  420. if(state != SND_PCM_STATE_RUNNING)
  421. {
  422. int err{snd_pcm_start(mPcmHandle)};
  423. if(err < 0)
  424. {
  425. ERR("start failed: %s\n", snd_strerror(err));
  426. continue;
  427. }
  428. }
  429. if(snd_pcm_wait(mPcmHandle, 1000) == 0)
  430. ERR("Wait timeout... buffer size too low?\n");
  431. continue;
  432. }
  433. avail -= avail%update_size;
  434. // it is possible that contiguous areas are smaller, thus we use a loop
  435. std::lock_guard<std::mutex> _{mMutex};
  436. while(avail > 0)
  437. {
  438. snd_pcm_uframes_t frames{avail};
  439. const snd_pcm_channel_area_t *areas{};
  440. snd_pcm_uframes_t offset{};
  441. int err{snd_pcm_mmap_begin(mPcmHandle, &areas, &offset, &frames)};
  442. if(err < 0)
  443. {
  444. ERR("mmap begin error: %s\n", snd_strerror(err));
  445. break;
  446. }
  447. char *WritePtr{static_cast<char*>(areas->addr) + (offset * areas->step / 8)};
  448. mDevice->renderSamples(WritePtr, static_cast<uint>(frames), areas->step/samplebits);
  449. snd_pcm_sframes_t commitres{snd_pcm_mmap_commit(mPcmHandle, offset, frames)};
  450. if(commitres < 0 || static_cast<snd_pcm_uframes_t>(commitres) != frames)
  451. {
  452. ERR("mmap commit error: %s\n",
  453. snd_strerror(commitres >= 0 ? -EPIPE : static_cast<int>(commitres)));
  454. break;
  455. }
  456. avail -= frames;
  457. }
  458. }
  459. return 0;
  460. }
  461. int AlsaPlayback::mixerNoMMapProc()
  462. {
  463. SetRTPriority();
  464. althrd_setname(MIXER_THREAD_NAME);
  465. const size_t frame_step{mDevice->channelsFromFmt()};
  466. const snd_pcm_uframes_t update_size{mDevice->UpdateSize};
  467. const snd_pcm_uframes_t buffer_size{mDevice->BufferSize};
  468. while(!mKillNow.load(std::memory_order_acquire))
  469. {
  470. int state{verify_state(mPcmHandle)};
  471. if(state < 0)
  472. {
  473. ERR("Invalid state detected: %s\n", snd_strerror(state));
  474. mDevice->handleDisconnect("Bad state: %s", snd_strerror(state));
  475. break;
  476. }
  477. snd_pcm_sframes_t avail{snd_pcm_avail_update(mPcmHandle)};
  478. if(avail < 0)
  479. {
  480. ERR("available update failed: %s\n", snd_strerror(static_cast<int>(avail)));
  481. continue;
  482. }
  483. if(static_cast<snd_pcm_uframes_t>(avail) > buffer_size)
  484. {
  485. WARN("available samples exceeds the buffer size\n");
  486. snd_pcm_reset(mPcmHandle);
  487. continue;
  488. }
  489. if(static_cast<snd_pcm_uframes_t>(avail) < update_size)
  490. {
  491. if(state != SND_PCM_STATE_RUNNING)
  492. {
  493. int err{snd_pcm_start(mPcmHandle)};
  494. if(err < 0)
  495. {
  496. ERR("start failed: %s\n", snd_strerror(err));
  497. continue;
  498. }
  499. }
  500. if(snd_pcm_wait(mPcmHandle, 1000) == 0)
  501. ERR("Wait timeout... buffer size too low?\n");
  502. continue;
  503. }
  504. al::byte *WritePtr{mBuffer.data()};
  505. avail = snd_pcm_bytes_to_frames(mPcmHandle, static_cast<ssize_t>(mBuffer.size()));
  506. std::lock_guard<std::mutex> _{mMutex};
  507. mDevice->renderSamples(WritePtr, static_cast<uint>(avail), frame_step);
  508. while(avail > 0)
  509. {
  510. snd_pcm_sframes_t ret{snd_pcm_writei(mPcmHandle, WritePtr,
  511. static_cast<snd_pcm_uframes_t>(avail))};
  512. switch(ret)
  513. {
  514. case -EAGAIN:
  515. continue;
  516. #if ESTRPIPE != EPIPE
  517. case -ESTRPIPE:
  518. #endif
  519. case -EPIPE:
  520. case -EINTR:
  521. ret = snd_pcm_recover(mPcmHandle, static_cast<int>(ret), 1);
  522. if(ret < 0)
  523. avail = 0;
  524. break;
  525. default:
  526. if(ret >= 0)
  527. {
  528. WritePtr += snd_pcm_frames_to_bytes(mPcmHandle, ret);
  529. avail -= ret;
  530. }
  531. break;
  532. }
  533. if(ret < 0)
  534. {
  535. ret = snd_pcm_prepare(mPcmHandle);
  536. if(ret < 0) break;
  537. }
  538. }
  539. }
  540. return 0;
  541. }
  542. void AlsaPlayback::open(const char *name)
  543. {
  544. const char *driver{};
  545. if(name)
  546. {
  547. if(PlaybackDevices.empty())
  548. PlaybackDevices = probe_devices(SND_PCM_STREAM_PLAYBACK);
  549. auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
  550. [name](const DevMap &entry) -> bool
  551. { return entry.name == name; }
  552. );
  553. if(iter == PlaybackDevices.cend())
  554. throw al::backend_exception{al::backend_error::NoDevice,
  555. "Device name \"%s\" not found", name};
  556. driver = iter->device_name.c_str();
  557. }
  558. else
  559. {
  560. name = alsaDevice;
  561. driver = GetConfigValue(nullptr, "alsa", "device", "default");
  562. }
  563. TRACE("Opening device \"%s\"\n", driver);
  564. int err{snd_pcm_open(&mPcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)};
  565. if(err < 0)
  566. throw al::backend_exception{al::backend_error::NoDevice,
  567. "Could not open ALSA device \"%s\"", driver};
  568. /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
  569. snd_config_update_free_global();
  570. mDevice->DeviceName = name;
  571. }
  572. bool AlsaPlayback::reset()
  573. {
  574. snd_pcm_format_t format{SND_PCM_FORMAT_UNKNOWN};
  575. switch(mDevice->FmtType)
  576. {
  577. case DevFmtByte:
  578. format = SND_PCM_FORMAT_S8;
  579. break;
  580. case DevFmtUByte:
  581. format = SND_PCM_FORMAT_U8;
  582. break;
  583. case DevFmtShort:
  584. format = SND_PCM_FORMAT_S16;
  585. break;
  586. case DevFmtUShort:
  587. format = SND_PCM_FORMAT_U16;
  588. break;
  589. case DevFmtInt:
  590. format = SND_PCM_FORMAT_S32;
  591. break;
  592. case DevFmtUInt:
  593. format = SND_PCM_FORMAT_U32;
  594. break;
  595. case DevFmtFloat:
  596. format = SND_PCM_FORMAT_FLOAT;
  597. break;
  598. }
  599. bool allowmmap{!!GetConfigValueBool(mDevice->DeviceName.c_str(), "alsa", "mmap", 1)};
  600. uint periodLen{static_cast<uint>(mDevice->UpdateSize * 1000000_u64 / mDevice->Frequency)};
  601. uint bufferLen{static_cast<uint>(mDevice->BufferSize * 1000000_u64 / mDevice->Frequency)};
  602. uint rate{mDevice->Frequency};
  603. int err{};
  604. HwParamsPtr hp{CreateHwParams()};
  605. #define CHECK(x) do { \
  606. if((err=(x)) < 0) \
  607. throw al::backend_exception{al::backend_error::DeviceError, #x " failed: %s", \
  608. snd_strerror(err)}; \
  609. } while(0)
  610. CHECK(snd_pcm_hw_params_any(mPcmHandle, hp.get()));
  611. /* set interleaved access */
  612. if(!allowmmap
  613. || snd_pcm_hw_params_set_access(mPcmHandle, hp.get(), SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0)
  614. {
  615. /* No mmap */
  616. CHECK(snd_pcm_hw_params_set_access(mPcmHandle, hp.get(), SND_PCM_ACCESS_RW_INTERLEAVED));
  617. }
  618. /* test and set format (implicitly sets sample bits) */
  619. if(snd_pcm_hw_params_test_format(mPcmHandle, hp.get(), format) < 0)
  620. {
  621. static const struct {
  622. snd_pcm_format_t format;
  623. DevFmtType fmttype;
  624. } formatlist[] = {
  625. { SND_PCM_FORMAT_FLOAT, DevFmtFloat },
  626. { SND_PCM_FORMAT_S32, DevFmtInt },
  627. { SND_PCM_FORMAT_U32, DevFmtUInt },
  628. { SND_PCM_FORMAT_S16, DevFmtShort },
  629. { SND_PCM_FORMAT_U16, DevFmtUShort },
  630. { SND_PCM_FORMAT_S8, DevFmtByte },
  631. { SND_PCM_FORMAT_U8, DevFmtUByte },
  632. };
  633. for(const auto &fmt : formatlist)
  634. {
  635. format = fmt.format;
  636. if(snd_pcm_hw_params_test_format(mPcmHandle, hp.get(), format) >= 0)
  637. {
  638. mDevice->FmtType = fmt.fmttype;
  639. break;
  640. }
  641. }
  642. }
  643. CHECK(snd_pcm_hw_params_set_format(mPcmHandle, hp.get(), format));
  644. /* test and set channels (implicitly sets frame bits) */
  645. if(snd_pcm_hw_params_test_channels(mPcmHandle, hp.get(), mDevice->channelsFromFmt()) < 0)
  646. {
  647. static const DevFmtChannels channellist[] = {
  648. DevFmtStereo,
  649. DevFmtQuad,
  650. DevFmtX51,
  651. DevFmtX71,
  652. DevFmtMono,
  653. };
  654. for(const auto &chan : channellist)
  655. {
  656. if(snd_pcm_hw_params_test_channels(mPcmHandle, hp.get(), ChannelsFromDevFmt(chan, 0)) >= 0)
  657. {
  658. mDevice->FmtChans = chan;
  659. mDevice->mAmbiOrder = 0;
  660. break;
  661. }
  662. }
  663. }
  664. CHECK(snd_pcm_hw_params_set_channels(mPcmHandle, hp.get(), mDevice->channelsFromFmt()));
  665. /* set rate (implicitly constrains period/buffer parameters) */
  666. if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "alsa", "allow-resampler", 0)
  667. || !mDevice->Flags.test(FrequencyRequest))
  668. {
  669. if(snd_pcm_hw_params_set_rate_resample(mPcmHandle, hp.get(), 0) < 0)
  670. ERR("Failed to disable ALSA resampler\n");
  671. }
  672. else if(snd_pcm_hw_params_set_rate_resample(mPcmHandle, hp.get(), 1) < 0)
  673. ERR("Failed to enable ALSA resampler\n");
  674. CHECK(snd_pcm_hw_params_set_rate_near(mPcmHandle, hp.get(), &rate, nullptr));
  675. /* set period time (implicitly constrains period/buffer parameters) */
  676. if((err=snd_pcm_hw_params_set_period_time_near(mPcmHandle, hp.get(), &periodLen, nullptr)) < 0)
  677. ERR("snd_pcm_hw_params_set_period_time_near failed: %s\n", snd_strerror(err));
  678. /* set buffer time (implicitly sets buffer size/bytes/time and period size/bytes) */
  679. if((err=snd_pcm_hw_params_set_buffer_time_near(mPcmHandle, hp.get(), &bufferLen, nullptr)) < 0)
  680. ERR("snd_pcm_hw_params_set_buffer_time_near failed: %s\n", snd_strerror(err));
  681. /* install and prepare hardware configuration */
  682. CHECK(snd_pcm_hw_params(mPcmHandle, hp.get()));
  683. /* retrieve configuration info */
  684. snd_pcm_uframes_t periodSizeInFrames{};
  685. snd_pcm_uframes_t bufferSizeInFrames{};
  686. snd_pcm_access_t access{};
  687. CHECK(snd_pcm_hw_params_get_access(hp.get(), &access));
  688. CHECK(snd_pcm_hw_params_get_period_size(hp.get(), &periodSizeInFrames, nullptr));
  689. CHECK(snd_pcm_hw_params_get_buffer_size(hp.get(), &bufferSizeInFrames));
  690. hp = nullptr;
  691. SwParamsPtr sp{CreateSwParams()};
  692. CHECK(snd_pcm_sw_params_current(mPcmHandle, sp.get()));
  693. CHECK(snd_pcm_sw_params_set_avail_min(mPcmHandle, sp.get(), periodSizeInFrames));
  694. CHECK(snd_pcm_sw_params_set_stop_threshold(mPcmHandle, sp.get(), bufferSizeInFrames));
  695. CHECK(snd_pcm_sw_params(mPcmHandle, sp.get()));
  696. #undef CHECK
  697. sp = nullptr;
  698. mDevice->BufferSize = static_cast<uint>(bufferSizeInFrames);
  699. mDevice->UpdateSize = static_cast<uint>(periodSizeInFrames);
  700. mDevice->Frequency = rate;
  701. setDefaultChannelOrder();
  702. return true;
  703. }
  704. void AlsaPlayback::start()
  705. {
  706. int err{};
  707. snd_pcm_access_t access{};
  708. HwParamsPtr hp{CreateHwParams()};
  709. #define CHECK(x) do { \
  710. if((err=(x)) < 0) \
  711. throw al::backend_exception{al::backend_error::DeviceError, #x " failed: %s", \
  712. snd_strerror(err)}; \
  713. } while(0)
  714. CHECK(snd_pcm_hw_params_current(mPcmHandle, hp.get()));
  715. /* retrieve configuration info */
  716. CHECK(snd_pcm_hw_params_get_access(hp.get(), &access));
  717. hp = nullptr;
  718. int (AlsaPlayback::*thread_func)(){};
  719. if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
  720. {
  721. mBuffer.resize(
  722. static_cast<size_t>(snd_pcm_frames_to_bytes(mPcmHandle, mDevice->UpdateSize)));
  723. thread_func = &AlsaPlayback::mixerNoMMapProc;
  724. }
  725. else
  726. {
  727. CHECK(snd_pcm_prepare(mPcmHandle));
  728. thread_func = &AlsaPlayback::mixerProc;
  729. }
  730. #undef CHECK
  731. try {
  732. mKillNow.store(false, std::memory_order_release);
  733. mThread = std::thread{std::mem_fn(thread_func), this};
  734. }
  735. catch(std::exception& e) {
  736. throw al::backend_exception{al::backend_error::DeviceError,
  737. "Failed to start mixing thread: %s", e.what()};
  738. }
  739. }
  740. void AlsaPlayback::stop()
  741. {
  742. if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable())
  743. return;
  744. mThread.join();
  745. mBuffer.clear();
  746. int err{snd_pcm_drop(mPcmHandle)};
  747. if(err < 0)
  748. ERR("snd_pcm_drop failed: %s\n", snd_strerror(err));
  749. }
  750. ClockLatency AlsaPlayback::getClockLatency()
  751. {
  752. ClockLatency ret;
  753. std::lock_guard<std::mutex> _{mMutex};
  754. ret.ClockTime = GetDeviceClockTime(mDevice);
  755. snd_pcm_sframes_t delay{};
  756. int err{snd_pcm_delay(mPcmHandle, &delay)};
  757. if(err < 0)
  758. {
  759. ERR("Failed to get pcm delay: %s\n", snd_strerror(err));
  760. delay = 0;
  761. }
  762. ret.Latency = std::chrono::seconds{std::max<snd_pcm_sframes_t>(0, delay)};
  763. ret.Latency /= mDevice->Frequency;
  764. return ret;
  765. }
  766. struct AlsaCapture final : public BackendBase {
  767. AlsaCapture(ALCdevice *device) noexcept : BackendBase{device} { }
  768. ~AlsaCapture() override;
  769. void open(const char *name) override;
  770. void start() override;
  771. void stop() override;
  772. void captureSamples(al::byte *buffer, uint samples) override;
  773. uint availableSamples() override;
  774. ClockLatency getClockLatency() override;
  775. snd_pcm_t *mPcmHandle{nullptr};
  776. al::vector<al::byte> mBuffer;
  777. bool mDoCapture{false};
  778. RingBufferPtr mRing{nullptr};
  779. snd_pcm_sframes_t mLastAvail{0};
  780. DEF_NEWDEL(AlsaCapture)
  781. };
  782. AlsaCapture::~AlsaCapture()
  783. {
  784. if(mPcmHandle)
  785. snd_pcm_close(mPcmHandle);
  786. mPcmHandle = nullptr;
  787. }
  788. void AlsaCapture::open(const char *name)
  789. {
  790. const char *driver{};
  791. if(name)
  792. {
  793. if(CaptureDevices.empty())
  794. CaptureDevices = probe_devices(SND_PCM_STREAM_CAPTURE);
  795. auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
  796. [name](const DevMap &entry) -> bool
  797. { return entry.name == name; }
  798. );
  799. if(iter == CaptureDevices.cend())
  800. throw al::backend_exception{al::backend_error::NoDevice,
  801. "Device name \"%s\" not found", name};
  802. driver = iter->device_name.c_str();
  803. }
  804. else
  805. {
  806. name = alsaDevice;
  807. driver = GetConfigValue(nullptr, "alsa", "capture", "default");
  808. }
  809. TRACE("Opening device \"%s\"\n", driver);
  810. int err{snd_pcm_open(&mPcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)};
  811. if(err < 0)
  812. throw al::backend_exception{al::backend_error::NoDevice,
  813. "Could not open ALSA device \"%s\"", driver};
  814. /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
  815. snd_config_update_free_global();
  816. snd_pcm_format_t format{SND_PCM_FORMAT_UNKNOWN};
  817. switch(mDevice->FmtType)
  818. {
  819. case DevFmtByte:
  820. format = SND_PCM_FORMAT_S8;
  821. break;
  822. case DevFmtUByte:
  823. format = SND_PCM_FORMAT_U8;
  824. break;
  825. case DevFmtShort:
  826. format = SND_PCM_FORMAT_S16;
  827. break;
  828. case DevFmtUShort:
  829. format = SND_PCM_FORMAT_U16;
  830. break;
  831. case DevFmtInt:
  832. format = SND_PCM_FORMAT_S32;
  833. break;
  834. case DevFmtUInt:
  835. format = SND_PCM_FORMAT_U32;
  836. break;
  837. case DevFmtFloat:
  838. format = SND_PCM_FORMAT_FLOAT;
  839. break;
  840. }
  841. snd_pcm_uframes_t bufferSizeInFrames{maxu(mDevice->BufferSize, 100*mDevice->Frequency/1000)};
  842. snd_pcm_uframes_t periodSizeInFrames{minu(mDevice->BufferSize, 25*mDevice->Frequency/1000)};
  843. bool needring{false};
  844. HwParamsPtr hp{CreateHwParams()};
  845. #define CHECK(x) do { \
  846. if((err=(x)) < 0) \
  847. throw al::backend_exception{al::backend_error::DeviceError, #x " failed: %s", \
  848. snd_strerror(err)}; \
  849. } while(0)
  850. CHECK(snd_pcm_hw_params_any(mPcmHandle, hp.get()));
  851. /* set interleaved access */
  852. CHECK(snd_pcm_hw_params_set_access(mPcmHandle, hp.get(), SND_PCM_ACCESS_RW_INTERLEAVED));
  853. /* set format (implicitly sets sample bits) */
  854. CHECK(snd_pcm_hw_params_set_format(mPcmHandle, hp.get(), format));
  855. /* set channels (implicitly sets frame bits) */
  856. CHECK(snd_pcm_hw_params_set_channels(mPcmHandle, hp.get(), mDevice->channelsFromFmt()));
  857. /* set rate (implicitly constrains period/buffer parameters) */
  858. CHECK(snd_pcm_hw_params_set_rate(mPcmHandle, hp.get(), mDevice->Frequency, 0));
  859. /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
  860. if(snd_pcm_hw_params_set_buffer_size_min(mPcmHandle, hp.get(), &bufferSizeInFrames) < 0)
  861. {
  862. TRACE("Buffer too large, using intermediate ring buffer\n");
  863. needring = true;
  864. CHECK(snd_pcm_hw_params_set_buffer_size_near(mPcmHandle, hp.get(), &bufferSizeInFrames));
  865. }
  866. /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
  867. CHECK(snd_pcm_hw_params_set_period_size_near(mPcmHandle, hp.get(), &periodSizeInFrames, nullptr));
  868. /* install and prepare hardware configuration */
  869. CHECK(snd_pcm_hw_params(mPcmHandle, hp.get()));
  870. /* retrieve configuration info */
  871. CHECK(snd_pcm_hw_params_get_period_size(hp.get(), &periodSizeInFrames, nullptr));
  872. #undef CHECK
  873. hp = nullptr;
  874. if(needring)
  875. mRing = RingBuffer::Create(mDevice->BufferSize, mDevice->frameSizeFromFmt(), false);
  876. mDevice->DeviceName = name;
  877. }
  878. void AlsaCapture::start()
  879. {
  880. int err{snd_pcm_prepare(mPcmHandle)};
  881. if(err < 0)
  882. throw al::backend_exception{al::backend_error::DeviceError, "snd_pcm_prepare failed: %s",
  883. snd_strerror(err)};
  884. err = snd_pcm_start(mPcmHandle);
  885. if(err < 0)
  886. throw al::backend_exception{al::backend_error::DeviceError, "snd_pcm_start failed: %s",
  887. snd_strerror(err)};
  888. mDoCapture = true;
  889. }
  890. void AlsaCapture::stop()
  891. {
  892. /* OpenAL requires access to unread audio after stopping, but ALSA's
  893. * snd_pcm_drain is unreliable and snd_pcm_drop drops it. Capture what's
  894. * available now so it'll be available later after the drop.
  895. */
  896. uint avail{availableSamples()};
  897. if(!mRing && avail > 0)
  898. {
  899. /* The ring buffer implicitly captures when checking availability.
  900. * Direct access needs to explicitly capture it into temp storage.
  901. */
  902. auto temp = al::vector<al::byte>(
  903. static_cast<size_t>(snd_pcm_frames_to_bytes(mPcmHandle, avail)));
  904. captureSamples(temp.data(), avail);
  905. mBuffer = std::move(temp);
  906. }
  907. int err{snd_pcm_drop(mPcmHandle)};
  908. if(err < 0)
  909. ERR("drop failed: %s\n", snd_strerror(err));
  910. mDoCapture = false;
  911. }
  912. void AlsaCapture::captureSamples(al::byte *buffer, uint samples)
  913. {
  914. if(mRing)
  915. {
  916. mRing->read(buffer, samples);
  917. return;
  918. }
  919. mLastAvail -= samples;
  920. while(mDevice->Connected.load(std::memory_order_acquire) && samples > 0)
  921. {
  922. snd_pcm_sframes_t amt{0};
  923. if(!mBuffer.empty())
  924. {
  925. /* First get any data stored from the last stop */
  926. amt = snd_pcm_bytes_to_frames(mPcmHandle, static_cast<ssize_t>(mBuffer.size()));
  927. if(static_cast<snd_pcm_uframes_t>(amt) > samples) amt = samples;
  928. amt = snd_pcm_frames_to_bytes(mPcmHandle, amt);
  929. std::copy_n(mBuffer.begin(), amt, buffer);
  930. mBuffer.erase(mBuffer.begin(), mBuffer.begin()+amt);
  931. amt = snd_pcm_bytes_to_frames(mPcmHandle, amt);
  932. }
  933. else if(mDoCapture)
  934. amt = snd_pcm_readi(mPcmHandle, buffer, samples);
  935. if(amt < 0)
  936. {
  937. ERR("read error: %s\n", snd_strerror(static_cast<int>(amt)));
  938. if(amt == -EAGAIN)
  939. continue;
  940. if((amt=snd_pcm_recover(mPcmHandle, static_cast<int>(amt), 1)) >= 0)
  941. {
  942. amt = snd_pcm_start(mPcmHandle);
  943. if(amt >= 0)
  944. amt = snd_pcm_avail_update(mPcmHandle);
  945. }
  946. if(amt < 0)
  947. {
  948. const char *err{snd_strerror(static_cast<int>(amt))};
  949. ERR("restore error: %s\n", err);
  950. mDevice->handleDisconnect("Capture recovery failure: %s", err);
  951. break;
  952. }
  953. /* If the amount available is less than what's asked, we lost it
  954. * during recovery. So just give silence instead. */
  955. if(static_cast<snd_pcm_uframes_t>(amt) < samples)
  956. break;
  957. continue;
  958. }
  959. buffer = buffer + amt;
  960. samples -= static_cast<uint>(amt);
  961. }
  962. if(samples > 0)
  963. std::fill_n(buffer, snd_pcm_frames_to_bytes(mPcmHandle, samples),
  964. al::byte((mDevice->FmtType == DevFmtUByte) ? 0x80 : 0));
  965. }
  966. uint AlsaCapture::availableSamples()
  967. {
  968. snd_pcm_sframes_t avail{0};
  969. if(mDevice->Connected.load(std::memory_order_acquire) && mDoCapture)
  970. avail = snd_pcm_avail_update(mPcmHandle);
  971. if(avail < 0)
  972. {
  973. ERR("avail update failed: %s\n", snd_strerror(static_cast<int>(avail)));
  974. if((avail=snd_pcm_recover(mPcmHandle, static_cast<int>(avail), 1)) >= 0)
  975. {
  976. if(mDoCapture)
  977. avail = snd_pcm_start(mPcmHandle);
  978. if(avail >= 0)
  979. avail = snd_pcm_avail_update(mPcmHandle);
  980. }
  981. if(avail < 0)
  982. {
  983. const char *err{snd_strerror(static_cast<int>(avail))};
  984. ERR("restore error: %s\n", err);
  985. mDevice->handleDisconnect("Capture recovery failure: %s", err);
  986. }
  987. }
  988. if(!mRing)
  989. {
  990. if(avail < 0) avail = 0;
  991. avail += snd_pcm_bytes_to_frames(mPcmHandle, static_cast<ssize_t>(mBuffer.size()));
  992. if(avail > mLastAvail) mLastAvail = avail;
  993. return static_cast<uint>(mLastAvail);
  994. }
  995. while(avail > 0)
  996. {
  997. auto vec = mRing->getWriteVector();
  998. if(vec.first.len == 0) break;
  999. snd_pcm_sframes_t amt{std::min(static_cast<snd_pcm_sframes_t>(vec.first.len), avail)};
  1000. amt = snd_pcm_readi(mPcmHandle, vec.first.buf, static_cast<snd_pcm_uframes_t>(amt));
  1001. if(amt < 0)
  1002. {
  1003. ERR("read error: %s\n", snd_strerror(static_cast<int>(amt)));
  1004. if(amt == -EAGAIN)
  1005. continue;
  1006. if((amt=snd_pcm_recover(mPcmHandle, static_cast<int>(amt), 1)) >= 0)
  1007. {
  1008. if(mDoCapture)
  1009. amt = snd_pcm_start(mPcmHandle);
  1010. if(amt >= 0)
  1011. amt = snd_pcm_avail_update(mPcmHandle);
  1012. }
  1013. if(amt < 0)
  1014. {
  1015. const char *err{snd_strerror(static_cast<int>(amt))};
  1016. ERR("restore error: %s\n", err);
  1017. mDevice->handleDisconnect("Capture recovery failure: %s", err);
  1018. break;
  1019. }
  1020. avail = amt;
  1021. continue;
  1022. }
  1023. mRing->writeAdvance(static_cast<snd_pcm_uframes_t>(amt));
  1024. avail -= amt;
  1025. }
  1026. return static_cast<uint>(mRing->readSpace());
  1027. }
  1028. ClockLatency AlsaCapture::getClockLatency()
  1029. {
  1030. ClockLatency ret;
  1031. ret.ClockTime = GetDeviceClockTime(mDevice);
  1032. snd_pcm_sframes_t delay{};
  1033. int err{snd_pcm_delay(mPcmHandle, &delay)};
  1034. if(err < 0)
  1035. {
  1036. ERR("Failed to get pcm delay: %s\n", snd_strerror(err));
  1037. delay = 0;
  1038. }
  1039. ret.Latency = std::chrono::seconds{std::max<snd_pcm_sframes_t>(0, delay)};
  1040. ret.Latency /= mDevice->Frequency;
  1041. return ret;
  1042. }
  1043. } // namespace
  1044. bool AlsaBackendFactory::init()
  1045. {
  1046. bool error{false};
  1047. #ifdef HAVE_DYNLOAD
  1048. if(!alsa_handle)
  1049. {
  1050. std::string missing_funcs;
  1051. alsa_handle = LoadLib("libasound.so.2");
  1052. if(!alsa_handle)
  1053. {
  1054. WARN("Failed to load %s\n", "libasound.so.2");
  1055. return false;
  1056. }
  1057. error = false;
  1058. #define LOAD_FUNC(f) do { \
  1059. p##f = reinterpret_cast<decltype(p##f)>(GetSymbol(alsa_handle, #f)); \
  1060. if(p##f == nullptr) { \
  1061. error = true; \
  1062. missing_funcs += "\n" #f; \
  1063. } \
  1064. } while(0)
  1065. ALSA_FUNCS(LOAD_FUNC);
  1066. #undef LOAD_FUNC
  1067. if(error)
  1068. {
  1069. WARN("Missing expected functions:%s\n", missing_funcs.c_str());
  1070. CloseLib(alsa_handle);
  1071. alsa_handle = nullptr;
  1072. }
  1073. }
  1074. #endif
  1075. return !error;
  1076. }
  1077. bool AlsaBackendFactory::querySupport(BackendType type)
  1078. { return (type == BackendType::Playback || type == BackendType::Capture); }
  1079. std::string AlsaBackendFactory::probe(BackendType type)
  1080. {
  1081. std::string outnames;
  1082. auto add_device = [&outnames](const DevMap &entry) -> void
  1083. {
  1084. /* +1 to also append the null char (to ensure a null-separated list and
  1085. * double-null terminated list).
  1086. */
  1087. outnames.append(entry.name.c_str(), entry.name.length()+1);
  1088. };
  1089. switch(type)
  1090. {
  1091. case BackendType::Playback:
  1092. PlaybackDevices = probe_devices(SND_PCM_STREAM_PLAYBACK);
  1093. std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
  1094. break;
  1095. case BackendType::Capture:
  1096. CaptureDevices = probe_devices(SND_PCM_STREAM_CAPTURE);
  1097. std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
  1098. break;
  1099. }
  1100. return outnames;
  1101. }
  1102. BackendPtr AlsaBackendFactory::createBackend(ALCdevice *device, BackendType type)
  1103. {
  1104. if(type == BackendType::Playback)
  1105. return BackendPtr{new AlsaPlayback{device}};
  1106. if(type == BackendType::Capture)
  1107. return BackendPtr{new AlsaCapture{device}};
  1108. return nullptr;
  1109. }
  1110. BackendFactory &AlsaBackendFactory::getFactory()
  1111. {
  1112. static AlsaBackendFactory factory{};
  1113. return factory;
  1114. }