]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
Merge commit 'origin/master-tx'
[pulseaudio] / src / modules / alsa / alsa-util.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <sys/types.h>
28 #include <limits.h>
29 #include <asoundlib.h>
30
31 #include <pulse/sample.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/i18n.h>
36 #include <pulse/utf8.h>
37
38 #include <pulsecore/log.h>
39 #include <pulsecore/macro.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/atomic.h>
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/once.h>
44 #include <pulsecore/thread.h>
45
46 #include "alsa-util.h"
47
48 #ifdef HAVE_HAL
49 #include "hal-util.h"
50 #endif
51
52 #ifdef HAVE_UDEV
53 #include "udev-util.h"
54 #endif
55
56 struct pa_alsa_fdlist {
57 unsigned num_fds;
58 struct pollfd *fds;
59 /* This is a temporary buffer used to avoid lots of mallocs */
60 struct pollfd *work_fds;
61
62 snd_mixer_t *mixer;
63
64 pa_mainloop_api *m;
65 pa_defer_event *defer;
66 pa_io_event **ios;
67
68 pa_bool_t polled;
69
70 void (*cb)(void *userdata);
71 void *userdata;
72 };
73
74 static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
75
76 struct pa_alsa_fdlist *fdl = userdata;
77 int err;
78 unsigned i;
79 unsigned short revents;
80
81 pa_assert(a);
82 pa_assert(fdl);
83 pa_assert(fdl->mixer);
84 pa_assert(fdl->fds);
85 pa_assert(fdl->work_fds);
86
87 if (fdl->polled)
88 return;
89
90 fdl->polled = TRUE;
91
92 memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
93
94 for (i = 0; i < fdl->num_fds; i++) {
95 if (e == fdl->ios[i]) {
96 if (events & PA_IO_EVENT_INPUT)
97 fdl->work_fds[i].revents |= POLLIN;
98 if (events & PA_IO_EVENT_OUTPUT)
99 fdl->work_fds[i].revents |= POLLOUT;
100 if (events & PA_IO_EVENT_ERROR)
101 fdl->work_fds[i].revents |= POLLERR;
102 if (events & PA_IO_EVENT_HANGUP)
103 fdl->work_fds[i].revents |= POLLHUP;
104 break;
105 }
106 }
107
108 pa_assert(i != fdl->num_fds);
109
110 if ((err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents)) < 0) {
111 pa_log_error("Unable to get poll revent: %s", pa_alsa_strerror(err));
112 return;
113 }
114
115 a->defer_enable(fdl->defer, 1);
116
117 if (revents)
118 snd_mixer_handle_events(fdl->mixer);
119 }
120
121 static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) {
122 struct pa_alsa_fdlist *fdl = userdata;
123 unsigned num_fds, i;
124 int err, n;
125 struct pollfd *temp;
126
127 pa_assert(a);
128 pa_assert(fdl);
129 pa_assert(fdl->mixer);
130
131 a->defer_enable(fdl->defer, 0);
132
133 if ((n = snd_mixer_poll_descriptors_count(fdl->mixer)) < 0) {
134 pa_log("snd_mixer_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
135 return;
136 }
137 num_fds = (unsigned) n;
138
139 if (num_fds != fdl->num_fds) {
140 if (fdl->fds)
141 pa_xfree(fdl->fds);
142 if (fdl->work_fds)
143 pa_xfree(fdl->work_fds);
144 fdl->fds = pa_xnew0(struct pollfd, num_fds);
145 fdl->work_fds = pa_xnew(struct pollfd, num_fds);
146 }
147
148 memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds);
149
150 if ((err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds)) < 0) {
151 pa_log_error("Unable to get poll descriptors: %s", pa_alsa_strerror(err));
152 return;
153 }
154
155 fdl->polled = FALSE;
156
157 if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0)
158 return;
159
160 if (fdl->ios) {
161 for (i = 0; i < fdl->num_fds; i++)
162 a->io_free(fdl->ios[i]);
163
164 if (num_fds != fdl->num_fds) {
165 pa_xfree(fdl->ios);
166 fdl->ios = NULL;
167 }
168 }
169
170 if (!fdl->ios)
171 fdl->ios = pa_xnew(pa_io_event*, num_fds);
172
173 /* Swap pointers */
174 temp = fdl->work_fds;
175 fdl->work_fds = fdl->fds;
176 fdl->fds = temp;
177
178 fdl->num_fds = num_fds;
179
180 for (i = 0;i < num_fds;i++)
181 fdl->ios[i] = a->io_new(a, fdl->fds[i].fd,
182 ((fdl->fds[i].events & POLLIN) ? PA_IO_EVENT_INPUT : 0) |
183 ((fdl->fds[i].events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0),
184 io_cb, fdl);
185 }
186
187 struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) {
188 struct pa_alsa_fdlist *fdl;
189
190 fdl = pa_xnew0(struct pa_alsa_fdlist, 1);
191
192 fdl->num_fds = 0;
193 fdl->fds = NULL;
194 fdl->work_fds = NULL;
195 fdl->mixer = NULL;
196 fdl->m = NULL;
197 fdl->defer = NULL;
198 fdl->ios = NULL;
199 fdl->polled = FALSE;
200
201 return fdl;
202 }
203
204 void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) {
205 pa_assert(fdl);
206
207 if (fdl->defer) {
208 pa_assert(fdl->m);
209 fdl->m->defer_free(fdl->defer);
210 }
211
212 if (fdl->ios) {
213 unsigned i;
214 pa_assert(fdl->m);
215 for (i = 0; i < fdl->num_fds; i++)
216 fdl->m->io_free(fdl->ios[i]);
217 pa_xfree(fdl->ios);
218 }
219
220 if (fdl->fds)
221 pa_xfree(fdl->fds);
222 if (fdl->work_fds)
223 pa_xfree(fdl->work_fds);
224
225 pa_xfree(fdl);
226 }
227
228 int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) {
229 pa_assert(fdl);
230 pa_assert(mixer_handle);
231 pa_assert(m);
232 pa_assert(!fdl->m);
233
234 fdl->mixer = mixer_handle;
235 fdl->m = m;
236 fdl->defer = m->defer_new(m, defer_cb, fdl);
237
238 return 0;
239 }
240
241 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
242
243 static const snd_pcm_format_t format_trans[] = {
244 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
245 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
246 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
247 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
248 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
249 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
250 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
251 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
252 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
253 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
254 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
255 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
256 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
257 };
258
259 static const pa_sample_format_t try_order[] = {
260 PA_SAMPLE_FLOAT32NE,
261 PA_SAMPLE_FLOAT32RE,
262 PA_SAMPLE_S32NE,
263 PA_SAMPLE_S32RE,
264 PA_SAMPLE_S24_32NE,
265 PA_SAMPLE_S24_32RE,
266 PA_SAMPLE_S24NE,
267 PA_SAMPLE_S24RE,
268 PA_SAMPLE_S16NE,
269 PA_SAMPLE_S16RE,
270 PA_SAMPLE_ALAW,
271 PA_SAMPLE_ULAW,
272 PA_SAMPLE_U8,
273 PA_SAMPLE_INVALID
274 };
275
276 int i, ret;
277
278 pa_assert(pcm_handle);
279 pa_assert(f);
280
281 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
282 return ret;
283
284 if (*f == PA_SAMPLE_FLOAT32BE)
285 *f = PA_SAMPLE_FLOAT32LE;
286 else if (*f == PA_SAMPLE_FLOAT32LE)
287 *f = PA_SAMPLE_FLOAT32BE;
288 else if (*f == PA_SAMPLE_S24BE)
289 *f = PA_SAMPLE_S24LE;
290 else if (*f == PA_SAMPLE_S24LE)
291 *f = PA_SAMPLE_S24BE;
292 else if (*f == PA_SAMPLE_S24_32BE)
293 *f = PA_SAMPLE_S24_32LE;
294 else if (*f == PA_SAMPLE_S24_32LE)
295 *f = PA_SAMPLE_S24_32BE;
296 else if (*f == PA_SAMPLE_S16BE)
297 *f = PA_SAMPLE_S16LE;
298 else if (*f == PA_SAMPLE_S16LE)
299 *f = PA_SAMPLE_S16BE;
300 else if (*f == PA_SAMPLE_S32BE)
301 *f = PA_SAMPLE_S32LE;
302 else if (*f == PA_SAMPLE_S32LE)
303 *f = PA_SAMPLE_S32BE;
304 else
305 goto try_auto;
306
307 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
308 return ret;
309
310 try_auto:
311
312 for (i = 0; try_order[i] != PA_SAMPLE_INVALID; i++) {
313 *f = try_order[i];
314
315 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
316 return ret;
317 }
318
319 return -1;
320 }
321
322 /* Set the hardware parameters of the given ALSA device. Returns the
323 * selected fragment settings in *period and *period_size */
324 int pa_alsa_set_hw_params(
325 snd_pcm_t *pcm_handle,
326 pa_sample_spec *ss,
327 uint32_t *periods,
328 snd_pcm_uframes_t *period_size,
329 snd_pcm_uframes_t tsched_size,
330 pa_bool_t *use_mmap,
331 pa_bool_t *use_tsched,
332 pa_bool_t require_exact_channel_number) {
333
334 int ret = -1;
335 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
336 unsigned int _periods = periods ? *periods : 0;
337 snd_pcm_uframes_t buffer_size;
338 unsigned int r = ss->rate;
339 unsigned int c = ss->channels;
340 pa_sample_format_t f = ss->format;
341 snd_pcm_hw_params_t *hwparams;
342 pa_bool_t _use_mmap = use_mmap && *use_mmap;
343 pa_bool_t _use_tsched = use_tsched && *use_tsched;
344 int dir;
345
346 pa_assert(pcm_handle);
347 pa_assert(ss);
348
349 snd_pcm_hw_params_alloca(&hwparams);
350
351 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
352 goto finish;
353
354 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0)
355 goto finish;
356
357 if (_use_mmap) {
358
359 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
360
361 /* mmap() didn't work, fall back to interleaved */
362
363 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
364 goto finish;
365
366 _use_mmap = FALSE;
367 }
368
369 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
370 goto finish;
371
372 if (!_use_mmap)
373 _use_tsched = FALSE;
374
375 if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
376 goto finish;
377
378 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0)
379 goto finish;
380
381 if (require_exact_channel_number) {
382 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0)
383 goto finish;
384 } else {
385 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0)
386 goto finish;
387 }
388
389 if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0)
390 goto finish;
391
392 if (_period_size && tsched_size && _periods) {
393 /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
394 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
395 tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
396
397 if (_use_tsched) {
398 _period_size = tsched_size;
399 _periods = 1;
400
401 pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size) == 0);
402 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
403 }
404
405 buffer_size = _periods * _period_size;
406
407 if (_periods > 0) {
408
409 /* First we pass 0 as direction to get exactly what we asked
410 * for. That this is necessary is presumably a bug in ALSA */
411
412 dir = 0;
413 if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
414 dir = 1;
415 if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
416 dir = -1;
417 if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
418 goto finish;
419 }
420 }
421 }
422
423 if (_period_size > 0)
424 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
425 goto finish;
426 }
427
428 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
429 goto finish;
430
431 if (ss->rate != r)
432 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
433
434 if (ss->channels != c)
435 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
436
437 if (ss->format != f)
438 pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
439
440 if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
441 goto finish;
442
443 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
444 (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0)
445 goto finish;
446
447 /* If the sample rate deviates too much, we need to resample */
448 if (r < ss->rate*.95 || r > ss->rate*1.05)
449 ss->rate = r;
450 ss->channels = (uint8_t) c;
451 ss->format = f;
452
453 pa_assert(_periods > 0);
454 pa_assert(_period_size > 0);
455
456 if (periods)
457 *periods = _periods;
458
459 if (period_size)
460 *period_size = _period_size;
461
462 if (use_mmap)
463 *use_mmap = _use_mmap;
464
465 if (use_tsched)
466 *use_tsched = _use_tsched;
467
468 ret = 0;
469
470 snd_pcm_nonblock(pcm_handle, 1);
471
472 finish:
473
474 return ret;
475 }
476
477 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
478 snd_pcm_sw_params_t *swparams;
479 snd_pcm_uframes_t boundary;
480 int err;
481
482 pa_assert(pcm);
483
484 snd_pcm_sw_params_alloca(&swparams);
485
486 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
487 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
488 return err;
489 }
490
491 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, 0)) < 0) {
492 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
493 return err;
494 }
495
496 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
497 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
498 return err;
499 }
500
501 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
502 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
503 return err;
504 }
505
506 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
507 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
508 return err;
509 }
510
511 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
512 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
513 return err;
514 }
515
516 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
517 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
518 return err;
519 }
520
521 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
522 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
523 return err;
524 }
525
526 return 0;
527 }
528
529 static const struct pa_alsa_profile_info device_table[] = {
530 {{ 1, { PA_CHANNEL_POSITION_MONO }},
531 "hw",
532 N_("Analog Mono"),
533 "analog-mono",
534 1,
535 "Master", "PCM",
536 "Capture", "Mic" },
537
538 {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
539 "front",
540 N_("Analog Stereo"),
541 "analog-stereo",
542 10,
543 "Master", "PCM",
544 "Capture", "Mic" },
545
546 {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
547 "iec958",
548 N_("Digital Stereo (IEC958)"),
549 "iec958-stereo",
550 5,
551 "IEC958", NULL,
552 "IEC958 In", NULL },
553
554 {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
555 "hdmi",
556 N_("Digital Stereo (HDMI)"),
557 "hdmi-stereo",
558 4,
559 "IEC958", NULL,
560 "IEC958 In", NULL },
561
562 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
563 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
564 "surround40",
565 N_("Analog Surround 4.0"),
566 "analog-surround-40",
567 7,
568 "Master", "PCM",
569 "Capture", "Mic" },
570
571 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
572 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
573 "a52",
574 N_("Digital Surround 4.0 (IEC958/AC3)"),
575 "iec958-ac3-surround-40",
576 2,
577 "Master", "PCM",
578 "Capture", "Mic" },
579
580 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
581 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
582 PA_CHANNEL_POSITION_LFE }},
583 "surround41",
584 N_("Analog Surround 4.1"),
585 "analog-surround-41",
586 7,
587 "Master", "PCM",
588 "Capture", "Mic" },
589
590 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
591 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
592 PA_CHANNEL_POSITION_CENTER }},
593 "surround50",
594 N_("Analog Surround 5.0"),
595 "analog-surround-50",
596 7,
597 "Master", "PCM",
598 "Capture", "Mic" },
599
600 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
601 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
602 PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }},
603 "surround51",
604 N_("Analog Surround 5.1"),
605 "analog-surround-51",
606 8,
607 "Master", "PCM",
608 "Capture", "Mic" },
609
610 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
611 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
612 PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE}},
613 "a52",
614 N_("Digital Surround 5.1 (IEC958/AC3)"),
615 "iec958-ac3-surround-51",
616 3,
617 "IEC958", NULL,
618 "IEC958 In", NULL },
619
620 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
621 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
622 PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
623 PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }},
624 "surround71",
625 N_("Analog Surround 7.1"),
626 "analog-surround-71",
627 7,
628 "Master", "PCM",
629 "Capture", "Mic" },
630
631 {{ 0, { 0 }}, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
632 };
633
634 snd_pcm_t *pa_alsa_open_by_device_id_auto(
635 const char *dev_id,
636 char **dev,
637 pa_sample_spec *ss,
638 pa_channel_map* map,
639 int mode,
640 uint32_t *nfrags,
641 snd_pcm_uframes_t *period_size,
642 snd_pcm_uframes_t tsched_size,
643 pa_bool_t *use_mmap,
644 pa_bool_t *use_tsched,
645 const pa_alsa_profile_info **profile) {
646
647 int i;
648 int direction = 1;
649 char *d;
650 snd_pcm_t *pcm_handle;
651
652 pa_assert(dev_id);
653 pa_assert(dev);
654 pa_assert(ss);
655 pa_assert(map);
656 pa_assert(nfrags);
657 pa_assert(period_size);
658
659 /* First we try to find a device string with a superset of the
660 * requested channel map and open it without the plug: prefix. We
661 * iterate through our device table from top to bottom and take
662 * the first that matches. If we didn't find a working device that
663 * way, we iterate backwards, and check all devices that do not
664 * provide a superset of the requested channel map.*/
665
666 i = 0;
667 for (;;) {
668
669 if ((direction > 0) == pa_channel_map_superset(&device_table[i].map, map)) {
670 pa_sample_spec try_ss;
671
672 pa_log_debug("Checking for %s (%s)", device_table[i].name, device_table[i].alsa_name);
673
674 d = pa_sprintf_malloc("%s:%s", device_table[i].alsa_name, dev_id);
675
676 try_ss.channels = device_table[i].map.channels;
677 try_ss.rate = ss->rate;
678 try_ss.format = ss->format;
679
680 pcm_handle = pa_alsa_open_by_device_string(
681 d,
682 dev,
683 &try_ss,
684 map,
685 mode,
686 nfrags,
687 period_size,
688 tsched_size,
689 use_mmap,
690 use_tsched,
691 TRUE);
692
693 pa_xfree(d);
694
695 if (pcm_handle) {
696
697 *ss = try_ss;
698 *map = device_table[i].map;
699 pa_assert(map->channels == ss->channels);
700
701 if (profile)
702 *profile = &device_table[i];
703
704 return pcm_handle;
705 }
706 }
707
708 if (direction > 0) {
709 if (!device_table[i+1].alsa_name) {
710 /* OK, so we are at the end of our list. Let's turn
711 * back. */
712 direction = -1;
713 } else {
714 /* We are not at the end of the list, so let's simply
715 * try the next entry */
716 i++;
717 }
718 }
719
720 if (direction < 0) {
721
722 if (device_table[i+1].alsa_name &&
723 device_table[i].map.channels == device_table[i+1].map.channels) {
724
725 /* OK, the next entry has the same number of channels,
726 * let's try it */
727 i++;
728
729 } else {
730 /* Hmm, so the next entry does not have the same
731 * number of channels, so let's go backwards until we
732 * find the next entry with a different number of
733 * channels */
734
735 for (i--; i >= 0; i--)
736 if (device_table[i].map.channels != device_table[i+1].map.channels)
737 break;
738
739 /* Hmm, there is no entry with a different number of
740 * entries, then we're done */
741 if (i < 0)
742 break;
743
744 /* OK, now lets find go back as long as we have the same number of channels */
745 for (; i > 0; i--)
746 if (device_table[i].map.channels != device_table[i-1].map.channels)
747 break;
748 }
749 }
750 }
751
752 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
753
754 d = pa_sprintf_malloc("hw:%s", dev_id);
755 pa_log_debug("Trying %s as last resort...", d);
756 pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
757 pa_xfree(d);
758
759 if (pcm_handle && profile)
760 *profile = NULL;
761
762 return pcm_handle;
763 }
764
765 snd_pcm_t *pa_alsa_open_by_device_id_profile(
766 const char *dev_id,
767 char **dev,
768 pa_sample_spec *ss,
769 pa_channel_map* map,
770 int mode,
771 uint32_t *nfrags,
772 snd_pcm_uframes_t *period_size,
773 snd_pcm_uframes_t tsched_size,
774 pa_bool_t *use_mmap,
775 pa_bool_t *use_tsched,
776 const pa_alsa_profile_info *profile) {
777
778 char *d;
779 snd_pcm_t *pcm_handle;
780 pa_sample_spec try_ss;
781
782 pa_assert(dev_id);
783 pa_assert(dev);
784 pa_assert(ss);
785 pa_assert(map);
786 pa_assert(nfrags);
787 pa_assert(period_size);
788 pa_assert(profile);
789
790 d = pa_sprintf_malloc("%s:%s", profile->alsa_name, dev_id);
791
792 try_ss.channels = profile->map.channels;
793 try_ss.rate = ss->rate;
794 try_ss.format = ss->format;
795
796 pcm_handle = pa_alsa_open_by_device_string(
797 d,
798 dev,
799 &try_ss,
800 map,
801 mode,
802 nfrags,
803 period_size,
804 tsched_size,
805 use_mmap,
806 use_tsched,
807 TRUE);
808
809 pa_xfree(d);
810
811 if (!pcm_handle)
812 return NULL;
813
814 *ss = try_ss;
815 *map = profile->map;
816 pa_assert(map->channels == ss->channels);
817
818 return pcm_handle;
819 }
820
821 snd_pcm_t *pa_alsa_open_by_device_string(
822 const char *device,
823 char **dev,
824 pa_sample_spec *ss,
825 pa_channel_map* map,
826 int mode,
827 uint32_t *nfrags,
828 snd_pcm_uframes_t *period_size,
829 snd_pcm_uframes_t tsched_size,
830 pa_bool_t *use_mmap,
831 pa_bool_t *use_tsched,
832 pa_bool_t require_exact_channel_number) {
833
834 int err;
835 char *d;
836 snd_pcm_t *pcm_handle;
837 pa_bool_t reformat = FALSE;
838
839 pa_assert(device);
840 pa_assert(ss);
841 pa_assert(map);
842
843 d = pa_xstrdup(device);
844
845 for (;;) {
846 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
847
848 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
849 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
850 * we enable nonblock mode afterwards via
851 * snd_pcm_nonblock(). Also see
852 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
853
854 if ((err = snd_pcm_open(&pcm_handle, d, mode,
855 /*SND_PCM_NONBLOCK|*/
856 SND_PCM_NO_AUTO_RESAMPLE|
857 SND_PCM_NO_AUTO_CHANNELS|
858 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
859 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
860 goto fail;
861 }
862
863 if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
864
865 if (!reformat) {
866 reformat = TRUE;
867
868 snd_pcm_close(pcm_handle);
869 continue;
870 }
871
872 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
873
874 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
875 char *t;
876
877 t = pa_sprintf_malloc("plug:%s", d);
878 pa_xfree(d);
879 d = t;
880
881 reformat = FALSE;
882
883 snd_pcm_close(pcm_handle);
884 continue;
885 }
886
887 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
888 snd_pcm_close(pcm_handle);
889
890 goto fail;
891 }
892
893 if (dev)
894 *dev = d;
895 else
896 pa_xfree(d);
897
898 if (ss->channels != map->channels)
899 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
900
901 return pcm_handle;
902 }
903
904 fail:
905 pa_xfree(d);
906
907 return NULL;
908 }
909
910 int pa_alsa_probe_profiles(
911 const char *dev_id,
912 const pa_sample_spec *ss,
913 void (*cb)(const pa_alsa_profile_info *sink, const pa_alsa_profile_info *source, void *userdata),
914 void *userdata) {
915
916 const pa_alsa_profile_info *i;
917
918 pa_assert(dev_id);
919 pa_assert(ss);
920 pa_assert(cb);
921
922 /* We try each combination of playback/capture. We also try to
923 * open only for capture resp. only for sink. Don't get confused
924 * by the trailing entry in device_table we use for this! */
925
926 for (i = device_table; i < device_table + PA_ELEMENTSOF(device_table); i++) {
927 const pa_alsa_profile_info *j;
928 snd_pcm_t *pcm_i = NULL;
929
930 if (i->alsa_name) {
931 char *id;
932 pa_sample_spec try_ss;
933 pa_channel_map try_map;
934
935 pa_log_debug("Checking for playback on %s (%s)", i->name, i->alsa_name);
936 id = pa_sprintf_malloc("%s:%s", i->alsa_name, dev_id);
937
938 try_ss = *ss;
939 try_ss.channels = i->map.channels;
940 try_map = i->map;
941
942 pcm_i = pa_alsa_open_by_device_string(
943 id, NULL,
944 &try_ss, &try_map,
945 SND_PCM_STREAM_PLAYBACK,
946 NULL, NULL, 0, NULL, NULL,
947 TRUE);
948
949 pa_xfree(id);
950
951 if (!pcm_i)
952 continue;
953 }
954
955 for (j = device_table; j < device_table + PA_ELEMENTSOF(device_table); j++) {
956 snd_pcm_t *pcm_j = NULL;
957
958 if (j->alsa_name) {
959 char *jd;
960 pa_sample_spec try_ss;
961 pa_channel_map try_map;
962
963 pa_log_debug("Checking for capture on %s (%s)", j->name, j->alsa_name);
964 jd = pa_sprintf_malloc("%s:%s", j->alsa_name, dev_id);
965
966 try_ss = *ss;
967 try_ss.channels = j->map.channels;
968 try_map = j->map;
969
970 pcm_j = pa_alsa_open_by_device_string(
971 jd, NULL,
972 &try_ss, &try_map,
973 SND_PCM_STREAM_CAPTURE,
974 NULL, NULL, 0, NULL, NULL,
975 TRUE);
976
977 pa_xfree(jd);
978
979 if (!pcm_j)
980 continue;
981 }
982
983 if (pcm_j)
984 snd_pcm_close(pcm_j);
985
986 if (i->alsa_name || j->alsa_name)
987 cb(i->alsa_name ? i : NULL,
988 j->alsa_name ? j : NULL, userdata);
989 }
990
991 if (pcm_i)
992 snd_pcm_close(pcm_i);
993 }
994
995 return TRUE;
996 }
997
998 int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
999 int err;
1000
1001 pa_assert(mixer);
1002 pa_assert(dev);
1003
1004 if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1005 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1006 return -1;
1007 }
1008
1009 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1010 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1011 return -1;
1012 }
1013
1014 if ((err = snd_mixer_load(mixer)) < 0) {
1015 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1016 return -1;
1017 }
1018
1019 pa_log_info("Successfully attached to mixer '%s'", dev);
1020
1021 return 0;
1022 }
1023
1024 static pa_bool_t elem_has_volume(snd_mixer_elem_t *elem, pa_bool_t playback) {
1025 pa_assert(elem);
1026
1027 if (playback && snd_mixer_selem_has_playback_volume(elem))
1028 return TRUE;
1029
1030 if (!playback && snd_mixer_selem_has_capture_volume(elem))
1031 return TRUE;
1032
1033 return FALSE;
1034 }
1035
1036 static pa_bool_t elem_has_switch(snd_mixer_elem_t *elem, pa_bool_t playback) {
1037 pa_assert(elem);
1038
1039 if (playback && snd_mixer_selem_has_playback_switch(elem))
1040 return TRUE;
1041
1042 if (!playback && snd_mixer_selem_has_capture_switch(elem))
1043 return TRUE;
1044
1045 return FALSE;
1046 }
1047
1048 snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback) {
1049 snd_mixer_elem_t *elem = NULL, *fallback_elem = NULL;
1050 snd_mixer_selem_id_t *sid = NULL;
1051
1052 snd_mixer_selem_id_alloca(&sid);
1053
1054 pa_assert(mixer);
1055 pa_assert(name);
1056
1057 snd_mixer_selem_id_set_name(sid, name);
1058 snd_mixer_selem_id_set_index(sid, 0);
1059
1060 if ((elem = snd_mixer_find_selem(mixer, sid))) {
1061
1062 if (elem_has_volume(elem, playback) &&
1063 elem_has_switch(elem, playback))
1064 goto success;
1065
1066 if (!elem_has_volume(elem, playback) &&
1067 !elem_has_switch(elem, playback))
1068 elem = NULL;
1069 }
1070
1071 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
1072
1073 if (fallback) {
1074 snd_mixer_selem_id_set_name(sid, fallback);
1075 snd_mixer_selem_id_set_index(sid, 0);
1076
1077 if ((fallback_elem = snd_mixer_find_selem(mixer, sid))) {
1078
1079 if (elem_has_volume(fallback_elem, playback) &&
1080 elem_has_switch(fallback_elem, playback)) {
1081 elem = fallback_elem;
1082 goto success;
1083 }
1084
1085 if (!elem_has_volume(fallback_elem, playback) &&
1086 !elem_has_switch(fallback_elem, playback))
1087 fallback_elem = NULL;
1088 }
1089
1090 pa_log_info("Cannot find fallback mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
1091 }
1092
1093 if (elem && fallback_elem) {
1094
1095 /* Hmm, so we have both elements, but neither has both mute
1096 * and volume. Let's prefer the one with the volume */
1097
1098 if (elem_has_volume(elem, playback))
1099 goto success;
1100
1101 if (elem_has_volume(fallback_elem, playback)) {
1102 elem = fallback_elem;
1103 goto success;
1104 }
1105 }
1106
1107 if (!elem && fallback_elem)
1108 elem = fallback_elem;
1109
1110 success:
1111
1112 if (elem)
1113 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
1114
1115 return elem;
1116 }
1117
1118 int pa_alsa_find_mixer_and_elem(
1119 snd_pcm_t *pcm,
1120 snd_mixer_t **_m,
1121 snd_mixer_elem_t **_e,
1122 const char *control_name,
1123 const pa_alsa_profile_info *profile) {
1124
1125 int err;
1126 snd_mixer_t *m;
1127 snd_mixer_elem_t *e;
1128 pa_bool_t found = FALSE;
1129 const char *dev;
1130
1131 pa_assert(pcm);
1132 pa_assert(_m);
1133 pa_assert(_e);
1134
1135 if (control_name && *control_name == 0) {
1136 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1137 return -1;
1138 }
1139
1140 if ((err = snd_mixer_open(&m, 0)) < 0) {
1141 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1142 return -1;
1143 }
1144
1145 /* First, try by name */
1146 if ((dev = snd_pcm_name(pcm)))
1147 if (pa_alsa_prepare_mixer(m, dev) >= 0)
1148 found = TRUE;
1149
1150 /* Then, try by card index */
1151 if (!found) {
1152 snd_pcm_info_t* info;
1153 snd_pcm_info_alloca(&info);
1154
1155 if (snd_pcm_info(pcm, info) >= 0) {
1156 char *md;
1157 int card_idx;
1158
1159 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1160
1161 md = pa_sprintf_malloc("hw:%i", card_idx);
1162
1163 if (!dev || !pa_streq(dev, md))
1164 if (pa_alsa_prepare_mixer(m, md) >= 0)
1165 found = TRUE;
1166
1167 pa_xfree(md);
1168 }
1169 }
1170 }
1171
1172 if (!found) {
1173 snd_mixer_close(m);
1174 return -1;
1175 }
1176
1177 switch (snd_pcm_stream(pcm)) {
1178
1179 case SND_PCM_STREAM_PLAYBACK:
1180 if (control_name)
1181 e = pa_alsa_find_elem(m, control_name, NULL, TRUE);
1182 else if (profile)
1183 e = pa_alsa_find_elem(m, profile->playback_control_name, profile->playback_control_fallback, TRUE);
1184 else
1185 e = pa_alsa_find_elem(m, "Master", "PCM", TRUE);
1186 break;
1187
1188 case SND_PCM_STREAM_CAPTURE:
1189 if (control_name)
1190 e = pa_alsa_find_elem(m, control_name, NULL, FALSE);
1191 else if (profile)
1192 e = pa_alsa_find_elem(m, profile->record_control_name, profile->record_control_fallback, FALSE);
1193 else
1194 e = pa_alsa_find_elem(m, "Capture", "Mic", FALSE);
1195 break;
1196
1197 default:
1198 pa_assert_not_reached();
1199 }
1200
1201 if (!e) {
1202 snd_mixer_close(m);
1203 return -1;
1204 }
1205
1206 pa_assert(e && m);
1207
1208 *_m = m;
1209 *_e = e;
1210
1211 return 0;
1212 }
1213
1214 static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = {
1215 [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
1216
1217 [PA_CHANNEL_POSITION_FRONT_CENTER] = SND_MIXER_SCHN_FRONT_CENTER,
1218 [PA_CHANNEL_POSITION_FRONT_LEFT] = SND_MIXER_SCHN_FRONT_LEFT,
1219 [PA_CHANNEL_POSITION_FRONT_RIGHT] = SND_MIXER_SCHN_FRONT_RIGHT,
1220
1221 [PA_CHANNEL_POSITION_REAR_CENTER] = SND_MIXER_SCHN_REAR_CENTER,
1222 [PA_CHANNEL_POSITION_REAR_LEFT] = SND_MIXER_SCHN_REAR_LEFT,
1223 [PA_CHANNEL_POSITION_REAR_RIGHT] = SND_MIXER_SCHN_REAR_RIGHT,
1224
1225 [PA_CHANNEL_POSITION_LFE] = SND_MIXER_SCHN_WOOFER,
1226
1227 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1228 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1229
1230 [PA_CHANNEL_POSITION_SIDE_LEFT] = SND_MIXER_SCHN_SIDE_LEFT,
1231 [PA_CHANNEL_POSITION_SIDE_RIGHT] = SND_MIXER_SCHN_SIDE_RIGHT,
1232
1233 [PA_CHANNEL_POSITION_AUX0] = SND_MIXER_SCHN_UNKNOWN,
1234 [PA_CHANNEL_POSITION_AUX1] = SND_MIXER_SCHN_UNKNOWN,
1235 [PA_CHANNEL_POSITION_AUX2] = SND_MIXER_SCHN_UNKNOWN,
1236 [PA_CHANNEL_POSITION_AUX3] = SND_MIXER_SCHN_UNKNOWN,
1237 [PA_CHANNEL_POSITION_AUX4] = SND_MIXER_SCHN_UNKNOWN,
1238 [PA_CHANNEL_POSITION_AUX5] = SND_MIXER_SCHN_UNKNOWN,
1239 [PA_CHANNEL_POSITION_AUX6] = SND_MIXER_SCHN_UNKNOWN,
1240 [PA_CHANNEL_POSITION_AUX7] = SND_MIXER_SCHN_UNKNOWN,
1241 [PA_CHANNEL_POSITION_AUX8] = SND_MIXER_SCHN_UNKNOWN,
1242 [PA_CHANNEL_POSITION_AUX9] = SND_MIXER_SCHN_UNKNOWN,
1243 [PA_CHANNEL_POSITION_AUX10] = SND_MIXER_SCHN_UNKNOWN,
1244 [PA_CHANNEL_POSITION_AUX11] = SND_MIXER_SCHN_UNKNOWN,
1245 [PA_CHANNEL_POSITION_AUX12] = SND_MIXER_SCHN_UNKNOWN,
1246 [PA_CHANNEL_POSITION_AUX13] = SND_MIXER_SCHN_UNKNOWN,
1247 [PA_CHANNEL_POSITION_AUX14] = SND_MIXER_SCHN_UNKNOWN,
1248 [PA_CHANNEL_POSITION_AUX15] = SND_MIXER_SCHN_UNKNOWN,
1249 [PA_CHANNEL_POSITION_AUX16] = SND_MIXER_SCHN_UNKNOWN,
1250 [PA_CHANNEL_POSITION_AUX17] = SND_MIXER_SCHN_UNKNOWN,
1251 [PA_CHANNEL_POSITION_AUX18] = SND_MIXER_SCHN_UNKNOWN,
1252 [PA_CHANNEL_POSITION_AUX19] = SND_MIXER_SCHN_UNKNOWN,
1253 [PA_CHANNEL_POSITION_AUX20] = SND_MIXER_SCHN_UNKNOWN,
1254 [PA_CHANNEL_POSITION_AUX21] = SND_MIXER_SCHN_UNKNOWN,
1255 [PA_CHANNEL_POSITION_AUX22] = SND_MIXER_SCHN_UNKNOWN,
1256 [PA_CHANNEL_POSITION_AUX23] = SND_MIXER_SCHN_UNKNOWN,
1257 [PA_CHANNEL_POSITION_AUX24] = SND_MIXER_SCHN_UNKNOWN,
1258 [PA_CHANNEL_POSITION_AUX25] = SND_MIXER_SCHN_UNKNOWN,
1259 [PA_CHANNEL_POSITION_AUX26] = SND_MIXER_SCHN_UNKNOWN,
1260 [PA_CHANNEL_POSITION_AUX27] = SND_MIXER_SCHN_UNKNOWN,
1261 [PA_CHANNEL_POSITION_AUX28] = SND_MIXER_SCHN_UNKNOWN,
1262 [PA_CHANNEL_POSITION_AUX29] = SND_MIXER_SCHN_UNKNOWN,
1263 [PA_CHANNEL_POSITION_AUX30] = SND_MIXER_SCHN_UNKNOWN,
1264 [PA_CHANNEL_POSITION_AUX31] = SND_MIXER_SCHN_UNKNOWN,
1265
1266 [PA_CHANNEL_POSITION_TOP_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1267
1268 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1269 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = SND_MIXER_SCHN_UNKNOWN,
1270 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = SND_MIXER_SCHN_UNKNOWN,
1271
1272 [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1273 [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = SND_MIXER_SCHN_UNKNOWN,
1274 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SND_MIXER_SCHN_UNKNOWN
1275 };
1276
1277
1278 int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback) {
1279 unsigned i;
1280 pa_bool_t alsa_channel_used[SND_MIXER_SCHN_LAST];
1281 pa_bool_t mono_used = FALSE;
1282
1283 pa_assert(elem);
1284 pa_assert(channel_map);
1285 pa_assert(mixer_map);
1286
1287 memset(&alsa_channel_used, 0, sizeof(alsa_channel_used));
1288
1289 if (channel_map->channels > 1 &&
1290 ((playback && snd_mixer_selem_has_playback_volume_joined(elem)) ||
1291 (!playback && snd_mixer_selem_has_capture_volume_joined(elem)))) {
1292 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1293 return -1;
1294 }
1295
1296 for (i = 0; i < channel_map->channels; i++) {
1297 snd_mixer_selem_channel_id_t id;
1298 pa_bool_t is_mono;
1299
1300 is_mono = channel_map->map[i] == PA_CHANNEL_POSITION_MONO;
1301 id = alsa_channel_ids[channel_map->map[i]];
1302
1303 if (!is_mono && id == SND_MIXER_SCHN_UNKNOWN) {
1304 pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer.", pa_channel_position_to_string(channel_map->map[i]));
1305 return -1;
1306 }
1307
1308 if ((is_mono && mono_used) || (!is_mono && alsa_channel_used[id])) {
1309 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
1310 return -1;
1311 }
1312
1313 if ((playback && (!snd_mixer_selem_has_playback_channel(elem, id) || (is_mono && !snd_mixer_selem_is_playback_mono(elem)))) ||
1314 (!playback && (!snd_mixer_selem_has_capture_channel(elem, id) || (is_mono && !snd_mixer_selem_is_capture_mono(elem))))) {
1315
1316 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map->map[i]));
1317 return -1;
1318 }
1319
1320 if (is_mono) {
1321 mixer_map[i] = SND_MIXER_SCHN_MONO;
1322 mono_used = TRUE;
1323 } else {
1324 mixer_map[i] = id;
1325 alsa_channel_used[id] = TRUE;
1326 }
1327 }
1328
1329 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map->channels);
1330
1331 return 0;
1332 }
1333
1334 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
1335 int err;
1336 snd_output_t *out;
1337
1338 pa_assert(pcm);
1339
1340 pa_assert_se(snd_output_buffer_open(&out) == 0);
1341
1342 if ((err = snd_pcm_dump(pcm, out)) < 0)
1343 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
1344 else {
1345 char *s = NULL;
1346 snd_output_buffer_string(out, &s);
1347 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
1348 }
1349
1350 pa_assert_se(snd_output_close(out) == 0);
1351 }
1352
1353 void pa_alsa_dump_status(snd_pcm_t *pcm) {
1354 int err;
1355 snd_output_t *out;
1356 snd_pcm_status_t *status;
1357
1358 pa_assert(pcm);
1359
1360 snd_pcm_status_alloca(&status);
1361
1362 pa_assert_se(snd_output_buffer_open(&out) == 0);
1363
1364 pa_assert_se(snd_pcm_status(pcm, status) == 0);
1365
1366 if ((err = snd_pcm_status_dump(status, out)) < 0)
1367 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
1368 else {
1369 char *s = NULL;
1370 snd_output_buffer_string(out, &s);
1371 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
1372 }
1373
1374 pa_assert_se(snd_output_close(out) == 0);
1375 }
1376
1377 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
1378 va_list ap;
1379 char *alsa_file;
1380
1381 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
1382
1383 va_start(ap, fmt);
1384
1385 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
1386
1387 va_end(ap);
1388
1389 pa_xfree(alsa_file);
1390 }
1391
1392 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
1393
1394 void pa_alsa_redirect_errors_inc(void) {
1395 /* This is not really thread safe, but we do our best */
1396
1397 if (pa_atomic_inc(&n_error_handler_installed) == 0)
1398 snd_lib_error_set_handler(alsa_error_handler);
1399 }
1400
1401 void pa_alsa_redirect_errors_dec(void) {
1402 int r;
1403
1404 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
1405
1406 if (r == 1)
1407 snd_lib_error_set_handler(NULL);
1408 }
1409
1410 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
1411 const char *s;
1412 pa_assert(p);
1413
1414 if (pa_device_init_description(p))
1415 return TRUE;
1416
1417 if ((s = pa_proplist_gets(p, "alsa.card_name"))) {
1418 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
1419 return TRUE;
1420 }
1421
1422 if ((s = pa_proplist_gets(p, "alsa.name"))) {
1423 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
1424 return TRUE;
1425 }
1426
1427 return FALSE;
1428 }
1429
1430 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
1431 char *cn, *lcn, *dn;
1432
1433 pa_assert(p);
1434 pa_assert(card >= 0);
1435
1436 pa_proplist_setf(p, "alsa.card", "%i", card);
1437
1438 if (snd_card_get_name(card, &cn) >= 0) {
1439 pa_proplist_sets(p, "alsa.card_name", cn);
1440 free(cn);
1441 }
1442
1443 if (snd_card_get_longname(card, &lcn) >= 0) {
1444 pa_proplist_sets(p, "alsa.long_card_name", lcn);
1445 free(lcn);
1446 }
1447
1448 if ((dn = pa_alsa_get_driver_name(card))) {
1449 pa_proplist_sets(p, "alsa.driver_name", dn);
1450 pa_xfree(dn);
1451 }
1452
1453 #ifdef HAVE_UDEV
1454 pa_udev_get_info(c, p, card);
1455 #endif
1456
1457 #ifdef HAVE_HAL
1458 pa_hal_get_info(c, p, card);
1459 #endif
1460 }
1461
1462 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
1463
1464 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
1465 [SND_PCM_CLASS_GENERIC] = "generic",
1466 [SND_PCM_CLASS_MULTI] = "multi",
1467 [SND_PCM_CLASS_MODEM] = "modem",
1468 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
1469 };
1470 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
1471 [SND_PCM_CLASS_GENERIC] = "sound",
1472 [SND_PCM_CLASS_MULTI] = NULL,
1473 [SND_PCM_CLASS_MODEM] = "modem",
1474 [SND_PCM_CLASS_DIGITIZER] = NULL
1475 };
1476 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
1477 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
1478 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
1479 };
1480
1481 snd_pcm_class_t class;
1482 snd_pcm_subclass_t subclass;
1483 const char *n, *id, *sdn;
1484 int card;
1485
1486 pa_assert(p);
1487 pa_assert(pcm_info);
1488
1489 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
1490
1491 class = snd_pcm_info_get_class(pcm_info);
1492 if (class <= SND_PCM_CLASS_LAST) {
1493 if (class_table[class])
1494 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
1495 if (alsa_class_table[class])
1496 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
1497 }
1498
1499 subclass = snd_pcm_info_get_subclass(pcm_info);
1500 if (subclass <= SND_PCM_SUBCLASS_LAST)
1501 if (alsa_subclass_table[subclass])
1502 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
1503
1504 if ((n = snd_pcm_info_get_name(pcm_info)))
1505 pa_proplist_sets(p, "alsa.name", n);
1506
1507 if ((id = snd_pcm_info_get_id(pcm_info)))
1508 pa_proplist_sets(p, "alsa.id", id);
1509
1510 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
1511 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
1512 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
1513
1514 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
1515
1516 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
1517 pa_alsa_init_proplist_card(c, p, card);
1518 }
1519
1520 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm, snd_mixer_elem_t *elem) {
1521 snd_pcm_hw_params_t *hwparams;
1522 snd_pcm_info_t *info;
1523 int bits, err;
1524
1525 snd_pcm_hw_params_alloca(&hwparams);
1526 snd_pcm_info_alloca(&info);
1527
1528 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
1529 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
1530 else {
1531
1532 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
1533 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
1534 }
1535
1536 if (elem)
1537 pa_proplist_sets(p, "alsa.mixer_element", snd_mixer_selem_get_name(elem));
1538
1539 if ((err = snd_pcm_info(pcm, info)) < 0)
1540 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1541 else
1542 pa_alsa_init_proplist_pcm_info(c, p, info);
1543 }
1544
1545 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1546 snd_pcm_state_t state;
1547 int err;
1548
1549 pa_assert(pcm);
1550
1551 if (revents & POLLERR)
1552 pa_log_debug("Got POLLERR from ALSA");
1553 if (revents & POLLNVAL)
1554 pa_log_warn("Got POLLNVAL from ALSA");
1555 if (revents & POLLHUP)
1556 pa_log_warn("Got POLLHUP from ALSA");
1557 if (revents & POLLPRI)
1558 pa_log_warn("Got POLLPRI from ALSA");
1559 if (revents & POLLIN)
1560 pa_log_debug("Got POLLIN from ALSA");
1561 if (revents & POLLOUT)
1562 pa_log_debug("Got POLLOUT from ALSA");
1563
1564 state = snd_pcm_state(pcm);
1565 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1566
1567 /* Try to recover from this error */
1568
1569 switch (state) {
1570
1571 case SND_PCM_STATE_XRUN:
1572 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1573 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1574 return -1;
1575 }
1576 break;
1577
1578 case SND_PCM_STATE_SUSPENDED:
1579 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1580 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1581 return -1;
1582 }
1583 break;
1584
1585 default:
1586
1587 snd_pcm_drop(pcm);
1588
1589 if ((err = snd_pcm_prepare(pcm)) < 0) {
1590 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1591 return -1;
1592 }
1593 break;
1594 }
1595
1596 return 0;
1597 }
1598
1599 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1600 int n, err;
1601 struct pollfd *pollfd;
1602 pa_rtpoll_item *item;
1603
1604 pa_assert(pcm);
1605
1606 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1607 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1608 return NULL;
1609 }
1610
1611 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1612 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1613
1614 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1615 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1616 pa_rtpoll_item_free(item);
1617 return NULL;
1618 }
1619
1620 return item;
1621 }
1622
1623 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1624 snd_pcm_sframes_t n;
1625 size_t k;
1626
1627 pa_assert(pcm);
1628 pa_assert(hwbuf_size > 0);
1629 pa_assert(ss);
1630
1631 /* Some ALSA driver expose weird bugs, let's inform the user about
1632 * what is going on */
1633
1634 n = snd_pcm_avail(pcm);
1635
1636 if (n <= 0)
1637 return n;
1638
1639 k = (size_t) n * pa_frame_size(ss);
1640
1641 if (k >= hwbuf_size * 5 ||
1642 k >= pa_bytes_per_second(ss)*10) {
1643
1644 PA_ONCE_BEGIN {
1645 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1646 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1647 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1648 (unsigned long) k,
1649 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1650 pa_strnull(dn));
1651 pa_xfree(dn);
1652 pa_alsa_dump(PA_LOG_ERROR, pcm);
1653 } PA_ONCE_END;
1654
1655 /* Mhmm, let's try not to fail completely */
1656 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1657 }
1658
1659 return n;
1660 }
1661
1662 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1663 ssize_t k;
1664 size_t abs_k;
1665 int r;
1666
1667 pa_assert(pcm);
1668 pa_assert(delay);
1669 pa_assert(hwbuf_size > 0);
1670 pa_assert(ss);
1671
1672 /* Some ALSA driver expose weird bugs, let's inform the user about
1673 * what is going on */
1674
1675 if ((r = snd_pcm_delay(pcm, delay)) < 0)
1676 return r;
1677
1678 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1679
1680 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1681
1682 if (abs_k >= hwbuf_size * 5 ||
1683 abs_k >= pa_bytes_per_second(ss)*10) {
1684
1685 PA_ONCE_BEGIN {
1686 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1687 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1688 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1689 (signed long) k,
1690 k < 0 ? "-" : "",
1691 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1692 pa_strnull(dn));
1693 pa_xfree(dn);
1694 pa_alsa_dump(PA_LOG_ERROR, pcm);
1695 } PA_ONCE_END;
1696
1697 /* Mhmm, let's try not to fail completely */
1698 if (k < 0)
1699 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1700 else
1701 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1702 }
1703
1704 return 0;
1705 }
1706
1707 int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss) {
1708 int r;
1709 snd_pcm_uframes_t before;
1710 size_t k;
1711
1712 pa_assert(pcm);
1713 pa_assert(areas);
1714 pa_assert(offset);
1715 pa_assert(frames);
1716 pa_assert(hwbuf_size > 0);
1717 pa_assert(ss);
1718
1719 before = *frames;
1720
1721 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1722
1723 if (r < 0)
1724 return r;
1725
1726 k = (size_t) *frames * pa_frame_size(ss);
1727
1728 if (*frames > before ||
1729 k >= hwbuf_size * 3 ||
1730 k >= pa_bytes_per_second(ss)*10)
1731
1732 PA_ONCE_BEGIN {
1733 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1734 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1735 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1736 (unsigned long) k,
1737 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1738 pa_strnull(dn));
1739 pa_xfree(dn);
1740 pa_alsa_dump(PA_LOG_ERROR, pcm);
1741 } PA_ONCE_END;
1742
1743 return r;
1744 }
1745
1746 char *pa_alsa_get_driver_name(int card) {
1747 char *t, *m, *n;
1748
1749 pa_assert(card >= 0);
1750
1751 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1752 m = pa_readlink(t);
1753 pa_xfree(t);
1754
1755 if (!m)
1756 return NULL;
1757
1758 n = pa_xstrdup(pa_path_get_filename(m));
1759 pa_xfree(m);
1760
1761 return n;
1762 }
1763
1764 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1765 int card;
1766 snd_pcm_info_t* info;
1767 snd_pcm_info_alloca(&info);
1768
1769 pa_assert(pcm);
1770
1771 if (snd_pcm_info(pcm, info) < 0)
1772 return NULL;
1773
1774 if ((card = snd_pcm_info_get_card(info)) < 0)
1775 return NULL;
1776
1777 return pa_alsa_get_driver_name(card);
1778 }
1779
1780 char *pa_alsa_get_reserve_name(const char *device) {
1781 const char *t;
1782 int i;
1783
1784 pa_assert(device);
1785
1786 if ((t = strchr(device, ':')))
1787 device = t+1;
1788
1789 if ((i = snd_card_get_index(device)) < 0) {
1790 int32_t k;
1791
1792 if (pa_atoi(device, &k) < 0)
1793 return NULL;
1794
1795 i = (int) k;
1796 }
1797
1798 return pa_sprintf_malloc("Audio%i", i);
1799 }
1800
1801 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1802 snd_pcm_info_t* info;
1803 snd_pcm_info_alloca(&info);
1804
1805 pa_assert(pcm);
1806
1807 if (snd_pcm_info(pcm, info) < 0)
1808 return FALSE;
1809
1810 return snd_pcm_info_get_card(info) >= 0;
1811 }
1812
1813 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1814 snd_pcm_info_t* info;
1815 snd_pcm_info_alloca(&info);
1816
1817 pa_assert(pcm);
1818
1819 if (snd_pcm_info(pcm, info) < 0)
1820 return FALSE;
1821
1822 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1823 }
1824
1825 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1826
1827 const char* pa_alsa_strerror(int errnum) {
1828 const char *original = NULL;
1829 char *translated, *t;
1830 char errbuf[128];
1831
1832 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1833 pa_xfree(t);
1834
1835 original = snd_strerror(errnum);
1836
1837 if (!original) {
1838 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1839 original = errbuf;
1840 }
1841
1842 if (!(translated = pa_locale_to_utf8(original))) {
1843 pa_log_warn("Unable to convert error string to locale, filtering.");
1844 translated = pa_utf8_filter(original);
1845 }
1846
1847 PA_STATIC_TLS_SET(cstrerror, translated);
1848
1849 return translated;
1850 }