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