]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
alsa: include the alsa mixer control that is used in the property list
[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 "Master", "PCM",
534 "Capture", "Mic" },
535
536 {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
537 "front",
538 N_("Analog Stereo"),
539 "analog-stereo",
540 10,
541 "Master", "PCM",
542 "Capture", "Mic" },
543
544 {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
545 "iec958",
546 N_("Digital Stereo (IEC958)"),
547 "iec958-stereo",
548 5,
549 "IEC958", NULL,
550 "IEC958 In", NULL },
551
552 {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
553 "hdmi",
554 N_("Digital Stereo (HDMI)"),
555 "hdmi-stereo",
556 4,
557 "IEC958", NULL,
558 "IEC958 In", NULL },
559
560 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
561 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
562 "surround40",
563 N_("Analog Surround 4.0"),
564 "analog-surround-40",
565 7,
566 "Master", "PCM",
567 "Capture", "Mic" },
568
569 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
570 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
571 "a52",
572 N_("Digital Surround 4.0 (IEC958/AC3)"),
573 "iec958-ac3-surround-40",
574 2,
575 "Master", "PCM",
576 "Capture", "Mic" },
577
578 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
579 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
580 PA_CHANNEL_POSITION_LFE }},
581 "surround41",
582 N_("Analog Surround 4.1"),
583 "analog-surround-41",
584 7,
585 "Master", "PCM",
586 "Capture", "Mic" },
587
588 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
589 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
590 PA_CHANNEL_POSITION_CENTER }},
591 "surround50",
592 N_("Analog Surround 5.0"),
593 "analog-surround-50",
594 7,
595 "Master", "PCM",
596 "Capture", "Mic" },
597
598 {{ 6, { 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 "surround51",
602 N_("Analog Surround 5.1"),
603 "analog-surround-51",
604 8,
605 "Master", "PCM",
606 "Capture", "Mic" },
607
608 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
609 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
610 PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE}},
611 "a52",
612 N_("Digital Surround 5.1 (IEC958/AC3)"),
613 "iec958-ac3-surround-51",
614 3,
615 "IEC958", NULL,
616 "IEC958 In", NULL },
617
618 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
619 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
620 PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
621 PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }},
622 "surround71",
623 N_("Analog Surround 7.1"),
624 "analog-surround-71",
625 7,
626 "Master", "PCM",
627 "Capture", "Mic" },
628
629 {{ 0, { 0 }}, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
630 };
631
632 snd_pcm_t *pa_alsa_open_by_device_id_auto(
633 const char *dev_id,
634 char **dev,
635 pa_sample_spec *ss,
636 pa_channel_map* map,
637 int mode,
638 uint32_t *nfrags,
639 snd_pcm_uframes_t *period_size,
640 snd_pcm_uframes_t tsched_size,
641 pa_bool_t *use_mmap,
642 pa_bool_t *use_tsched,
643 const pa_alsa_profile_info **profile) {
644
645 int i;
646 int direction = 1;
647 char *d;
648 snd_pcm_t *pcm_handle;
649
650 pa_assert(dev_id);
651 pa_assert(dev);
652 pa_assert(ss);
653 pa_assert(map);
654 pa_assert(nfrags);
655 pa_assert(period_size);
656
657 /* First we try to find a device string with a superset of the
658 * requested channel map and open it without the plug: prefix. We
659 * iterate through our device table from top to bottom and take
660 * the first that matches. If we didn't find a working device that
661 * way, we iterate backwards, and check all devices that do not
662 * provide a superset of the requested channel map.*/
663
664 i = 0;
665 for (;;) {
666
667 if ((direction > 0) == pa_channel_map_superset(&device_table[i].map, map)) {
668 pa_sample_spec try_ss;
669
670 pa_log_debug("Checking for %s (%s)", device_table[i].name, device_table[i].alsa_name);
671
672 d = pa_sprintf_malloc("%s:%s", device_table[i].alsa_name, dev_id);
673
674 try_ss.channels = device_table[i].map.channels;
675 try_ss.rate = ss->rate;
676 try_ss.format = ss->format;
677
678 pcm_handle = pa_alsa_open_by_device_string(
679 d,
680 dev,
681 &try_ss,
682 map,
683 mode,
684 nfrags,
685 period_size,
686 tsched_size,
687 use_mmap,
688 use_tsched,
689 TRUE);
690
691 pa_xfree(d);
692
693 if (pcm_handle) {
694
695 *ss = try_ss;
696 *map = device_table[i].map;
697 pa_assert(map->channels == ss->channels);
698
699 if (profile)
700 *profile = &device_table[i];
701
702 return pcm_handle;
703 }
704 }
705
706 if (direction > 0) {
707 if (!device_table[i+1].alsa_name) {
708 /* OK, so we are at the end of our list. Let's turn
709 * back. */
710 direction = -1;
711 } else {
712 /* We are not at the end of the list, so let's simply
713 * try the next entry */
714 i++;
715 }
716 }
717
718 if (direction < 0) {
719
720 if (device_table[i+1].alsa_name &&
721 device_table[i].map.channels == device_table[i+1].map.channels) {
722
723 /* OK, the next entry has the same number of channels,
724 * let's try it */
725 i++;
726
727 } else {
728 /* Hmm, so the next entry does not have the same
729 * number of channels, so let's go backwards until we
730 * find the next entry with a different number of
731 * channels */
732
733 for (i--; i >= 0; i--)
734 if (device_table[i].map.channels != device_table[i+1].map.channels)
735 break;
736
737 /* Hmm, there is no entry with a different number of
738 * entries, then we're done */
739 if (i < 0)
740 break;
741
742 /* OK, now lets find go back as long as we have the same number of channels */
743 for (; i > 0; i--)
744 if (device_table[i].map.channels != device_table[i-1].map.channels)
745 break;
746 }
747 }
748 }
749
750 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
751
752 d = pa_sprintf_malloc("hw:%s", dev_id);
753 pa_log_debug("Trying %s as last resort...", d);
754 pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
755 pa_xfree(d);
756
757 if (pcm_handle && profile)
758 *profile = NULL;
759
760 return pcm_handle;
761 }
762
763 snd_pcm_t *pa_alsa_open_by_device_id_profile(
764 const char *dev_id,
765 char **dev,
766 pa_sample_spec *ss,
767 pa_channel_map* map,
768 int mode,
769 uint32_t *nfrags,
770 snd_pcm_uframes_t *period_size,
771 snd_pcm_uframes_t tsched_size,
772 pa_bool_t *use_mmap,
773 pa_bool_t *use_tsched,
774 const pa_alsa_profile_info *profile) {
775
776 char *d;
777 snd_pcm_t *pcm_handle;
778 pa_sample_spec try_ss;
779
780 pa_assert(dev_id);
781 pa_assert(dev);
782 pa_assert(ss);
783 pa_assert(map);
784 pa_assert(nfrags);
785 pa_assert(period_size);
786 pa_assert(profile);
787
788 d = pa_sprintf_malloc("%s:%s", profile->alsa_name, dev_id);
789
790 try_ss.channels = profile->map.channels;
791 try_ss.rate = ss->rate;
792 try_ss.format = ss->format;
793
794 pcm_handle = pa_alsa_open_by_device_string(
795 d,
796 dev,
797 &try_ss,
798 map,
799 mode,
800 nfrags,
801 period_size,
802 tsched_size,
803 use_mmap,
804 use_tsched,
805 TRUE);
806
807 pa_xfree(d);
808
809 if (!pcm_handle)
810 return NULL;
811
812 *ss = try_ss;
813 *map = profile->map;
814 pa_assert(map->channels == ss->channels);
815
816 return pcm_handle;
817 }
818
819 snd_pcm_t *pa_alsa_open_by_device_string(
820 const char *device,
821 char **dev,
822 pa_sample_spec *ss,
823 pa_channel_map* map,
824 int mode,
825 uint32_t *nfrags,
826 snd_pcm_uframes_t *period_size,
827 snd_pcm_uframes_t tsched_size,
828 pa_bool_t *use_mmap,
829 pa_bool_t *use_tsched,
830 pa_bool_t require_exact_channel_number) {
831
832 int err;
833 char *d;
834 snd_pcm_t *pcm_handle;
835 pa_bool_t reformat = FALSE;
836
837 pa_assert(device);
838 pa_assert(ss);
839 pa_assert(map);
840
841 d = pa_xstrdup(device);
842
843 for (;;) {
844 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
845
846 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
847 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
848 * we enable nonblock mode afterwards via
849 * snd_pcm_nonblock(). Also see
850 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
851
852 if ((err = snd_pcm_open(&pcm_handle, d, mode,
853 /*SND_PCM_NONBLOCK|*/
854 SND_PCM_NO_AUTO_RESAMPLE|
855 SND_PCM_NO_AUTO_CHANNELS|
856 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
857 pa_log_info("Error opening PCM device %s: %s", d, snd_strerror(err));
858 goto fail;
859 }
860
861 if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
862
863 if (!reformat) {
864 reformat = TRUE;
865
866 snd_pcm_close(pcm_handle);
867 continue;
868 }
869
870 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
871
872 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
873 char *t;
874
875 t = pa_sprintf_malloc("plug:%s", d);
876 pa_xfree(d);
877 d = t;
878
879 reformat = FALSE;
880
881 snd_pcm_close(pcm_handle);
882 continue;
883 }
884
885 pa_log_info("Failed to set hardware parameters on %s: %s", d, snd_strerror(err));
886 snd_pcm_close(pcm_handle);
887
888 goto fail;
889 }
890
891 if (dev)
892 *dev = d;
893 else
894 pa_xfree(d);
895
896 if (ss->channels != map->channels)
897 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
898
899 return pcm_handle;
900 }
901
902 fail:
903 pa_xfree(d);
904
905 return NULL;
906 }
907
908 int pa_alsa_probe_profiles(
909 const char *dev_id,
910 const pa_sample_spec *ss,
911 void (*cb)(const pa_alsa_profile_info *sink, const pa_alsa_profile_info *source, void *userdata),
912 void *userdata) {
913
914 const pa_alsa_profile_info *i;
915
916 pa_assert(dev_id);
917 pa_assert(ss);
918 pa_assert(cb);
919
920 /* We try each combination of playback/capture. We also try to
921 * open only for capture resp. only for sink. Don't get confused
922 * by the trailing entry in device_table we use for this! */
923
924 for (i = device_table; i < device_table + PA_ELEMENTSOF(device_table); i++) {
925 const pa_alsa_profile_info *j;
926 snd_pcm_t *pcm_i = NULL;
927
928 if (i->alsa_name) {
929 char *id;
930 pa_sample_spec try_ss;
931 pa_channel_map try_map;
932
933 pa_log_debug("Checking for playback on %s (%s)", i->name, i->alsa_name);
934 id = pa_sprintf_malloc("%s:%s", i->alsa_name, dev_id);
935
936 try_ss = *ss;
937 try_ss.channels = i->map.channels;
938 try_map = i->map;
939
940 pcm_i = pa_alsa_open_by_device_string(
941 id, NULL,
942 &try_ss, &try_map,
943 SND_PCM_STREAM_PLAYBACK,
944 NULL, NULL, 0, NULL, NULL,
945 TRUE);
946
947 pa_xfree(id);
948
949 if (!pcm_i)
950 continue;
951 }
952
953 for (j = device_table; j < device_table + PA_ELEMENTSOF(device_table); j++) {
954 snd_pcm_t *pcm_j = NULL;
955
956 if (j->alsa_name) {
957 char *jd;
958 pa_sample_spec try_ss;
959 pa_channel_map try_map;
960
961 pa_log_debug("Checking for capture on %s (%s)", j->name, j->alsa_name);
962 jd = pa_sprintf_malloc("%s:%s", j->alsa_name, dev_id);
963
964 try_ss = *ss;
965 try_ss.channels = j->map.channels;
966 try_map = j->map;
967
968 pcm_j = pa_alsa_open_by_device_string(
969 jd, NULL,
970 &try_ss, &try_map,
971 SND_PCM_STREAM_CAPTURE,
972 NULL, NULL, 0, NULL, NULL,
973 TRUE);
974
975 pa_xfree(jd);
976
977 if (!pcm_j)
978 continue;
979 }
980
981 if (pcm_j)
982 snd_pcm_close(pcm_j);
983
984 if (i->alsa_name || j->alsa_name)
985 cb(i->alsa_name ? i : NULL,
986 j->alsa_name ? j : NULL, userdata);
987 }
988
989 if (pcm_i)
990 snd_pcm_close(pcm_i);
991 }
992
993 return TRUE;
994 }
995
996 int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
997 int err;
998
999 pa_assert(mixer);
1000 pa_assert(dev);
1001
1002 if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1003 pa_log_info("Unable to attach to mixer %s: %s", dev, snd_strerror(err));
1004 return -1;
1005 }
1006
1007 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1008 pa_log_warn("Unable to register mixer: %s", snd_strerror(err));
1009 return -1;
1010 }
1011
1012 if ((err = snd_mixer_load(mixer)) < 0) {
1013 pa_log_warn("Unable to load mixer: %s", snd_strerror(err));
1014 return -1;
1015 }
1016
1017 pa_log_info("Successfully attached to mixer '%s'", dev);
1018
1019 return 0;
1020 }
1021
1022 static pa_bool_t elem_has_volume(snd_mixer_elem_t *elem, pa_bool_t playback) {
1023 pa_assert(elem);
1024
1025 if (playback && snd_mixer_selem_has_playback_volume(elem))
1026 return TRUE;
1027
1028 if (!playback && snd_mixer_selem_has_capture_volume(elem))
1029 return TRUE;
1030
1031 return FALSE;
1032 }
1033
1034 static pa_bool_t elem_has_switch(snd_mixer_elem_t *elem, pa_bool_t playback) {
1035 pa_assert(elem);
1036
1037 if (playback && snd_mixer_selem_has_playback_switch(elem))
1038 return TRUE;
1039
1040 if (!playback && snd_mixer_selem_has_capture_switch(elem))
1041 return TRUE;
1042
1043 return FALSE;
1044 }
1045
1046 snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback) {
1047 snd_mixer_elem_t *elem = NULL, *fallback_elem = NULL;
1048 snd_mixer_selem_id_t *sid = NULL;
1049
1050 snd_mixer_selem_id_alloca(&sid);
1051
1052 pa_assert(mixer);
1053 pa_assert(name);
1054
1055 snd_mixer_selem_id_set_name(sid, name);
1056 snd_mixer_selem_id_set_index(sid, 0);
1057
1058 if ((elem = snd_mixer_find_selem(mixer, sid))) {
1059
1060 if (elem_has_volume(elem, playback) &&
1061 elem_has_switch(elem, playback))
1062 goto success;
1063
1064 if (!elem_has_volume(elem, playback) &&
1065 !elem_has_switch(elem, playback))
1066 elem = NULL;
1067 }
1068
1069 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
1070
1071 if (fallback) {
1072 snd_mixer_selem_id_set_name(sid, fallback);
1073 snd_mixer_selem_id_set_index(sid, 0);
1074
1075 if ((fallback_elem = snd_mixer_find_selem(mixer, sid))) {
1076
1077 if (elem_has_volume(fallback_elem, playback) &&
1078 elem_has_switch(fallback_elem, playback)) {
1079 elem = fallback_elem;
1080 goto success;
1081 }
1082
1083 if (!elem_has_volume(fallback_elem, playback) &&
1084 !elem_has_switch(fallback_elem, playback))
1085 fallback_elem = NULL;
1086 }
1087
1088 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));
1089 }
1090
1091 if (elem && fallback_elem) {
1092
1093 /* Hmm, so we have both elements, but neither has both mute
1094 * and volume. Let's prefer the one with the volume */
1095
1096 if (elem_has_volume(elem, playback))
1097 goto success;
1098
1099 if (elem_has_volume(fallback_elem, playback)) {
1100 elem = fallback_elem;
1101 goto success;
1102 }
1103 }
1104
1105 if (!elem && fallback_elem)
1106 elem = fallback_elem;
1107
1108 success:
1109
1110 if (elem)
1111 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
1112
1113 return elem;
1114 }
1115
1116 int pa_alsa_find_mixer_and_elem(
1117 snd_pcm_t *pcm,
1118 snd_mixer_t **_m,
1119 snd_mixer_elem_t **_e,
1120 const char *control_name,
1121 const pa_alsa_profile_info *profile) {
1122
1123 int err;
1124 snd_mixer_t *m;
1125 snd_mixer_elem_t *e;
1126 pa_bool_t found = FALSE;
1127 const char *dev;
1128
1129 pa_assert(pcm);
1130 pa_assert(_m);
1131 pa_assert(_e);
1132
1133 if (control_name && *control_name == 0) {
1134 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1135 return -1;
1136 }
1137
1138 if ((err = snd_mixer_open(&m, 0)) < 0) {
1139 pa_log("Error opening mixer: %s", snd_strerror(err));
1140 return -1;
1141 }
1142
1143 /* First, try by name */
1144 if ((dev = snd_pcm_name(pcm)))
1145 if (pa_alsa_prepare_mixer(m, dev) >= 0)
1146 found = TRUE;
1147
1148 /* Then, try by card index */
1149 if (!found) {
1150 snd_pcm_info_t* info;
1151 snd_pcm_info_alloca(&info);
1152
1153 if (snd_pcm_info(pcm, info) >= 0) {
1154 char *md;
1155 int card_idx;
1156
1157 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1158
1159 md = pa_sprintf_malloc("hw:%i", card_idx);
1160
1161 if (!dev || !pa_streq(dev, md))
1162 if (pa_alsa_prepare_mixer(m, md) >= 0)
1163 found = TRUE;
1164
1165 pa_xfree(md);
1166 }
1167 }
1168 }
1169
1170 if (!found) {
1171 snd_mixer_close(m);
1172 return -1;
1173 }
1174
1175 switch (snd_pcm_stream(pcm)) {
1176
1177 case SND_PCM_STREAM_PLAYBACK:
1178 if (control_name)
1179 e = pa_alsa_find_elem(m, control_name, NULL, TRUE);
1180 else if (profile)
1181 e = pa_alsa_find_elem(m, profile->playback_control_name, profile->playback_control_fallback, TRUE);
1182 else
1183 e = pa_alsa_find_elem(m, "Master", "PCM", TRUE);
1184 break;
1185
1186 case SND_PCM_STREAM_CAPTURE:
1187 if (control_name)
1188 e = pa_alsa_find_elem(m, control_name, NULL, FALSE);
1189 else if (profile)
1190 e = pa_alsa_find_elem(m, profile->record_control_name, profile->record_control_fallback, FALSE);
1191 else
1192 e = pa_alsa_find_elem(m, "Capture", "Mic", FALSE);
1193 break;
1194
1195 default:
1196 pa_assert_not_reached();
1197 }
1198
1199 if (!e) {
1200 snd_mixer_close(m);
1201 return -1;
1202 }
1203
1204 pa_assert(e && m);
1205
1206 *_m = m;
1207 *_e = e;
1208
1209 return 0;
1210 }
1211
1212 static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = {
1213 [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
1214
1215 [PA_CHANNEL_POSITION_FRONT_CENTER] = SND_MIXER_SCHN_FRONT_CENTER,
1216 [PA_CHANNEL_POSITION_FRONT_LEFT] = SND_MIXER_SCHN_FRONT_LEFT,
1217 [PA_CHANNEL_POSITION_FRONT_RIGHT] = SND_MIXER_SCHN_FRONT_RIGHT,
1218
1219 [PA_CHANNEL_POSITION_REAR_CENTER] = SND_MIXER_SCHN_REAR_CENTER,
1220 [PA_CHANNEL_POSITION_REAR_LEFT] = SND_MIXER_SCHN_REAR_LEFT,
1221 [PA_CHANNEL_POSITION_REAR_RIGHT] = SND_MIXER_SCHN_REAR_RIGHT,
1222
1223 [PA_CHANNEL_POSITION_LFE] = SND_MIXER_SCHN_WOOFER,
1224
1225 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1226 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1227
1228 [PA_CHANNEL_POSITION_SIDE_LEFT] = SND_MIXER_SCHN_SIDE_LEFT,
1229 [PA_CHANNEL_POSITION_SIDE_RIGHT] = SND_MIXER_SCHN_SIDE_RIGHT,
1230
1231 [PA_CHANNEL_POSITION_AUX0] = SND_MIXER_SCHN_UNKNOWN,
1232 [PA_CHANNEL_POSITION_AUX1] = SND_MIXER_SCHN_UNKNOWN,
1233 [PA_CHANNEL_POSITION_AUX2] = SND_MIXER_SCHN_UNKNOWN,
1234 [PA_CHANNEL_POSITION_AUX3] = SND_MIXER_SCHN_UNKNOWN,
1235 [PA_CHANNEL_POSITION_AUX4] = SND_MIXER_SCHN_UNKNOWN,
1236 [PA_CHANNEL_POSITION_AUX5] = SND_MIXER_SCHN_UNKNOWN,
1237 [PA_CHANNEL_POSITION_AUX6] = SND_MIXER_SCHN_UNKNOWN,
1238 [PA_CHANNEL_POSITION_AUX7] = SND_MIXER_SCHN_UNKNOWN,
1239 [PA_CHANNEL_POSITION_AUX8] = SND_MIXER_SCHN_UNKNOWN,
1240 [PA_CHANNEL_POSITION_AUX9] = SND_MIXER_SCHN_UNKNOWN,
1241 [PA_CHANNEL_POSITION_AUX10] = SND_MIXER_SCHN_UNKNOWN,
1242 [PA_CHANNEL_POSITION_AUX11] = SND_MIXER_SCHN_UNKNOWN,
1243 [PA_CHANNEL_POSITION_AUX12] = SND_MIXER_SCHN_UNKNOWN,
1244 [PA_CHANNEL_POSITION_AUX13] = SND_MIXER_SCHN_UNKNOWN,
1245 [PA_CHANNEL_POSITION_AUX14] = SND_MIXER_SCHN_UNKNOWN,
1246 [PA_CHANNEL_POSITION_AUX15] = SND_MIXER_SCHN_UNKNOWN,
1247 [PA_CHANNEL_POSITION_AUX16] = SND_MIXER_SCHN_UNKNOWN,
1248 [PA_CHANNEL_POSITION_AUX17] = SND_MIXER_SCHN_UNKNOWN,
1249 [PA_CHANNEL_POSITION_AUX18] = SND_MIXER_SCHN_UNKNOWN,
1250 [PA_CHANNEL_POSITION_AUX19] = SND_MIXER_SCHN_UNKNOWN,
1251 [PA_CHANNEL_POSITION_AUX20] = SND_MIXER_SCHN_UNKNOWN,
1252 [PA_CHANNEL_POSITION_AUX21] = SND_MIXER_SCHN_UNKNOWN,
1253 [PA_CHANNEL_POSITION_AUX22] = SND_MIXER_SCHN_UNKNOWN,
1254 [PA_CHANNEL_POSITION_AUX23] = SND_MIXER_SCHN_UNKNOWN,
1255 [PA_CHANNEL_POSITION_AUX24] = SND_MIXER_SCHN_UNKNOWN,
1256 [PA_CHANNEL_POSITION_AUX25] = SND_MIXER_SCHN_UNKNOWN,
1257 [PA_CHANNEL_POSITION_AUX26] = SND_MIXER_SCHN_UNKNOWN,
1258 [PA_CHANNEL_POSITION_AUX27] = SND_MIXER_SCHN_UNKNOWN,
1259 [PA_CHANNEL_POSITION_AUX28] = SND_MIXER_SCHN_UNKNOWN,
1260 [PA_CHANNEL_POSITION_AUX29] = SND_MIXER_SCHN_UNKNOWN,
1261 [PA_CHANNEL_POSITION_AUX30] = SND_MIXER_SCHN_UNKNOWN,
1262 [PA_CHANNEL_POSITION_AUX31] = SND_MIXER_SCHN_UNKNOWN,
1263
1264 [PA_CHANNEL_POSITION_TOP_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1265
1266 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1267 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = SND_MIXER_SCHN_UNKNOWN,
1268 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = SND_MIXER_SCHN_UNKNOWN,
1269
1270 [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1271 [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = SND_MIXER_SCHN_UNKNOWN,
1272 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SND_MIXER_SCHN_UNKNOWN
1273 };
1274
1275
1276 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) {
1277 unsigned i;
1278 pa_bool_t alsa_channel_used[SND_MIXER_SCHN_LAST];
1279 pa_bool_t mono_used = FALSE;
1280
1281 pa_assert(elem);
1282 pa_assert(channel_map);
1283 pa_assert(mixer_map);
1284
1285 memset(&alsa_channel_used, 0, sizeof(alsa_channel_used));
1286
1287 if (channel_map->channels > 1 &&
1288 ((playback && snd_mixer_selem_has_playback_volume_joined(elem)) ||
1289 (!playback && snd_mixer_selem_has_capture_volume_joined(elem)))) {
1290 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1291 return -1;
1292 }
1293
1294 for (i = 0; i < channel_map->channels; i++) {
1295 snd_mixer_selem_channel_id_t id;
1296 pa_bool_t is_mono;
1297
1298 is_mono = channel_map->map[i] == PA_CHANNEL_POSITION_MONO;
1299 id = alsa_channel_ids[channel_map->map[i]];
1300
1301 if (!is_mono && id == SND_MIXER_SCHN_UNKNOWN) {
1302 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]));
1303 return -1;
1304 }
1305
1306 if ((is_mono && mono_used) || (!is_mono && alsa_channel_used[id])) {
1307 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
1308 return -1;
1309 }
1310
1311 if ((playback && (!snd_mixer_selem_has_playback_channel(elem, id) || (is_mono && !snd_mixer_selem_is_playback_mono(elem)))) ||
1312 (!playback && (!snd_mixer_selem_has_capture_channel(elem, id) || (is_mono && !snd_mixer_selem_is_capture_mono(elem))))) {
1313
1314 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map->map[i]));
1315 return -1;
1316 }
1317
1318 if (is_mono) {
1319 mixer_map[i] = SND_MIXER_SCHN_MONO;
1320 mono_used = TRUE;
1321 } else {
1322 mixer_map[i] = id;
1323 alsa_channel_used[id] = TRUE;
1324 }
1325 }
1326
1327 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map->channels);
1328
1329 return 0;
1330 }
1331
1332 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
1333 int err;
1334 snd_output_t *out;
1335
1336 pa_assert(pcm);
1337
1338 pa_assert_se(snd_output_buffer_open(&out) == 0);
1339
1340 if ((err = snd_pcm_dump(pcm, out)) < 0)
1341 pa_logl(level, "snd_pcm_dump(): %s", snd_strerror(err));
1342 else {
1343 char *s = NULL;
1344 snd_output_buffer_string(out, &s);
1345 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
1346 }
1347
1348 pa_assert_se(snd_output_close(out) == 0);
1349 }
1350
1351 void pa_alsa_dump_status(snd_pcm_t *pcm) {
1352 int err;
1353 snd_output_t *out;
1354 snd_pcm_status_t *status;
1355
1356 pa_assert(pcm);
1357
1358 snd_pcm_status_alloca(&status);
1359
1360 pa_assert_se(snd_output_buffer_open(&out) == 0);
1361
1362 pa_assert_se(snd_pcm_status(pcm, status) == 0);
1363
1364 if ((err = snd_pcm_status_dump(status, out)) < 0)
1365 pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err));
1366 else {
1367 char *s = NULL;
1368 snd_output_buffer_string(out, &s);
1369 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
1370 }
1371
1372 pa_assert_se(snd_output_close(out) == 0);
1373 }
1374
1375 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
1376 va_list ap;
1377 char *alsa_file;
1378
1379 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
1380
1381 va_start(ap, fmt);
1382
1383 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
1384
1385 va_end(ap);
1386
1387 pa_xfree(alsa_file);
1388 }
1389
1390 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
1391
1392 void pa_alsa_redirect_errors_inc(void) {
1393 /* This is not really thread safe, but we do our best */
1394
1395 if (pa_atomic_inc(&n_error_handler_installed) == 0)
1396 snd_lib_error_set_handler(alsa_error_handler);
1397 }
1398
1399 void pa_alsa_redirect_errors_dec(void) {
1400 int r;
1401
1402 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
1403
1404 if (r == 1)
1405 snd_lib_error_set_handler(NULL);
1406 }
1407
1408 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
1409 const char *s;
1410 pa_assert(p);
1411
1412 if (pa_device_init_description(p))
1413 return TRUE;
1414
1415 if ((s = pa_proplist_gets(p, "alsa.card_name"))) {
1416 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
1417 return TRUE;
1418 }
1419
1420 if ((s = pa_proplist_gets(p, "alsa.name"))) {
1421 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
1422 return TRUE;
1423 }
1424
1425 return FALSE;
1426 }
1427
1428 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
1429 char *cn, *lcn, *dn;
1430
1431 pa_assert(p);
1432 pa_assert(card >= 0);
1433
1434 pa_proplist_setf(p, "alsa.card", "%i", card);
1435
1436 if (snd_card_get_name(card, &cn) >= 0) {
1437 pa_proplist_sets(p, "alsa.card_name", cn);
1438 free(cn);
1439 }
1440
1441 if (snd_card_get_longname(card, &lcn) >= 0) {
1442 pa_proplist_sets(p, "alsa.long_card_name", lcn);
1443 free(lcn);
1444 }
1445
1446 if ((dn = pa_alsa_get_driver_name(card))) {
1447 pa_proplist_sets(p, "alsa.driver_name", dn);
1448 pa_xfree(dn);
1449 }
1450
1451 #ifdef HAVE_UDEV
1452 pa_udev_get_info(c, p, card);
1453 #endif
1454
1455 #ifdef HAVE_HAL
1456 pa_hal_get_info(c, p, card);
1457 #endif
1458 }
1459
1460 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
1461
1462 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
1463 [SND_PCM_CLASS_GENERIC] = "generic",
1464 [SND_PCM_CLASS_MULTI] = "multi",
1465 [SND_PCM_CLASS_MODEM] = "modem",
1466 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
1467 };
1468 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
1469 [SND_PCM_CLASS_GENERIC] = "sound",
1470 [SND_PCM_CLASS_MULTI] = NULL,
1471 [SND_PCM_CLASS_MODEM] = "modem",
1472 [SND_PCM_CLASS_DIGITIZER] = NULL
1473 };
1474 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
1475 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
1476 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
1477 };
1478
1479 snd_pcm_class_t class;
1480 snd_pcm_subclass_t subclass;
1481 const char *n, *id, *sdn;
1482 int card;
1483
1484 pa_assert(p);
1485 pa_assert(pcm_info);
1486
1487 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
1488
1489 class = snd_pcm_info_get_class(pcm_info);
1490 if (class <= SND_PCM_CLASS_LAST) {
1491 if (class_table[class])
1492 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
1493 if (alsa_class_table[class])
1494 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
1495 }
1496
1497 subclass = snd_pcm_info_get_subclass(pcm_info);
1498 if (subclass <= SND_PCM_SUBCLASS_LAST)
1499 if (alsa_subclass_table[subclass])
1500 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
1501
1502 if ((n = snd_pcm_info_get_name(pcm_info)))
1503 pa_proplist_sets(p, "alsa.name", n);
1504
1505 if ((id = snd_pcm_info_get_id(pcm_info)))
1506 pa_proplist_sets(p, "alsa.id", id);
1507
1508 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
1509 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
1510 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
1511
1512 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
1513
1514 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
1515 pa_alsa_init_proplist_card(c, p, card);
1516 }
1517
1518 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm, snd_mixer_elem_t *elem) {
1519 snd_pcm_hw_params_t *hwparams;
1520 snd_pcm_info_t *info;
1521 int bits, err;
1522
1523 snd_pcm_hw_params_alloca(&hwparams);
1524 snd_pcm_info_alloca(&info);
1525
1526 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
1527 pa_log_warn("Error fetching hardware parameter info: %s", snd_strerror(err));
1528 else {
1529
1530 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
1531 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
1532 }
1533
1534 if (elem)
1535 pa_proplist_sets(p, "alsa.mixer_element", snd_mixer_selem_get_name(elem));
1536
1537 if ((err = snd_pcm_info(pcm, info)) < 0)
1538 pa_log_warn("Error fetching PCM info: %s", snd_strerror(err));
1539 else
1540 pa_alsa_init_proplist_pcm_info(c, p, info);
1541 }
1542
1543 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1544 snd_pcm_state_t state;
1545 int err;
1546
1547 pa_assert(pcm);
1548
1549 if (revents & POLLERR)
1550 pa_log_debug("Got POLLERR from ALSA");
1551 if (revents & POLLNVAL)
1552 pa_log_warn("Got POLLNVAL from ALSA");
1553 if (revents & POLLHUP)
1554 pa_log_warn("Got POLLHUP from ALSA");
1555 if (revents & POLLPRI)
1556 pa_log_warn("Got POLLPRI from ALSA");
1557 if (revents & POLLIN)
1558 pa_log_debug("Got POLLIN from ALSA");
1559 if (revents & POLLOUT)
1560 pa_log_debug("Got POLLOUT from ALSA");
1561
1562 state = snd_pcm_state(pcm);
1563 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1564
1565 /* Try to recover from this error */
1566
1567 switch (state) {
1568
1569 case SND_PCM_STATE_XRUN:
1570 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1571 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err));
1572 return -1;
1573 }
1574 break;
1575
1576 case SND_PCM_STATE_SUSPENDED:
1577 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1578 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err));
1579 return -1;
1580 }
1581 break;
1582
1583 default:
1584
1585 snd_pcm_drop(pcm);
1586
1587 if ((err = snd_pcm_prepare(pcm)) < 0) {
1588 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err));
1589 return -1;
1590 }
1591 break;
1592 }
1593
1594 return 0;
1595 }
1596
1597 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1598 int n, err;
1599 struct pollfd *pollfd;
1600 pa_rtpoll_item *item;
1601
1602 pa_assert(pcm);
1603
1604 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1605 pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n));
1606 return NULL;
1607 }
1608
1609 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1610 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1611
1612 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1613 pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
1614 pa_rtpoll_item_free(item);
1615 return NULL;
1616 }
1617
1618 return item;
1619 }
1620
1621 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1622 snd_pcm_sframes_t n;
1623 size_t k;
1624
1625 pa_assert(pcm);
1626 pa_assert(hwbuf_size > 0);
1627 pa_assert(ss);
1628
1629 /* Some ALSA driver expose weird bugs, let's inform the user about
1630 * what is going on */
1631
1632 n = snd_pcm_avail(pcm);
1633
1634 if (n <= 0)
1635 return n;
1636
1637 k = (size_t) n * pa_frame_size(ss);
1638
1639 if (k >= hwbuf_size * 5 ||
1640 k >= pa_bytes_per_second(ss)*10) {
1641
1642 PA_ONCE_BEGIN {
1643 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1644 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1645 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1646 (unsigned long) k,
1647 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1648 pa_strnull(dn));
1649 pa_xfree(dn);
1650 pa_alsa_dump(PA_LOG_ERROR, pcm);
1651 } PA_ONCE_END;
1652
1653 /* Mhmm, let's try not to fail completely */
1654 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1655 }
1656
1657 return n;
1658 }
1659
1660 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1661 ssize_t k;
1662 size_t abs_k;
1663 int r;
1664
1665 pa_assert(pcm);
1666 pa_assert(delay);
1667 pa_assert(hwbuf_size > 0);
1668 pa_assert(ss);
1669
1670 /* Some ALSA driver expose weird bugs, let's inform the user about
1671 * what is going on */
1672
1673 if ((r = snd_pcm_delay(pcm, delay)) < 0)
1674 return r;
1675
1676 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1677
1678 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1679
1680 if (abs_k >= hwbuf_size * 5 ||
1681 abs_k >= pa_bytes_per_second(ss)*10) {
1682
1683 PA_ONCE_BEGIN {
1684 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1685 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1686 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1687 (signed long) k,
1688 k < 0 ? "-" : "",
1689 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1690 pa_strnull(dn));
1691 pa_xfree(dn);
1692 pa_alsa_dump(PA_LOG_ERROR, pcm);
1693 } PA_ONCE_END;
1694
1695 /* Mhmm, let's try not to fail completely */
1696 if (k < 0)
1697 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1698 else
1699 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1700 }
1701
1702 return 0;
1703 }
1704
1705 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) {
1706 int r;
1707 snd_pcm_uframes_t before;
1708 size_t k;
1709
1710 pa_assert(pcm);
1711 pa_assert(areas);
1712 pa_assert(offset);
1713 pa_assert(frames);
1714 pa_assert(hwbuf_size > 0);
1715 pa_assert(ss);
1716
1717 before = *frames;
1718
1719 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1720
1721 if (r < 0)
1722 return r;
1723
1724 k = (size_t) *frames * pa_frame_size(ss);
1725
1726 if (*frames > before ||
1727 k >= hwbuf_size * 3 ||
1728 k >= pa_bytes_per_second(ss)*10)
1729
1730 PA_ONCE_BEGIN {
1731 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1732 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1733 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1734 (unsigned long) k,
1735 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1736 pa_strnull(dn));
1737 pa_xfree(dn);
1738 pa_alsa_dump(PA_LOG_ERROR, pcm);
1739 } PA_ONCE_END;
1740
1741 return r;
1742 }
1743
1744 char *pa_alsa_get_driver_name(int card) {
1745 char *t, *m, *n;
1746
1747 pa_assert(card >= 0);
1748
1749 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1750 m = pa_readlink(t);
1751 pa_xfree(t);
1752
1753 if (!m)
1754 return NULL;
1755
1756 n = pa_xstrdup(pa_path_get_filename(m));
1757 pa_xfree(m);
1758
1759 return n;
1760 }
1761
1762 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1763 int card;
1764 snd_pcm_info_t* info;
1765 snd_pcm_info_alloca(&info);
1766
1767 pa_assert(pcm);
1768
1769 if (snd_pcm_info(pcm, info) < 0)
1770 return NULL;
1771
1772 if ((card = snd_pcm_info_get_card(info)) < 0)
1773 return NULL;
1774
1775 return pa_alsa_get_driver_name(card);
1776 }
1777
1778 char *pa_alsa_get_reserve_name(const char *device) {
1779 const char *t;
1780 int i;
1781
1782 pa_assert(device);
1783
1784 if ((t = strchr(device, ':')))
1785 device = t+1;
1786
1787 if ((i = snd_card_get_index(device)) < 0) {
1788 int32_t k;
1789
1790 if (pa_atoi(device, &k) < 0)
1791 return NULL;
1792
1793 i = (int) k;
1794 }
1795
1796 return pa_sprintf_malloc("Audio%i", i);
1797 }
1798
1799 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1800 snd_pcm_info_t* info;
1801 snd_pcm_info_alloca(&info);
1802
1803 pa_assert(pcm);
1804
1805 if (snd_pcm_info(pcm, info) < 0)
1806 return FALSE;
1807
1808 return snd_pcm_info_get_card(info) >= 0;
1809 }
1810
1811 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1812 snd_pcm_info_t* info;
1813 snd_pcm_info_alloca(&info);
1814
1815 pa_assert(pcm);
1816
1817 if (snd_pcm_info(pcm, info) < 0)
1818 return FALSE;
1819
1820 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1821 }