alsa: disable timer-based scheduling inside a VM
[pulseaudio-mirror.git] / src / modules / alsa / alsa-util.c
blobb8d135758439bc18c80a2b245f69cb3e7a21df44
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <sys/types.h>
28 #include <limits.h>
29 #include <asoundlib.h>
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>
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 #include <pulsecore/core-rtclock.h>
48 #include "alsa-util.h"
49 #include "alsa-mixer.h"
51 #ifdef HAVE_HAL
52 #include "hal-util.h"
53 #endif
55 #ifdef HAVE_UDEV
56 #include "udev-util.h"
57 #endif
59 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
61 static const snd_pcm_format_t format_trans[] = {
62 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
63 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
64 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
65 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
66 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
67 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
68 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
69 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
70 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
71 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
72 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
73 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
74 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
77 static const pa_sample_format_t try_order[] = {
78 PA_SAMPLE_FLOAT32NE,
79 PA_SAMPLE_FLOAT32RE,
80 PA_SAMPLE_S32NE,
81 PA_SAMPLE_S32RE,
82 PA_SAMPLE_S24_32NE,
83 PA_SAMPLE_S24_32RE,
84 PA_SAMPLE_S24NE,
85 PA_SAMPLE_S24RE,
86 PA_SAMPLE_S16NE,
87 PA_SAMPLE_S16RE,
88 PA_SAMPLE_ALAW,
89 PA_SAMPLE_ULAW,
90 PA_SAMPLE_U8
93 unsigned i;
94 int ret;
96 pa_assert(pcm_handle);
97 pa_assert(hwparams);
98 pa_assert(f);
100 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
101 return ret;
103 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
104 snd_pcm_format_description(format_trans[*f]),
105 pa_alsa_strerror(ret));
107 if (*f == PA_SAMPLE_FLOAT32BE)
108 *f = PA_SAMPLE_FLOAT32LE;
109 else if (*f == PA_SAMPLE_FLOAT32LE)
110 *f = PA_SAMPLE_FLOAT32BE;
111 else if (*f == PA_SAMPLE_S24BE)
112 *f = PA_SAMPLE_S24LE;
113 else if (*f == PA_SAMPLE_S24LE)
114 *f = PA_SAMPLE_S24BE;
115 else if (*f == PA_SAMPLE_S24_32BE)
116 *f = PA_SAMPLE_S24_32LE;
117 else if (*f == PA_SAMPLE_S24_32LE)
118 *f = PA_SAMPLE_S24_32BE;
119 else if (*f == PA_SAMPLE_S16BE)
120 *f = PA_SAMPLE_S16LE;
121 else if (*f == PA_SAMPLE_S16LE)
122 *f = PA_SAMPLE_S16BE;
123 else if (*f == PA_SAMPLE_S32BE)
124 *f = PA_SAMPLE_S32LE;
125 else if (*f == PA_SAMPLE_S32LE)
126 *f = PA_SAMPLE_S32BE;
127 else
128 goto try_auto;
130 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
131 return ret;
133 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
134 snd_pcm_format_description(format_trans[*f]),
135 pa_alsa_strerror(ret));
137 try_auto:
139 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
140 *f = try_order[i];
142 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
143 return ret;
145 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
146 snd_pcm_format_description(format_trans[*f]),
147 pa_alsa_strerror(ret));
150 return -1;
153 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
154 snd_pcm_uframes_t s;
155 int d, ret;
157 pa_assert(pcm_handle);
158 pa_assert(hwparams);
160 s = size;
161 d = 0;
162 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
163 s = size;
164 d = -1;
165 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
166 s = size;
167 d = 1;
168 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
169 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
170 return ret;
175 return 0;
178 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
179 int ret;
181 pa_assert(pcm_handle);
182 pa_assert(hwparams);
184 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
185 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
186 return ret;
189 return 0;
192 /* Set the hardware parameters of the given ALSA device. Returns the
193 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
194 int pa_alsa_set_hw_params(
195 snd_pcm_t *pcm_handle,
196 pa_sample_spec *ss,
197 snd_pcm_uframes_t *period_size,
198 snd_pcm_uframes_t *buffer_size,
199 snd_pcm_uframes_t tsched_size,
200 pa_bool_t *use_mmap,
201 pa_bool_t *use_tsched,
202 pa_bool_t require_exact_channel_number) {
204 int ret = -1;
205 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
206 int dir;
207 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
208 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
209 pa_bool_t _use_mmap = use_mmap && *use_mmap;
210 pa_bool_t _use_tsched = use_tsched && *use_tsched;
211 pa_sample_spec _ss = *ss;
213 pa_assert(pcm_handle);
214 pa_assert(ss);
216 snd_pcm_hw_params_alloca(&hwparams);
217 snd_pcm_hw_params_alloca(&hwparams_copy);
219 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
220 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
221 goto finish;
224 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
225 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
226 goto finish;
229 if (_use_mmap) {
231 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
233 /* mmap() didn't work, fall back to interleaved */
235 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
236 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
237 goto finish;
240 _use_mmap = FALSE;
243 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
244 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
245 goto finish;
248 if (!_use_mmap)
249 _use_tsched = FALSE;
251 if (!pa_alsa_pcm_is_hw(pcm_handle))
252 _use_tsched = FALSE;
254 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
255 goto finish;
257 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
258 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
259 goto finish;
262 if (require_exact_channel_number) {
263 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
264 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
265 goto finish;
267 } else {
268 unsigned int c = _ss.channels;
270 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
271 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
272 goto finish;
275 _ss.channels = c;
278 if (_use_tsched && tsched_size > 0) {
279 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
280 _period_size = _buffer_size;
281 } else {
282 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
283 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
286 if (_buffer_size > 0 || _period_size > 0) {
287 snd_pcm_uframes_t max_frames = 0;
289 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
290 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
291 else
292 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
294 /* Some ALSA drivers really don't like if we set the buffer
295 * size first and the number of periods second. (which would
296 * make a lot more sense to me) So, try a few combinations
297 * before we give up. */
299 if (_buffer_size > 0 && _period_size > 0) {
300 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
302 /* First try: set buffer size first, followed by period size */
303 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
304 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
305 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
306 pa_log_debug("Set buffer size first, period size second.");
307 goto success;
310 /* Second try: set period size first, followed by buffer size */
311 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
312 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
313 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
314 pa_log_debug("Set period size first, buffer size second.");
315 goto success;
319 if (_buffer_size > 0) {
320 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
322 /* Third try: set only buffer size */
323 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
324 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
325 pa_log_debug("Set only buffer size second.");
326 goto success;
330 if (_period_size > 0) {
331 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
333 /* Fourth try: set only period size */
334 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
335 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
336 pa_log_debug("Set only period size second.");
337 goto success;
342 pa_log_debug("Set neither period nor buffer size.");
344 /* Last chance, set nothing */
345 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
346 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
347 goto finish;
350 success:
352 if (ss->rate != _ss.rate)
353 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
355 if (ss->channels != _ss.channels)
356 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
358 if (ss->format != _ss.format)
359 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(_ss.format));
361 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
362 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
363 goto finish;
366 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
367 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
368 goto finish;
371 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
372 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
373 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
374 goto finish;
377 /* If the sample rate deviates too much, we need to resample */
378 if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
379 ss->rate = _ss.rate;
380 ss->channels = _ss.channels;
381 ss->format = _ss.format;
383 pa_assert(_period_size > 0);
384 pa_assert(_buffer_size > 0);
386 if (buffer_size)
387 *buffer_size = _buffer_size;
389 if (period_size)
390 *period_size = _period_size;
392 if (use_mmap)
393 *use_mmap = _use_mmap;
395 if (use_tsched)
396 *use_tsched = _use_tsched;
398 ret = 0;
400 snd_pcm_nonblock(pcm_handle, 1);
402 finish:
404 return ret;
407 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, pa_bool_t period_event) {
408 snd_pcm_sw_params_t *swparams;
409 snd_pcm_uframes_t boundary;
410 int err;
412 pa_assert(pcm);
414 snd_pcm_sw_params_alloca(&swparams);
416 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
417 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
418 return err;
421 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
422 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
423 return err;
426 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
427 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
428 return err;
431 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
432 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
433 return err;
436 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
437 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
438 return err;
441 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
442 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
443 return err;
446 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
447 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
448 return err;
451 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
452 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
453 return err;
456 return 0;
459 snd_pcm_t *pa_alsa_open_by_device_id_auto(
460 const char *dev_id,
461 char **dev,
462 pa_sample_spec *ss,
463 pa_channel_map* map,
464 int mode,
465 snd_pcm_uframes_t *period_size,
466 snd_pcm_uframes_t *buffer_size,
467 snd_pcm_uframes_t tsched_size,
468 pa_bool_t *use_mmap,
469 pa_bool_t *use_tsched,
470 pa_alsa_profile_set *ps,
471 pa_alsa_mapping **mapping) {
473 char *d;
474 snd_pcm_t *pcm_handle;
475 void *state;
476 pa_alsa_mapping *m;
478 pa_assert(dev_id);
479 pa_assert(dev);
480 pa_assert(ss);
481 pa_assert(map);
482 pa_assert(ps);
484 /* First we try to find a device string with a superset of the
485 * requested channel map. We iterate through our device table from
486 * top to bottom and take the first that matches. If we didn't
487 * find a working device that way, we iterate backwards, and check
488 * all devices that do not provide a superset of the requested
489 * channel map.*/
491 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
492 if (!pa_channel_map_superset(&m->channel_map, map))
493 continue;
495 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
497 pcm_handle = pa_alsa_open_by_device_id_mapping(
498 dev_id,
499 dev,
501 map,
502 mode,
503 period_size,
504 buffer_size,
505 tsched_size,
506 use_mmap,
507 use_tsched,
510 if (pcm_handle) {
511 if (mapping)
512 *mapping = m;
514 return pcm_handle;
518 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
519 if (pa_channel_map_superset(&m->channel_map, map))
520 continue;
522 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
524 pcm_handle = pa_alsa_open_by_device_id_mapping(
525 dev_id,
526 dev,
528 map,
529 mode,
530 period_size,
531 buffer_size,
532 tsched_size,
533 use_mmap,
534 use_tsched,
537 if (pcm_handle) {
538 if (mapping)
539 *mapping = m;
541 return pcm_handle;
545 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
546 d = pa_sprintf_malloc("hw:%s", dev_id);
547 pa_log_debug("Trying %s as last resort...", d);
548 pcm_handle = pa_alsa_open_by_device_string(
550 dev,
552 map,
553 mode,
554 period_size,
555 buffer_size,
556 tsched_size,
557 use_mmap,
558 use_tsched,
559 FALSE);
560 pa_xfree(d);
562 if (pcm_handle && mapping)
563 *mapping = NULL;
565 return pcm_handle;
568 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
569 const char *dev_id,
570 char **dev,
571 pa_sample_spec *ss,
572 pa_channel_map* map,
573 int mode,
574 snd_pcm_uframes_t *period_size,
575 snd_pcm_uframes_t *buffer_size,
576 snd_pcm_uframes_t tsched_size,
577 pa_bool_t *use_mmap,
578 pa_bool_t *use_tsched,
579 pa_alsa_mapping *m) {
581 snd_pcm_t *pcm_handle;
582 pa_sample_spec try_ss;
583 pa_channel_map try_map;
585 pa_assert(dev_id);
586 pa_assert(dev);
587 pa_assert(ss);
588 pa_assert(map);
589 pa_assert(m);
591 try_ss.channels = m->channel_map.channels;
592 try_ss.rate = ss->rate;
593 try_ss.format = ss->format;
594 try_map = m->channel_map;
596 pcm_handle = pa_alsa_open_by_template(
597 m->device_strings,
598 dev_id,
599 dev,
600 &try_ss,
601 &try_map,
602 mode,
603 period_size,
604 buffer_size,
605 tsched_size,
606 use_mmap,
607 use_tsched,
608 TRUE);
610 if (!pcm_handle)
611 return NULL;
613 *ss = try_ss;
614 *map = try_map;
615 pa_assert(map->channels == ss->channels);
617 return pcm_handle;
620 snd_pcm_t *pa_alsa_open_by_device_string(
621 const char *device,
622 char **dev,
623 pa_sample_spec *ss,
624 pa_channel_map* map,
625 int mode,
626 snd_pcm_uframes_t *period_size,
627 snd_pcm_uframes_t *buffer_size,
628 snd_pcm_uframes_t tsched_size,
629 pa_bool_t *use_mmap,
630 pa_bool_t *use_tsched,
631 pa_bool_t require_exact_channel_number) {
633 int err;
634 char *d;
635 snd_pcm_t *pcm_handle;
636 pa_bool_t reformat = FALSE;
638 pa_assert(device);
639 pa_assert(ss);
640 pa_assert(map);
642 d = pa_xstrdup(device);
644 for (;;) {
645 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
647 if ((err = snd_pcm_open(&pcm_handle, d, mode,
648 SND_PCM_NONBLOCK|
649 SND_PCM_NO_AUTO_RESAMPLE|
650 SND_PCM_NO_AUTO_CHANNELS|
651 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
652 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
653 goto fail;
656 pa_log_debug("Managed to open %s", d);
658 if ((err = pa_alsa_set_hw_params(
659 pcm_handle,
661 period_size,
662 buffer_size,
663 tsched_size,
664 use_mmap,
665 use_tsched,
666 require_exact_channel_number)) < 0) {
668 if (!reformat) {
669 reformat = TRUE;
671 snd_pcm_close(pcm_handle);
672 continue;
675 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
676 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
677 char *t;
679 t = pa_sprintf_malloc("plug:%s", d);
680 pa_xfree(d);
681 d = t;
683 reformat = FALSE;
685 snd_pcm_close(pcm_handle);
686 continue;
689 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
690 snd_pcm_close(pcm_handle);
692 goto fail;
695 if (dev)
696 *dev = d;
697 else
698 pa_xfree(d);
700 if (ss->channels != map->channels)
701 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
703 return pcm_handle;
706 fail:
707 pa_xfree(d);
709 return NULL;
712 snd_pcm_t *pa_alsa_open_by_template(
713 char **template,
714 const char *dev_id,
715 char **dev,
716 pa_sample_spec *ss,
717 pa_channel_map* map,
718 int mode,
719 snd_pcm_uframes_t *period_size,
720 snd_pcm_uframes_t *buffer_size,
721 snd_pcm_uframes_t tsched_size,
722 pa_bool_t *use_mmap,
723 pa_bool_t *use_tsched,
724 pa_bool_t require_exact_channel_number) {
726 snd_pcm_t *pcm_handle;
727 char **i;
729 for (i = template; *i; i++) {
730 char *d;
732 d = pa_replace(*i, "%f", dev_id);
734 pcm_handle = pa_alsa_open_by_device_string(
736 dev,
738 map,
739 mode,
740 period_size,
741 buffer_size,
742 tsched_size,
743 use_mmap,
744 use_tsched,
745 require_exact_channel_number);
747 pa_xfree(d);
749 if (pcm_handle)
750 return pcm_handle;
753 return NULL;
756 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
757 int err;
758 snd_output_t *out;
760 pa_assert(pcm);
762 pa_assert_se(snd_output_buffer_open(&out) == 0);
764 if ((err = snd_pcm_dump(pcm, out)) < 0)
765 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
766 else {
767 char *s = NULL;
768 snd_output_buffer_string(out, &s);
769 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
772 pa_assert_se(snd_output_close(out) == 0);
775 void pa_alsa_dump_status(snd_pcm_t *pcm) {
776 int err;
777 snd_output_t *out;
778 snd_pcm_status_t *status;
779 char *s = NULL;
781 pa_assert(pcm);
783 snd_pcm_status_alloca(&status);
785 if ((err = snd_output_buffer_open(&out)) < 0) {
786 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
787 return;
790 if ((err = snd_pcm_status(pcm, status)) < 0) {
791 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
792 goto finish;
795 if ((err = snd_pcm_status_dump(status, out)) < 0) {
796 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
797 goto finish;
800 snd_output_buffer_string(out, &s);
801 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
803 finish:
805 snd_output_close(out);
808 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
809 va_list ap;
810 char *alsa_file;
812 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
814 va_start(ap, fmt);
816 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
818 va_end(ap);
820 pa_xfree(alsa_file);
823 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
825 void pa_alsa_refcnt_inc(void) {
826 /* This is not really thread safe, but we do our best */
828 if (pa_atomic_inc(&n_error_handler_installed) == 0)
829 snd_lib_error_set_handler(alsa_error_handler);
832 void pa_alsa_refcnt_dec(void) {
833 int r;
835 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
837 if (r == 1) {
838 snd_lib_error_set_handler(NULL);
839 snd_config_update_free_global();
843 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
844 const char *d, *k;
845 pa_assert(p);
847 if (pa_device_init_description(p))
848 return TRUE;
850 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
851 d = pa_proplist_gets(p, "alsa.name");
853 if (!d)
854 return FALSE;
856 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
858 if (d && k)
859 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k);
860 else if (d)
861 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
863 return FALSE;
866 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
867 char *cn, *lcn, *dn;
869 pa_assert(p);
870 pa_assert(card >= 0);
872 pa_proplist_setf(p, "alsa.card", "%i", card);
874 if (snd_card_get_name(card, &cn) >= 0) {
875 pa_proplist_sets(p, "alsa.card_name", cn);
876 free(cn);
879 if (snd_card_get_longname(card, &lcn) >= 0) {
880 pa_proplist_sets(p, "alsa.long_card_name", lcn);
881 free(lcn);
884 if ((dn = pa_alsa_get_driver_name(card))) {
885 pa_proplist_sets(p, "alsa.driver_name", dn);
886 pa_xfree(dn);
889 #ifdef HAVE_UDEV
890 pa_udev_get_info(card, p);
891 #endif
893 #ifdef HAVE_HAL
894 pa_hal_get_info(c, p, card);
895 #endif
898 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
900 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
901 [SND_PCM_CLASS_GENERIC] = "generic",
902 [SND_PCM_CLASS_MULTI] = "multi",
903 [SND_PCM_CLASS_MODEM] = "modem",
904 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
906 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
907 [SND_PCM_CLASS_GENERIC] = "sound",
908 [SND_PCM_CLASS_MULTI] = NULL,
909 [SND_PCM_CLASS_MODEM] = "modem",
910 [SND_PCM_CLASS_DIGITIZER] = NULL
912 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
913 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
914 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
917 snd_pcm_class_t class;
918 snd_pcm_subclass_t subclass;
919 const char *n, *id, *sdn;
920 int card;
922 pa_assert(p);
923 pa_assert(pcm_info);
925 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
927 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
928 if (class_table[class])
929 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
930 if (alsa_class_table[class])
931 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
934 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
935 if (alsa_subclass_table[subclass])
936 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
938 if ((n = snd_pcm_info_get_name(pcm_info)))
939 pa_proplist_sets(p, "alsa.name", n);
941 if ((id = snd_pcm_info_get_id(pcm_info)))
942 pa_proplist_sets(p, "alsa.id", id);
944 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
945 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
946 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
948 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
950 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
951 pa_alsa_init_proplist_card(c, p, card);
954 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
955 snd_pcm_hw_params_t *hwparams;
956 snd_pcm_info_t *info;
957 int bits, err;
959 snd_pcm_hw_params_alloca(&hwparams);
960 snd_pcm_info_alloca(&info);
962 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
963 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
964 else {
966 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
967 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
970 if ((err = snd_pcm_info(pcm, info)) < 0)
971 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
972 else
973 pa_alsa_init_proplist_pcm_info(c, p, info);
976 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
977 int err;
978 snd_ctl_t *ctl;
979 snd_ctl_card_info_t *info;
980 const char *t;
982 pa_assert(p);
984 snd_ctl_card_info_alloca(&info);
986 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
987 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
988 return;
991 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
992 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
993 snd_ctl_close(ctl);
994 return;
997 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
998 pa_proplist_sets(p, "alsa.mixer_name", t);
1000 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1001 pa_proplist_sets(p, "alsa.components", t);
1003 snd_ctl_close(ctl);
1006 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1007 snd_pcm_state_t state;
1008 int err;
1010 pa_assert(pcm);
1012 if (revents & POLLERR)
1013 pa_log_debug("Got POLLERR from ALSA");
1014 if (revents & POLLNVAL)
1015 pa_log_warn("Got POLLNVAL from ALSA");
1016 if (revents & POLLHUP)
1017 pa_log_warn("Got POLLHUP from ALSA");
1018 if (revents & POLLPRI)
1019 pa_log_warn("Got POLLPRI from ALSA");
1020 if (revents & POLLIN)
1021 pa_log_debug("Got POLLIN from ALSA");
1022 if (revents & POLLOUT)
1023 pa_log_debug("Got POLLOUT from ALSA");
1025 state = snd_pcm_state(pcm);
1026 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1028 /* Try to recover from this error */
1030 switch (state) {
1032 case SND_PCM_STATE_XRUN:
1033 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1034 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1035 return -1;
1037 break;
1039 case SND_PCM_STATE_SUSPENDED:
1040 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1041 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1042 return -1;
1044 break;
1046 default:
1048 snd_pcm_drop(pcm);
1050 if ((err = snd_pcm_prepare(pcm)) < 0) {
1051 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1052 return -1;
1054 break;
1057 return 0;
1060 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1061 int n, err;
1062 struct pollfd *pollfd;
1063 pa_rtpoll_item *item;
1065 pa_assert(pcm);
1067 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1068 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1069 return NULL;
1072 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1073 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1075 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1076 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1077 pa_rtpoll_item_free(item);
1078 return NULL;
1081 return item;
1084 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1085 snd_pcm_sframes_t n;
1086 size_t k;
1088 pa_assert(pcm);
1089 pa_assert(hwbuf_size > 0);
1090 pa_assert(ss);
1092 /* Some ALSA driver expose weird bugs, let's inform the user about
1093 * what is going on */
1095 n = snd_pcm_avail(pcm);
1097 if (n <= 0)
1098 return n;
1100 k = (size_t) n * pa_frame_size(ss);
1102 if (k >= hwbuf_size * 5 ||
1103 k >= pa_bytes_per_second(ss)*10) {
1105 PA_ONCE_BEGIN {
1106 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1107 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1108 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1109 (unsigned long) k,
1110 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1111 pa_strnull(dn));
1112 pa_xfree(dn);
1113 pa_alsa_dump(PA_LOG_ERROR, pcm);
1114 } PA_ONCE_END;
1116 /* Mhmm, let's try not to fail completely */
1117 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1120 return n;
1123 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1124 ssize_t k;
1125 size_t abs_k;
1126 int r;
1128 pa_assert(pcm);
1129 pa_assert(delay);
1130 pa_assert(hwbuf_size > 0);
1131 pa_assert(ss);
1133 /* Some ALSA driver expose weird bugs, let's inform the user about
1134 * what is going on */
1136 if ((r = snd_pcm_delay(pcm, delay)) < 0)
1137 return r;
1139 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1141 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1143 if (abs_k >= hwbuf_size * 5 ||
1144 abs_k >= pa_bytes_per_second(ss)*10) {
1146 PA_ONCE_BEGIN {
1147 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1148 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1149 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1150 (signed long) k,
1151 k < 0 ? "-" : "",
1152 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1153 pa_strnull(dn));
1154 pa_xfree(dn);
1155 pa_alsa_dump(PA_LOG_ERROR, pcm);
1156 } PA_ONCE_END;
1158 /* Mhmm, let's try not to fail completely */
1159 if (k < 0)
1160 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1161 else
1162 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1165 return 0;
1168 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) {
1169 int r;
1170 snd_pcm_uframes_t before;
1171 size_t k;
1173 pa_assert(pcm);
1174 pa_assert(areas);
1175 pa_assert(offset);
1176 pa_assert(frames);
1177 pa_assert(hwbuf_size > 0);
1178 pa_assert(ss);
1180 before = *frames;
1182 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1184 if (r < 0)
1185 return r;
1187 k = (size_t) *frames * pa_frame_size(ss);
1189 if (*frames > before ||
1190 k >= hwbuf_size * 3 ||
1191 k >= pa_bytes_per_second(ss)*10)
1193 PA_ONCE_BEGIN {
1194 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1195 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1196 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1197 (unsigned long) k,
1198 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1199 pa_strnull(dn));
1200 pa_xfree(dn);
1201 pa_alsa_dump(PA_LOG_ERROR, pcm);
1202 } PA_ONCE_END;
1204 return r;
1207 char *pa_alsa_get_driver_name(int card) {
1208 char *t, *m, *n;
1210 pa_assert(card >= 0);
1212 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1213 m = pa_readlink(t);
1214 pa_xfree(t);
1216 if (!m)
1217 return NULL;
1219 n = pa_xstrdup(pa_path_get_filename(m));
1220 pa_xfree(m);
1222 return n;
1225 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1226 int card;
1227 snd_pcm_info_t* info;
1228 snd_pcm_info_alloca(&info);
1230 pa_assert(pcm);
1232 if (snd_pcm_info(pcm, info) < 0)
1233 return NULL;
1235 if ((card = snd_pcm_info_get_card(info)) < 0)
1236 return NULL;
1238 return pa_alsa_get_driver_name(card);
1241 char *pa_alsa_get_reserve_name(const char *device) {
1242 const char *t;
1243 int i;
1245 pa_assert(device);
1247 if ((t = strchr(device, ':')))
1248 device = t+1;
1250 if ((i = snd_card_get_index(device)) < 0) {
1251 int32_t k;
1253 if (pa_atoi(device, &k) < 0)
1254 return NULL;
1256 i = (int) k;
1259 return pa_sprintf_malloc("Audio%i", i);
1262 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1263 snd_pcm_info_t* info;
1264 snd_pcm_info_alloca(&info);
1266 pa_assert(pcm);
1268 if (snd_pcm_info(pcm, info) < 0)
1269 return FALSE;
1271 return snd_pcm_info_get_card(info) >= 0;
1274 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1275 snd_pcm_info_t* info;
1276 snd_pcm_info_alloca(&info);
1278 pa_assert(pcm);
1280 if (snd_pcm_info(pcm, info) < 0)
1281 return FALSE;
1283 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1286 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1288 const char* pa_alsa_strerror(int errnum) {
1289 const char *original = NULL;
1290 char *translated, *t;
1291 char errbuf[128];
1293 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1294 pa_xfree(t);
1296 original = snd_strerror(errnum);
1298 if (!original) {
1299 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1300 original = errbuf;
1303 if (!(translated = pa_locale_to_utf8(original))) {
1304 pa_log_warn("Unable to convert error string to locale, filtering.");
1305 translated = pa_utf8_filter(original);
1308 PA_STATIC_TLS_SET(cstrerror, translated);
1310 return translated;
1313 pa_bool_t pa_alsa_may_tsched(pa_bool_t want) {
1315 if (!want)
1316 return FALSE;
1318 if (!pa_rtclock_hrtimer()) {
1319 /* We cannot depend on being woken up in time when the timers
1320 are inaccurate, so let's fallback to classic IO based playback
1321 then. */
1322 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1323 return FALSE; }
1325 if (pa_running_in_vm()) {
1326 /* We cannot depend on being woken up when we ask for in a VM,
1327 * so let's fallback to classic IO based playback then. */
1328 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1329 return FALSE;
1333 return TRUE;