alsa.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #include <errno.h>
  2. #include <limits.h>
  3. #include <stdarg.h>
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <asoundlib.h>
  10. #include "au.h"
  11. #include "adev.h"
  12. #include "common.h"
  13. enum {
  14. A_NULL,
  15. A_ENC,
  16. A_RATE,
  17. A_CHAN
  18. };
  19. struct adev {
  20. snd_pcm_t *snd;
  21. snd_pcm_hw_params_t *param;
  22. size_t ssize;
  23. uint32_t enc;
  24. unsigned chan;
  25. int mode;
  26. };
  27. const struct a_lookup stab[] = {
  28. { "enc", A_ENC },
  29. { "encoding", A_ENC },
  30. { "rate", A_RATE },
  31. { "chan", A_CHAN },
  32. { "channel", A_CHAN },
  33. { "channels", A_CHAN },
  34. { NULL, A_NULL }
  35. };
  36. static snd_pcm_format_t auenc2sndpcmfmt(uint32_t);
  37. static uint32_t sndpcmfmt2auenc(snd_pcm_format_t);
  38. struct adev *
  39. ad_open(const char *dev, int mode)
  40. {
  41. struct adev *a;
  42. snd_pcm_format_t fmt = SND_PCM_FORMAT_UNKNOWN;
  43. unsigned int rate = 48000;
  44. int e;
  45. if (dev == NULL)
  46. dev = "default";
  47. if ((a = malloc(sizeof(struct adev))) == NULL)
  48. return (NULL);
  49. a->enc = AU_PCM16;
  50. a->chan = 2;
  51. a->mode = mode == A_READ;
  52. if ((e = snd_pcm_open(&a->snd, dev, a->mode ?
  53. SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
  54. free(a);
  55. errno = -e;
  56. return (NULL);
  57. }
  58. if ((e = snd_pcm_hw_params_malloc(&a->param)) < 0) {
  59. snd_pcm_close(a->snd);
  60. free(a);
  61. errno = -e;
  62. return (NULL);
  63. }
  64. if ((e = snd_pcm_hw_params_any(a->snd, a->param)) < 0)
  65. goto err;
  66. if ((e = snd_pcm_hw_params_set_access(a->snd, a->param,
  67. SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
  68. goto err;
  69. if ((e = snd_pcm_hw_params_set_format(a->snd, a->param,
  70. auenc2sndpcmfmt(a->enc))) < 0)
  71. goto err;
  72. if ((e = snd_pcm_hw_params_set_channels_near(a->snd, a->param,
  73. &a->chan)) < 0)
  74. goto err;
  75. if ((e = snd_pcm_hw_params_set_rate_near(a->snd, a->param,
  76. &rate, 0)) < 0)
  77. goto err;
  78. a->ssize = au_encsize(a->enc) * (size_t)a->chan;
  79. return (a);
  80. err:
  81. ad_close(a);
  82. errno = -e;
  83. return (NULL);
  84. }
  85. struct adev *
  86. ad_fpopen(FILE *fp, int mode)
  87. {
  88. ERR(EOPNOTSUPP, NULL);
  89. }
  90. void
  91. ad_close(struct adev *a)
  92. {
  93. if (a == NULL)
  94. return;
  95. (void)snd_pcm_drain(a->snd);
  96. snd_pcm_hw_params_free(a->param);
  97. snd_pcm_close(a->snd);
  98. free(a);
  99. }
  100. int
  101. ad_limit(struct adev *a)
  102. {
  103. ERR(ENOSYS, -1);
  104. }
  105. int
  106. ad_get(struct adev *a, const char *s, ...)
  107. {
  108. va_list ap;
  109. ssize_t r;
  110. unsigned u;
  111. int n;
  112. int v;
  113. int i;
  114. if (a == NULL || s == NULL)
  115. ERR(EINVAL, -1);
  116. va_start(ap, s);
  117. for (n = 0; (r = a_lookup(stab, s, &v)) > 0; n++, s += r)
  118. switch (v) {
  119. case A_ENC:
  120. *va_arg(ap, uint32_t *) = a->enc;
  121. break;
  122. case A_RATE:
  123. if (snd_pcm_hw_params_get_rate(a->param, &u, &i)
  124. < 0)
  125. goto err;
  126. if (u > UINT32_MAX)
  127. errno = EINVAL;
  128. *va_arg(ap, uint32_t *) = u;
  129. break;
  130. case A_CHAN:
  131. *va_arg(ap, uint32_t *) = a->chan;
  132. break;
  133. default:
  134. goto err;
  135. }
  136. if (r == 0) {
  137. va_end(ap);
  138. return (n);
  139. }
  140. err:
  141. va_end(ap);
  142. ERR(EINVAL, n);
  143. }
  144. int
  145. ad_set(struct adev *a, const char *s, ...)
  146. {
  147. va_list ap;
  148. ssize_t r;
  149. uint32_t u32;
  150. int n;
  151. int v;
  152. if (a == NULL || s == NULL)
  153. ERR(EINVAL, -1);
  154. va_start(ap, s);
  155. for (n = 0; (r = a_lookup(stab, s, &v)) > 0; n++, s += r)
  156. switch (v) {
  157. case A_ENC:
  158. if ((u32 = va_arg(ap, uint32_t)) > UINT_MAX)
  159. goto err;
  160. if (snd_pcm_hw_params_set_format(a->snd,
  161. a->param, auenc2sndpcmfmt(u32)) < 0)
  162. goto err;
  163. (void)snd_pcm_drain(a->snd);
  164. if (snd_pcm_hw_params(a->snd, a->param) < 0)
  165. goto err;
  166. a->enc = u32;
  167. break;
  168. case A_RATE:
  169. if ((u32 = va_arg(ap, uint32_t)) > UINT_MAX)
  170. goto err;
  171. if (snd_pcm_hw_params_set_rate(a->snd, a->param,
  172. u32, 0) < 0)
  173. goto err;
  174. (void)snd_pcm_drain(a->snd);
  175. if (snd_pcm_hw_params(a->snd, a->param) < 0)
  176. goto err;
  177. break;
  178. case A_CHAN:
  179. if ((u32 = va_arg(ap, uint32_t)) > UINT_MAX)
  180. goto err;
  181. if (snd_pcm_hw_params_set_channels(a->snd,
  182. a->param, u32) < 0)
  183. goto err;
  184. (void)snd_pcm_drain(a->snd);
  185. if (snd_pcm_hw_params(a->snd, a->param) < 0)
  186. goto err;
  187. a->chan = u32;
  188. break;
  189. default:
  190. goto err;
  191. }
  192. if (r == 0) {
  193. va_end(ap);
  194. return (n);
  195. }
  196. err:
  197. va_end(ap);
  198. ERR(EINVAL, n);
  199. }
  200. ssize_t
  201. ad_read(struct adev *a, void *b, size_t s)
  202. {
  203. ssize_t r;
  204. if (a == NULL || b == NULL || !a->mode)
  205. ERR(EINVAL, -1);
  206. s /= a->ssize;
  207. if (s == 0)
  208. return (0);
  209. r = snd_pcm_readi(a->snd, b, s);
  210. return (r > 0 ? r * a->ssize : r);
  211. }
  212. ssize_t
  213. ad_write(struct adev *a, const void *b, size_t s)
  214. {
  215. ssize_t r;
  216. if (a == NULL || b == NULL || a->mode)
  217. ERR(EINVAL, -1);
  218. s /= a->ssize;
  219. if (s == 0)
  220. return (0);
  221. r = snd_pcm_writei(a->snd, b, s);
  222. return (r > 0 ? r * a->ssize : r);
  223. }
  224. snd_pcm_format_t
  225. auenc2sndpcmfmt(uint32_t enc)
  226. {
  227. switch (enc) {
  228. case AU_ULAW:
  229. return (SND_PCM_FORMAT_MU_LAW);
  230. case AU_PCM8:
  231. return (SND_PCM_FORMAT_S8);
  232. case AU_PCM16:
  233. return (SND_PCM_FORMAT_S16_BE);
  234. case AU_PCM24:
  235. return (SND_PCM_FORMAT_S24_3BE);
  236. case AU_PCM32:
  237. return (SND_PCM_FORMAT_S32_BE);
  238. case AU_FLOAT32:
  239. return (SND_PCM_FORMAT_FLOAT_BE);
  240. case AU_FLOAT64:
  241. return (SND_PCM_FORMAT_FLOAT64_BE);
  242. case AU_ALAW:
  243. return (SND_PCM_FORMAT_A_LAW);
  244. default:
  245. return (SND_PCM_FORMAT_S16_BE);
  246. }
  247. }
  248. uint32_t
  249. sndpcmfmt2auenc(snd_pcm_format_t fmt)
  250. {
  251. switch (fmt) {
  252. case SND_PCM_FORMAT_S8:
  253. return (AU_PCM8);
  254. case SND_PCM_FORMAT_U8:
  255. return (AU_PCM8);
  256. case SND_PCM_FORMAT_S16_LE:
  257. return (AU_PCM16);
  258. case SND_PCM_FORMAT_U16_LE:
  259. return (AU_PCM16);
  260. case SND_PCM_FORMAT_S16_BE:
  261. return (AU_PCM16);
  262. case SND_PCM_FORMAT_U16_BE:
  263. return (AU_PCM16);
  264. case SND_PCM_FORMAT_S24_LE:
  265. return (AU_PCM24);
  266. case SND_PCM_FORMAT_U24_LE:
  267. return (AU_PCM24);
  268. case SND_PCM_FORMAT_S24_BE:
  269. return (AU_PCM24);
  270. case SND_PCM_FORMAT_U24_BE:
  271. return (AU_PCM24);
  272. case SND_PCM_FORMAT_S32_LE:
  273. return (AU_PCM32);
  274. case SND_PCM_FORMAT_U32_LE:
  275. return (AU_PCM32);
  276. case SND_PCM_FORMAT_S32_BE:
  277. return (AU_PCM32);
  278. case SND_PCM_FORMAT_U32_BE:
  279. return (AU_PCM32);
  280. case SND_PCM_FORMAT_FLOAT_LE:
  281. return (AU_FLOAT32);
  282. case SND_PCM_FORMAT_FLOAT64_LE:
  283. return (AU_FLOAT64);
  284. case SND_PCM_FORMAT_FLOAT_BE:
  285. return (AU_FLOAT32);
  286. case SND_PCM_FORMAT_FLOAT64_BE:
  287. return (AU_FLOAT64);
  288. case SND_PCM_FORMAT_MU_LAW:
  289. return (AU_ULAW);
  290. case SND_PCM_FORMAT_A_LAW:
  291. return (AU_ALAW);
  292. case SND_PCM_FORMAT_IMA_ADPCM:
  293. return (AU_PCM16);
  294. case SND_PCM_FORMAT_S24_3LE:
  295. return (AU_PCM24);
  296. case SND_PCM_FORMAT_U24_3LE:
  297. return (AU_PCM24);
  298. case SND_PCM_FORMAT_S24_3BE:
  299. return (AU_PCM24);
  300. case SND_PCM_FORMAT_U24_3BE:
  301. return (AU_PCM24);
  302. case SND_PCM_FORMAT_S20_3LE:
  303. return (AU_PCM24);
  304. case SND_PCM_FORMAT_U20_3LE:
  305. return (AU_PCM24);
  306. case SND_PCM_FORMAT_S20_3BE:
  307. return (AU_PCM24);
  308. case SND_PCM_FORMAT_U20_3BE:
  309. return (AU_PCM24);
  310. case SND_PCM_FORMAT_S18_3LE:
  311. return (AU_PCM24);
  312. case SND_PCM_FORMAT_U18_3LE:
  313. return (AU_PCM24);
  314. case SND_PCM_FORMAT_S18_3BE:
  315. return (AU_PCM24);
  316. case SND_PCM_FORMAT_U18_3BE:
  317. return (AU_PCM24);
  318. case SND_PCM_FORMAT_G723_24:
  319. return (AU_PCM16);
  320. case SND_PCM_FORMAT_G723_24_1B:
  321. return (AU_PCM16);
  322. case SND_PCM_FORMAT_G723_40:
  323. return (AU_PCM16);
  324. case SND_PCM_FORMAT_G723_40_1B:
  325. return (AU_PCM16);
  326. case SND_PCM_FORMAT_DSD_U8:
  327. return (AU_PCM8);
  328. case SND_PCM_FORMAT_DSD_U16_LE:
  329. return (AU_PCM16);
  330. case SND_PCM_FORMAT_DSD_U32_LE:
  331. return (AU_PCM32);
  332. case SND_PCM_FORMAT_DSD_U16_BE:
  333. return (AU_PCM16);
  334. case SND_PCM_FORMAT_DSD_U32_BE:
  335. return (AU_PCM32);
  336. default:
  337. return (AU_PCM16);
  338. }
  339. }