]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
Merge commit 'origin/master-tx'
[pulseaudio] / src / modules / alsa / alsa-util.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <sys/types.h>
28 #include <limits.h>
29 #include <asoundlib.h>
30
31 #include <pulse/sample.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/i18n.h>
36 #include <pulse/utf8.h>
37
38 #include <pulsecore/log.h>
39 #include <pulsecore/macro.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/atomic.h>
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/once.h>
44 #include <pulsecore/thread.h>
45 #include <pulsecore/conf-parser.h>
46
47 #include "alsa-util.h"
48 #include "alsa-mixer.h"
49
50 #ifdef HAVE_HAL
51 #include "hal-util.h"
52 #endif
53
54 #ifdef HAVE_UDEV
55 #include "udev-util.h"
56 #endif
57
58 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
59
60 static const snd_pcm_format_t format_trans[] = {
61 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
62 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
63 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
64 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
65 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
66 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
67 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
68 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
69 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
70 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
71 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
72 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
73 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
74 };
75
76 static const pa_sample_format_t try_order[] = {
77 PA_SAMPLE_FLOAT32NE,
78 PA_SAMPLE_FLOAT32RE,
79 PA_SAMPLE_S32NE,
80 PA_SAMPLE_S32RE,
81 PA_SAMPLE_S24_32NE,
82 PA_SAMPLE_S24_32RE,
83 PA_SAMPLE_S24NE,
84 PA_SAMPLE_S24RE,
85 PA_SAMPLE_S16NE,
86 PA_SAMPLE_S16RE,
87 PA_SAMPLE_ALAW,
88 PA_SAMPLE_ULAW,
89 PA_SAMPLE_U8
90 };
91
92 unsigned i;
93 int ret;
94
95 pa_assert(pcm_handle);
96 pa_assert(f);
97
98 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
99 return ret;
100
101 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
102 snd_pcm_format_description(format_trans[*f]),
103 pa_alsa_strerror(ret));
104
105 if (*f == PA_SAMPLE_FLOAT32BE)
106 *f = PA_SAMPLE_FLOAT32LE;
107 else if (*f == PA_SAMPLE_FLOAT32LE)
108 *f = PA_SAMPLE_FLOAT32BE;
109 else if (*f == PA_SAMPLE_S24BE)
110 *f = PA_SAMPLE_S24LE;
111 else if (*f == PA_SAMPLE_S24LE)
112 *f = PA_SAMPLE_S24BE;
113 else if (*f == PA_SAMPLE_S24_32BE)
114 *f = PA_SAMPLE_S24_32LE;
115 else if (*f == PA_SAMPLE_S24_32LE)
116 *f = PA_SAMPLE_S24_32BE;
117 else if (*f == PA_SAMPLE_S16BE)
118 *f = PA_SAMPLE_S16LE;
119 else if (*f == PA_SAMPLE_S16LE)
120 *f = PA_SAMPLE_S16BE;
121 else if (*f == PA_SAMPLE_S32BE)
122 *f = PA_SAMPLE_S32LE;
123 else if (*f == PA_SAMPLE_S32LE)
124 *f = PA_SAMPLE_S32BE;
125 else
126 goto try_auto;
127
128 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
129 return ret;
130
131 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
132 snd_pcm_format_description(format_trans[*f]),
133 pa_alsa_strerror(ret));
134
135 try_auto:
136
137 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
138 *f = try_order[i];
139
140 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
141 return ret;
142
143 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
144 snd_pcm_format_description(format_trans[*f]),
145 pa_alsa_strerror(ret));
146 }
147
148 return -1;
149 }
150
151 /* Set the hardware parameters of the given ALSA device. Returns the
152 * selected fragment settings in *period and *period_size */
153 int pa_alsa_set_hw_params(
154 snd_pcm_t *pcm_handle,
155 pa_sample_spec *ss,
156 uint32_t *periods,
157 snd_pcm_uframes_t *period_size,
158 snd_pcm_uframes_t tsched_size,
159 pa_bool_t *use_mmap,
160 pa_bool_t *use_tsched,
161 pa_bool_t require_exact_channel_number) {
162
163 int ret = -1;
164 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
165 unsigned int _periods = periods ? *periods : 0;
166 unsigned int r = ss->rate;
167 unsigned int c = ss->channels;
168 pa_sample_format_t f = ss->format;
169 snd_pcm_hw_params_t *hwparams;
170 pa_bool_t _use_mmap = use_mmap && *use_mmap;
171 pa_bool_t _use_tsched = use_tsched && *use_tsched;
172 int dir;
173
174 pa_assert(pcm_handle);
175 pa_assert(ss);
176
177 snd_pcm_hw_params_alloca(&hwparams);
178
179 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
180 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
181 goto finish;
182 }
183
184 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
185 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
186 goto finish;
187 }
188
189 if (_use_mmap) {
190
191 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
192
193 /* mmap() didn't work, fall back to interleaved */
194
195 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
196 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
197 goto finish;
198 }
199
200 _use_mmap = FALSE;
201 }
202
203 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
204 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
205 goto finish;
206 }
207
208 if (!_use_mmap)
209 _use_tsched = FALSE;
210
211 if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
212 goto finish;
213
214 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) {
215 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
216 goto finish;
217 }
218
219 if (require_exact_channel_number) {
220 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) {
221 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", c, pa_alsa_strerror(ret));
222 goto finish;
223 }
224 } else {
225 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
226 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", c, pa_alsa_strerror(ret));
227 goto finish;
228 }
229 }
230
231 if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0) {
232 pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret));
233 goto finish;
234 }
235
236 if (_period_size > 0 && tsched_size > 0 && _periods > 0) {
237 snd_pcm_uframes_t buffer_size;
238 unsigned int p;
239
240 /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
241 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
242 tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
243
244 if (_use_tsched) {
245 buffer_size = 0;
246
247 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size)) < 0)
248 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
249 else
250 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
251
252 _period_size = tsched_size;
253 _periods = 1;
254 }
255
256 /* Some ALSA drivers really don't like if we set the buffer
257 * size first and the number of periods second. (which would
258 * make a lot more sense to me) So, follow this rule and
259 * adjust the periods first and the buffer size second */
260
261 /* First we pass 0 as direction to get exactly what we
262 * asked for. That this is necessary is presumably a bug
263 * in ALSA. All in all this is mostly a hint to ALSA, so
264 * we don't care if this fails. */
265
266 p = _periods;
267 dir = 0;
268 if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
269 p = _periods;
270 dir = 1;
271 if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir) < 0) {
272 p = _periods;
273 dir = -1;
274 if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &p, &dir)) < 0)
275 pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret));
276 }
277 }
278
279 /* Now set the buffer size */
280 buffer_size = _periods * _period_size;
281 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
282 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
283 }
284
285 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
286 goto finish;
287
288 if (ss->rate != r)
289 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
290
291 if (ss->channels != c)
292 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
293
294 if (ss->format != f)
295 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));
296
297 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
298 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
299 goto finish;
300 }
301
302 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
303 (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0) {
304 pa_log_info("snd_pcm_hw_params_get_period{s|_size}() failed: %s", pa_alsa_strerror(ret));
305 goto finish;
306 }
307
308 /* If the sample rate deviates too much, we need to resample */
309 if (r < ss->rate*.95 || r > ss->rate*1.05)
310 ss->rate = r;
311 ss->channels = (uint8_t) c;
312 ss->format = f;
313
314 pa_assert(_periods > 0);
315 pa_assert(_period_size > 0);
316
317 if (periods)
318 *periods = _periods;
319
320 if (period_size)
321 *period_size = _period_size;
322
323 if (use_mmap)
324 *use_mmap = _use_mmap;
325
326 if (use_tsched)
327 *use_tsched = _use_tsched;
328
329 ret = 0;
330
331 snd_pcm_nonblock(pcm_handle, 1);
332
333 finish:
334
335 return ret;
336 }
337
338 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
339 snd_pcm_sw_params_t *swparams;
340 snd_pcm_uframes_t boundary;
341 int err;
342
343 pa_assert(pcm);
344
345 snd_pcm_sw_params_alloca(&swparams);
346
347 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
348 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
349 return err;
350 }
351
352 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, 0)) < 0) {
353 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
354 return err;
355 }
356
357 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
358 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
359 return err;
360 }
361
362 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
363 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
364 return err;
365 }
366
367 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
368 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
369 return err;
370 }
371
372 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
373 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
374 return err;
375 }
376
377 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
378 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
379 return err;
380 }
381
382 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
383 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
384 return err;
385 }
386
387 return 0;
388 }
389
390 snd_pcm_t *pa_alsa_open_by_device_id_auto(
391 const char *dev_id,
392 char **dev,
393 pa_sample_spec *ss,
394 pa_channel_map* map,
395 int mode,
396 uint32_t *nfrags,
397 snd_pcm_uframes_t *period_size,
398 snd_pcm_uframes_t tsched_size,
399 pa_bool_t *use_mmap,
400 pa_bool_t *use_tsched,
401 pa_alsa_profile_set *ps,
402 pa_alsa_mapping **mapping) {
403
404 char *d;
405 snd_pcm_t *pcm_handle;
406 void *state;
407 pa_alsa_mapping *m;
408
409 pa_assert(dev_id);
410 pa_assert(dev);
411 pa_assert(ss);
412 pa_assert(map);
413 pa_assert(nfrags);
414 pa_assert(period_size);
415 pa_assert(ps);
416
417 /* First we try to find a device string with a superset of the
418 * requested channel map. We iterate through our device table from
419 * top to bottom and take the first that matches. If we didn't
420 * find a working device that way, we iterate backwards, and check
421 * all devices that do not provide a superset of the requested
422 * channel map.*/
423
424 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
425 if (!pa_channel_map_superset(&m->channel_map, map))
426 continue;
427
428 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
429
430 pcm_handle = pa_alsa_open_by_device_id_mapping(
431 dev_id,
432 dev,
433 ss,
434 map,
435 mode,
436 nfrags,
437 period_size,
438 tsched_size,
439 use_mmap,
440 use_tsched,
441 m);
442
443 if (pcm_handle) {
444 if (mapping)
445 *mapping = m;
446
447 return pcm_handle;
448 }
449 }
450
451 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
452 if (pa_channel_map_superset(&m->channel_map, map))
453 continue;
454
455 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
456
457 pcm_handle = pa_alsa_open_by_device_id_mapping(
458 dev_id,
459 dev,
460 ss,
461 map,
462 mode,
463 nfrags,
464 period_size,
465 tsched_size,
466 use_mmap,
467 use_tsched,
468 m);
469
470 if (pcm_handle) {
471 if (mapping)
472 *mapping = m;
473
474 return pcm_handle;
475 }
476 }
477
478 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
479 d = pa_sprintf_malloc("hw:%s", dev_id);
480 pa_log_debug("Trying %s as last resort...", d);
481 pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
482 pa_xfree(d);
483
484 if (pcm_handle && mapping)
485 *mapping = NULL;
486
487 return pcm_handle;
488 }
489
490 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
491 const char *dev_id,
492 char **dev,
493 pa_sample_spec *ss,
494 pa_channel_map* map,
495 int mode,
496 uint32_t *nfrags,
497 snd_pcm_uframes_t *period_size,
498 snd_pcm_uframes_t tsched_size,
499 pa_bool_t *use_mmap,
500 pa_bool_t *use_tsched,
501 pa_alsa_mapping *m) {
502
503 snd_pcm_t *pcm_handle;
504 pa_sample_spec try_ss;
505 pa_channel_map try_map;
506
507 pa_assert(dev_id);
508 pa_assert(dev);
509 pa_assert(ss);
510 pa_assert(map);
511 pa_assert(nfrags);
512 pa_assert(period_size);
513 pa_assert(m);
514
515 try_ss.channels = m->channel_map.channels;
516 try_ss.rate = ss->rate;
517 try_ss.format = ss->format;
518 try_map = m->channel_map;
519
520 pcm_handle = pa_alsa_open_by_template(
521 m->device_strings,
522 dev_id,
523 dev,
524 &try_ss,
525 &try_map,
526 mode,
527 nfrags,
528 period_size,
529 tsched_size,
530 use_mmap,
531 use_tsched,
532 TRUE);
533
534 if (!pcm_handle)
535 return NULL;
536
537 *ss = try_ss;
538 *map = try_map;
539 pa_assert(map->channels == ss->channels);
540
541 return pcm_handle;
542 }
543
544 snd_pcm_t *pa_alsa_open_by_device_string(
545 const char *device,
546 char **dev,
547 pa_sample_spec *ss,
548 pa_channel_map* map,
549 int mode,
550 uint32_t *nfrags,
551 snd_pcm_uframes_t *period_size,
552 snd_pcm_uframes_t tsched_size,
553 pa_bool_t *use_mmap,
554 pa_bool_t *use_tsched,
555 pa_bool_t require_exact_channel_number) {
556
557 int err;
558 char *d;
559 snd_pcm_t *pcm_handle;
560 pa_bool_t reformat = FALSE;
561
562 pa_assert(device);
563 pa_assert(ss);
564 pa_assert(map);
565
566 d = pa_xstrdup(device);
567
568 for (;;) {
569 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
570
571 if ((err = snd_pcm_open(&pcm_handle, d, mode,
572 SND_PCM_NONBLOCK|
573 SND_PCM_NO_AUTO_RESAMPLE|
574 SND_PCM_NO_AUTO_CHANNELS|
575 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
576 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
577 goto fail;
578 }
579
580 pa_log_debug("Managed to open %s", d);
581
582 if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
583
584 if (!reformat) {
585 reformat = TRUE;
586
587 snd_pcm_close(pcm_handle);
588 continue;
589 }
590
591 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
592 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
593 char *t;
594
595 t = pa_sprintf_malloc("plug:%s", d);
596 pa_xfree(d);
597 d = t;
598
599 reformat = FALSE;
600
601 snd_pcm_close(pcm_handle);
602 continue;
603 }
604
605 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
606 snd_pcm_close(pcm_handle);
607
608 goto fail;
609 }
610
611 if (dev)
612 *dev = d;
613 else
614 pa_xfree(d);
615
616 if (ss->channels != map->channels)
617 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
618
619 return pcm_handle;
620 }
621
622 fail:
623 pa_xfree(d);
624
625 return NULL;
626 }
627
628 snd_pcm_t *pa_alsa_open_by_template(
629 char **template,
630 const char *dev_id,
631 char **dev,
632 pa_sample_spec *ss,
633 pa_channel_map* map,
634 int mode,
635 uint32_t *nfrags,
636 snd_pcm_uframes_t *period_size,
637 snd_pcm_uframes_t tsched_size,
638 pa_bool_t *use_mmap,
639 pa_bool_t *use_tsched,
640 pa_bool_t require_exact_channel_number) {
641
642 snd_pcm_t *pcm_handle;
643 char **i;
644
645 for (i = template; *i; i++) {
646 char *d;
647
648 d = pa_replace(*i, "%f", dev_id);
649
650 pcm_handle = pa_alsa_open_by_device_string(
651 d,
652 dev,
653 ss,
654 map,
655 mode,
656 nfrags,
657 period_size,
658 tsched_size,
659 use_mmap,
660 use_tsched,
661 require_exact_channel_number);
662
663 pa_xfree(d);
664
665 if (pcm_handle)
666 return pcm_handle;
667 }
668
669 return NULL;
670 }
671
672 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
673 int err;
674 snd_output_t *out;
675
676 pa_assert(pcm);
677
678 pa_assert_se(snd_output_buffer_open(&out) == 0);
679
680 if ((err = snd_pcm_dump(pcm, out)) < 0)
681 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
682 else {
683 char *s = NULL;
684 snd_output_buffer_string(out, &s);
685 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
686 }
687
688 pa_assert_se(snd_output_close(out) == 0);
689 }
690
691 void pa_alsa_dump_status(snd_pcm_t *pcm) {
692 int err;
693 snd_output_t *out;
694 snd_pcm_status_t *status;
695 char *s = NULL;
696
697 pa_assert(pcm);
698
699 snd_pcm_status_alloca(&status);
700
701 if ((err = snd_output_buffer_open(&out)) < 0) {
702 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
703 return;
704 }
705
706 if ((err = snd_pcm_status(pcm, status)) < 0) {
707 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
708 goto finish;
709 }
710
711 if ((err = snd_pcm_status_dump(status, out)) < 0) {
712 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
713 goto finish;
714 }
715
716 snd_output_buffer_string(out, &s);
717 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
718
719 finish:
720
721 snd_output_close(out);
722 }
723
724 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
725 va_list ap;
726 char *alsa_file;
727
728 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
729
730 va_start(ap, fmt);
731
732 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
733
734 va_end(ap);
735
736 pa_xfree(alsa_file);
737 }
738
739 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
740
741 void pa_alsa_refcnt_inc(void) {
742 /* This is not really thread safe, but we do our best */
743
744 if (pa_atomic_inc(&n_error_handler_installed) == 0)
745 snd_lib_error_set_handler(alsa_error_handler);
746 }
747
748 void pa_alsa_refcnt_dec(void) {
749 int r;
750
751 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
752
753 if (r == 1) {
754 snd_lib_error_set_handler(NULL);
755 snd_config_update_free_global();
756 }
757 }
758
759 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
760 const char *d, *k;
761 pa_assert(p);
762
763 if (pa_device_init_description(p))
764 return TRUE;
765
766 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
767 d = pa_proplist_gets(p, "alsa.name");
768
769 if (!d)
770 return FALSE;
771
772 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
773
774 if (d && k)
775 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k);
776 else if (d)
777 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
778
779 return FALSE;
780 }
781
782 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
783 char *cn, *lcn, *dn;
784
785 pa_assert(p);
786 pa_assert(card >= 0);
787
788 pa_proplist_setf(p, "alsa.card", "%i", card);
789
790 if (snd_card_get_name(card, &cn) >= 0) {
791 pa_proplist_sets(p, "alsa.card_name", cn);
792 free(cn);
793 }
794
795 if (snd_card_get_longname(card, &lcn) >= 0) {
796 pa_proplist_sets(p, "alsa.long_card_name", lcn);
797 free(lcn);
798 }
799
800 if ((dn = pa_alsa_get_driver_name(card))) {
801 pa_proplist_sets(p, "alsa.driver_name", dn);
802 pa_xfree(dn);
803 }
804
805 #ifdef HAVE_UDEV
806 pa_udev_get_info(card, p);
807 #endif
808
809 #ifdef HAVE_HAL
810 pa_hal_get_info(c, p, card);
811 #endif
812 }
813
814 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
815
816 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
817 [SND_PCM_CLASS_GENERIC] = "generic",
818 [SND_PCM_CLASS_MULTI] = "multi",
819 [SND_PCM_CLASS_MODEM] = "modem",
820 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
821 };
822 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
823 [SND_PCM_CLASS_GENERIC] = "sound",
824 [SND_PCM_CLASS_MULTI] = NULL,
825 [SND_PCM_CLASS_MODEM] = "modem",
826 [SND_PCM_CLASS_DIGITIZER] = NULL
827 };
828 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
829 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
830 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
831 };
832
833 snd_pcm_class_t class;
834 snd_pcm_subclass_t subclass;
835 const char *n, *id, *sdn;
836 int card;
837
838 pa_assert(p);
839 pa_assert(pcm_info);
840
841 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
842
843 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
844 if (class_table[class])
845 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
846 if (alsa_class_table[class])
847 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
848 }
849
850 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
851 if (alsa_subclass_table[subclass])
852 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
853
854 if ((n = snd_pcm_info_get_name(pcm_info)))
855 pa_proplist_sets(p, "alsa.name", n);
856
857 if ((id = snd_pcm_info_get_id(pcm_info)))
858 pa_proplist_sets(p, "alsa.id", id);
859
860 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
861 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
862 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
863
864 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
865
866 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
867 pa_alsa_init_proplist_card(c, p, card);
868 }
869
870 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
871 snd_pcm_hw_params_t *hwparams;
872 snd_pcm_info_t *info;
873 int bits, err;
874
875 snd_pcm_hw_params_alloca(&hwparams);
876 snd_pcm_info_alloca(&info);
877
878 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
879 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
880 else {
881
882 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
883 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
884 }
885
886 if ((err = snd_pcm_info(pcm, info)) < 0)
887 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
888 else
889 pa_alsa_init_proplist_pcm_info(c, p, info);
890 }
891
892 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
893 int err;
894 snd_ctl_t *ctl;
895 snd_ctl_card_info_t *info;
896 const char *t;
897
898 pa_assert(p);
899
900 snd_ctl_card_info_alloca(&info);
901
902 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
903 pa_log_warn("Error opening low-level control device '%s'", name);
904 return;
905 }
906
907 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
908 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
909 snd_ctl_close(ctl);
910 return;
911 }
912
913 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
914 pa_proplist_sets(p, "alsa.mixer_name", t);
915
916 if ((t = snd_ctl_card_info_get_components(info)) && *t)
917 pa_proplist_sets(p, "alsa.components", t);
918
919 snd_ctl_close(ctl);
920 }
921
922 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
923 snd_pcm_state_t state;
924 int err;
925
926 pa_assert(pcm);
927
928 if (revents & POLLERR)
929 pa_log_debug("Got POLLERR from ALSA");
930 if (revents & POLLNVAL)
931 pa_log_warn("Got POLLNVAL from ALSA");
932 if (revents & POLLHUP)
933 pa_log_warn("Got POLLHUP from ALSA");
934 if (revents & POLLPRI)
935 pa_log_warn("Got POLLPRI from ALSA");
936 if (revents & POLLIN)
937 pa_log_debug("Got POLLIN from ALSA");
938 if (revents & POLLOUT)
939 pa_log_debug("Got POLLOUT from ALSA");
940
941 state = snd_pcm_state(pcm);
942 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
943
944 /* Try to recover from this error */
945
946 switch (state) {
947
948 case SND_PCM_STATE_XRUN:
949 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
950 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
951 return -1;
952 }
953 break;
954
955 case SND_PCM_STATE_SUSPENDED:
956 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
957 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
958 return -1;
959 }
960 break;
961
962 default:
963
964 snd_pcm_drop(pcm);
965
966 if ((err = snd_pcm_prepare(pcm)) < 0) {
967 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
968 return -1;
969 }
970 break;
971 }
972
973 return 0;
974 }
975
976 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
977 int n, err;
978 struct pollfd *pollfd;
979 pa_rtpoll_item *item;
980
981 pa_assert(pcm);
982
983 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
984 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
985 return NULL;
986 }
987
988 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
989 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
990
991 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
992 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
993 pa_rtpoll_item_free(item);
994 return NULL;
995 }
996
997 return item;
998 }
999
1000 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1001 snd_pcm_sframes_t n;
1002 size_t k;
1003
1004 pa_assert(pcm);
1005 pa_assert(hwbuf_size > 0);
1006 pa_assert(ss);
1007
1008 /* Some ALSA driver expose weird bugs, let's inform the user about
1009 * what is going on */
1010
1011 n = snd_pcm_avail(pcm);
1012
1013 if (n <= 0)
1014 return n;
1015
1016 k = (size_t) n * pa_frame_size(ss);
1017
1018 if (k >= hwbuf_size * 5 ||
1019 k >= pa_bytes_per_second(ss)*10) {
1020
1021 PA_ONCE_BEGIN {
1022 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1023 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1024 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1025 (unsigned long) k,
1026 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1027 pa_strnull(dn));
1028 pa_xfree(dn);
1029 pa_alsa_dump(PA_LOG_ERROR, pcm);
1030 } PA_ONCE_END;
1031
1032 /* Mhmm, let's try not to fail completely */
1033 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1034 }
1035
1036 return n;
1037 }
1038
1039 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1040 ssize_t k;
1041 size_t abs_k;
1042 int r;
1043
1044 pa_assert(pcm);
1045 pa_assert(delay);
1046 pa_assert(hwbuf_size > 0);
1047 pa_assert(ss);
1048
1049 /* Some ALSA driver expose weird bugs, let's inform the user about
1050 * what is going on */
1051
1052 if ((r = snd_pcm_delay(pcm, delay)) < 0)
1053 return r;
1054
1055 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1056
1057 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1058
1059 if (abs_k >= hwbuf_size * 5 ||
1060 abs_k >= pa_bytes_per_second(ss)*10) {
1061
1062 PA_ONCE_BEGIN {
1063 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1064 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1065 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1066 (signed long) k,
1067 k < 0 ? "-" : "",
1068 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1069 pa_strnull(dn));
1070 pa_xfree(dn);
1071 pa_alsa_dump(PA_LOG_ERROR, pcm);
1072 } PA_ONCE_END;
1073
1074 /* Mhmm, let's try not to fail completely */
1075 if (k < 0)
1076 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1077 else
1078 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1079 }
1080
1081 return 0;
1082 }
1083
1084 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) {
1085 int r;
1086 snd_pcm_uframes_t before;
1087 size_t k;
1088
1089 pa_assert(pcm);
1090 pa_assert(areas);
1091 pa_assert(offset);
1092 pa_assert(frames);
1093 pa_assert(hwbuf_size > 0);
1094 pa_assert(ss);
1095
1096 before = *frames;
1097
1098 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1099
1100 if (r < 0)
1101 return r;
1102
1103 k = (size_t) *frames * pa_frame_size(ss);
1104
1105 if (*frames > before ||
1106 k >= hwbuf_size * 3 ||
1107 k >= pa_bytes_per_second(ss)*10)
1108
1109 PA_ONCE_BEGIN {
1110 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1111 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1112 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1113 (unsigned long) k,
1114 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1115 pa_strnull(dn));
1116 pa_xfree(dn);
1117 pa_alsa_dump(PA_LOG_ERROR, pcm);
1118 } PA_ONCE_END;
1119
1120 return r;
1121 }
1122
1123 char *pa_alsa_get_driver_name(int card) {
1124 char *t, *m, *n;
1125
1126 pa_assert(card >= 0);
1127
1128 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1129 m = pa_readlink(t);
1130 pa_xfree(t);
1131
1132 if (!m)
1133 return NULL;
1134
1135 n = pa_xstrdup(pa_path_get_filename(m));
1136 pa_xfree(m);
1137
1138 return n;
1139 }
1140
1141 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1142 int card;
1143 snd_pcm_info_t* info;
1144 snd_pcm_info_alloca(&info);
1145
1146 pa_assert(pcm);
1147
1148 if (snd_pcm_info(pcm, info) < 0)
1149 return NULL;
1150
1151 if ((card = snd_pcm_info_get_card(info)) < 0)
1152 return NULL;
1153
1154 return pa_alsa_get_driver_name(card);
1155 }
1156
1157 char *pa_alsa_get_reserve_name(const char *device) {
1158 const char *t;
1159 int i;
1160
1161 pa_assert(device);
1162
1163 if ((t = strchr(device, ':')))
1164 device = t+1;
1165
1166 if ((i = snd_card_get_index(device)) < 0) {
1167 int32_t k;
1168
1169 if (pa_atoi(device, &k) < 0)
1170 return NULL;
1171
1172 i = (int) k;
1173 }
1174
1175 return pa_sprintf_malloc("Audio%i", i);
1176 }
1177
1178 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1179 snd_pcm_info_t* info;
1180 snd_pcm_info_alloca(&info);
1181
1182 pa_assert(pcm);
1183
1184 if (snd_pcm_info(pcm, info) < 0)
1185 return FALSE;
1186
1187 return snd_pcm_info_get_card(info) >= 0;
1188 }
1189
1190 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1191 snd_pcm_info_t* info;
1192 snd_pcm_info_alloca(&info);
1193
1194 pa_assert(pcm);
1195
1196 if (snd_pcm_info(pcm, info) < 0)
1197 return FALSE;
1198
1199 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1200 }
1201
1202 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1203
1204 const char* pa_alsa_strerror(int errnum) {
1205 const char *original = NULL;
1206 char *translated, *t;
1207 char errbuf[128];
1208
1209 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1210 pa_xfree(t);
1211
1212 original = snd_strerror(errnum);
1213
1214 if (!original) {
1215 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1216 original = errbuf;
1217 }
1218
1219 if (!(translated = pa_locale_to_utf8(original))) {
1220 pa_log_warn("Unable to convert error string to locale, filtering.");
1221 translated = pa_utf8_filter(original);
1222 }
1223
1224 PA_STATIC_TLS_SET(cstrerror, translated);
1225
1226 return translated;
1227 }