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
27 #include <sys/types.h>
28 #include <asoundlib.h>
30 #include <pulse/sample.h>
31 #include <pulse/xmalloc.h>
32 #include <pulse/timeval.h>
33 #include <pulse/util.h>
34 #include <pulse/utf8.h>
36 #include <pulsecore/i18n.h>
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/thread.h>
43 #include <pulsecore/conf-parser.h>
44 #include <pulsecore/core-rtclock.h>
46 #include "alsa-util.h"
47 #include "alsa-mixer.h"
54 #include "udev-util.h"
57 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
59 static const snd_pcm_format_t format_trans[] = {
60 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
61 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
62 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
63 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
64 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
65 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
66 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
67 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
68 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
69 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
70 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
71 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
72 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
75 static const pa_sample_format_t try_order[] = {
94 pa_assert(pcm_handle);
98 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
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));
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;
128 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
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));
137 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
140 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
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));
151 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
155 pa_assert(pcm_handle);
160 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
163 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
166 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
167 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
176 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
179 pa_assert(pcm_handle);
182 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
183 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
190 /* Set the hardware parameters of the given ALSA device. Returns the
191 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
192 int pa_alsa_set_hw_params(
193 snd_pcm_t *pcm_handle,
195 snd_pcm_uframes_t *period_size,
196 snd_pcm_uframes_t *buffer_size,
197 snd_pcm_uframes_t tsched_size,
199 pa_bool_t *use_tsched,
200 pa_bool_t require_exact_channel_number) {
203 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
205 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
206 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
207 pa_bool_t _use_mmap = use_mmap && *use_mmap;
208 pa_bool_t _use_tsched = use_tsched && *use_tsched;
209 pa_sample_spec _ss = *ss;
211 pa_assert(pcm_handle);
214 snd_pcm_hw_params_alloca(&hwparams);
215 snd_pcm_hw_params_alloca(&hwparams_copy);
217 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
218 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
222 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
223 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
229 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
231 /* mmap() didn't work, fall back to interleaved */
233 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
234 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
241 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
242 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
249 if (!pa_alsa_pcm_is_hw(pcm_handle))
252 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
255 /* try to disable period wakeups if hardware can do so */
256 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
258 if (snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, FALSE) < 0)
259 /* don't bail, keep going with default mode with period wakeups */
260 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret));
262 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
264 pa_log_info("cannot disable ALSA period wakeups");
268 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
271 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
272 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
276 /* We ignore very small sampling rate deviations */
277 if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
280 if (require_exact_channel_number) {
281 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
282 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
286 unsigned int c = _ss.channels;
288 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
289 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
296 if (_use_tsched && tsched_size > 0) {
297 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
298 _period_size = _buffer_size;
300 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
301 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
304 if (_buffer_size > 0 || _period_size > 0) {
305 snd_pcm_uframes_t max_frames = 0;
307 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
308 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
310 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
312 /* Some ALSA drivers really don't like if we set the buffer
313 * size first and the number of periods second. (which would
314 * make a lot more sense to me) So, try a few combinations
315 * before we give up. */
317 if (_buffer_size > 0 && _period_size > 0) {
318 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
320 /* First try: set buffer size first, followed by period size */
321 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
322 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
323 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
324 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
328 /* Second try: set period size first, followed by buffer size */
329 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
330 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
331 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
332 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);
337 if (_buffer_size > 0) {
338 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
340 /* Third try: set only buffer size */
341 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
342 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
343 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);
348 if (_period_size > 0) {
349 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
351 /* Fourth try: set only period size */
352 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
353 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
354 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);
360 pa_log_debug("Set neither period nor buffer size.");
362 /* Last chance, set nothing */
363 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
364 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
370 if (ss->rate != _ss.rate)
371 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
373 if (ss->channels != _ss.channels)
374 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
376 if (ss->format != _ss.format)
377 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));
379 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
380 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
384 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
385 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
389 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
390 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
391 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
395 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
397 unsigned int no_wakeup;
398 /* see if period wakeups were disabled */
399 snd_pcm_hw_params_get_period_wakeup(pcm_handle, hwparams, &no_wakeup);
401 pa_log_info("ALSA period wakeups disabled");
403 pa_log_info("ALSA period wakeups were not disabled");
408 ss->channels = _ss.channels;
409 ss->format = _ss.format;
411 pa_assert(_period_size > 0);
412 pa_assert(_buffer_size > 0);
415 *buffer_size = _buffer_size;
418 *period_size = _period_size;
421 *use_mmap = _use_mmap;
424 *use_tsched = _use_tsched;
433 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, pa_bool_t period_event) {
434 snd_pcm_sw_params_t *swparams;
435 snd_pcm_uframes_t boundary;
440 snd_pcm_sw_params_alloca(&swparams);
442 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
443 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
447 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
448 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
452 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
453 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
457 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
458 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
462 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
463 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
467 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
468 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
472 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
473 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
477 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
478 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
485 snd_pcm_t *pa_alsa_open_by_device_id_auto(
491 snd_pcm_uframes_t *period_size,
492 snd_pcm_uframes_t *buffer_size,
493 snd_pcm_uframes_t tsched_size,
495 pa_bool_t *use_tsched,
496 pa_alsa_profile_set *ps,
497 pa_alsa_mapping **mapping) {
500 snd_pcm_t *pcm_handle;
510 /* First we try to find a device string with a superset of the
511 * requested channel map. We iterate through our device table from
512 * top to bottom and take the first that matches. If we didn't
513 * find a working device that way, we iterate backwards, and check
514 * all devices that do not provide a superset of the requested
517 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
518 if (!pa_channel_map_superset(&m->channel_map, map))
521 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
523 pcm_handle = pa_alsa_open_by_device_id_mapping(
544 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
545 if (pa_channel_map_superset(&m->channel_map, map))
548 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
550 pcm_handle = pa_alsa_open_by_device_id_mapping(
571 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
572 d = pa_sprintf_malloc("hw:%s", dev_id);
573 pa_log_debug("Trying %s as last resort...", d);
574 pcm_handle = pa_alsa_open_by_device_string(
588 if (pcm_handle && mapping)
594 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
600 snd_pcm_uframes_t *period_size,
601 snd_pcm_uframes_t *buffer_size,
602 snd_pcm_uframes_t tsched_size,
604 pa_bool_t *use_tsched,
605 pa_alsa_mapping *m) {
607 snd_pcm_t *pcm_handle;
608 pa_sample_spec try_ss;
609 pa_channel_map try_map;
617 try_ss.channels = m->channel_map.channels;
618 try_ss.rate = ss->rate;
619 try_ss.format = ss->format;
620 try_map = m->channel_map;
622 pcm_handle = pa_alsa_open_by_template(
641 pa_assert(map->channels == ss->channels);
646 snd_pcm_t *pa_alsa_open_by_device_string(
652 snd_pcm_uframes_t *period_size,
653 snd_pcm_uframes_t *buffer_size,
654 snd_pcm_uframes_t tsched_size,
656 pa_bool_t *use_tsched,
657 pa_bool_t require_exact_channel_number) {
661 snd_pcm_t *pcm_handle;
662 pa_bool_t reformat = FALSE;
668 d = pa_xstrdup(device);
671 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
673 if ((err = snd_pcm_open(&pcm_handle, d, mode,
675 SND_PCM_NO_AUTO_RESAMPLE|
676 SND_PCM_NO_AUTO_CHANNELS|
677 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
678 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
682 pa_log_debug("Managed to open %s", d);
684 if ((err = pa_alsa_set_hw_params(
692 require_exact_channel_number)) < 0) {
697 snd_pcm_close(pcm_handle);
701 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
702 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
705 t = pa_sprintf_malloc("plug:%s", d);
711 snd_pcm_close(pcm_handle);
715 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
716 snd_pcm_close(pcm_handle);
726 if (ss->channels != map->channels)
727 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
738 snd_pcm_t *pa_alsa_open_by_template(
745 snd_pcm_uframes_t *period_size,
746 snd_pcm_uframes_t *buffer_size,
747 snd_pcm_uframes_t tsched_size,
749 pa_bool_t *use_tsched,
750 pa_bool_t require_exact_channel_number) {
752 snd_pcm_t *pcm_handle;
755 for (i = template; *i; i++) {
758 d = pa_replace(*i, "%f", dev_id);
760 pcm_handle = pa_alsa_open_by_device_string(
771 require_exact_channel_number);
782 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
788 pa_assert_se(snd_output_buffer_open(&out) == 0);
790 if ((err = snd_pcm_dump(pcm, out)) < 0)
791 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
794 snd_output_buffer_string(out, &s);
795 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
798 pa_assert_se(snd_output_close(out) == 0);
801 void pa_alsa_dump_status(snd_pcm_t *pcm) {
804 snd_pcm_status_t *status;
809 snd_pcm_status_alloca(&status);
811 if ((err = snd_output_buffer_open(&out)) < 0) {
812 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
816 if ((err = snd_pcm_status(pcm, status)) < 0) {
817 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
821 if ((err = snd_pcm_status_dump(status, out)) < 0) {
822 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
826 snd_output_buffer_string(out, &s);
827 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
831 snd_output_close(out);
834 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
838 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
842 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
849 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
851 void pa_alsa_refcnt_inc(void) {
852 /* This is not really thread safe, but we do our best */
854 if (pa_atomic_inc(&n_error_handler_installed) == 0)
855 snd_lib_error_set_handler(alsa_error_handler);
858 void pa_alsa_refcnt_dec(void) {
861 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
864 snd_lib_error_set_handler(NULL);
865 snd_config_update_free_global();
869 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
873 if (pa_device_init_description(p))
876 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
877 d = pa_proplist_gets(p, "alsa.name");
882 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
885 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k);
887 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
892 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
896 pa_assert(card >= 0);
898 pa_proplist_setf(p, "alsa.card", "%i", card);
900 if (snd_card_get_name(card, &cn) >= 0) {
901 pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
905 if (snd_card_get_longname(card, &lcn) >= 0) {
906 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
910 if ((dn = pa_alsa_get_driver_name(card))) {
911 pa_proplist_sets(p, "alsa.driver_name", dn);
916 pa_udev_get_info(card, p);
920 pa_hal_get_info(c, p, card);
924 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
926 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
927 [SND_PCM_CLASS_GENERIC] = "generic",
928 [SND_PCM_CLASS_MULTI] = "multi",
929 [SND_PCM_CLASS_MODEM] = "modem",
930 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
932 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
933 [SND_PCM_CLASS_GENERIC] = "sound",
934 [SND_PCM_CLASS_MULTI] = NULL,
935 [SND_PCM_CLASS_MODEM] = "modem",
936 [SND_PCM_CLASS_DIGITIZER] = NULL
938 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
939 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
940 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
943 snd_pcm_class_t class;
944 snd_pcm_subclass_t subclass;
945 const char *n, *id, *sdn;
951 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
953 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
954 if (class_table[class])
955 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
956 if (alsa_class_table[class])
957 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
960 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
961 if (alsa_subclass_table[subclass])
962 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
964 if ((n = snd_pcm_info_get_name(pcm_info))) {
965 char *t = pa_xstrdup(n);
966 pa_proplist_sets(p, "alsa.name", pa_strip(t));
970 if ((id = snd_pcm_info_get_id(pcm_info)))
971 pa_proplist_sets(p, "alsa.id", id);
973 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
974 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
975 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
977 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
979 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
980 pa_alsa_init_proplist_card(c, p, card);
983 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
984 snd_pcm_hw_params_t *hwparams;
985 snd_pcm_info_t *info;
988 snd_pcm_hw_params_alloca(&hwparams);
989 snd_pcm_info_alloca(&info);
991 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
992 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
995 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
996 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
999 if ((err = snd_pcm_info(pcm, info)) < 0)
1000 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1002 pa_alsa_init_proplist_pcm_info(c, p, info);
1005 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1008 snd_ctl_card_info_t *info;
1013 snd_ctl_card_info_alloca(&info);
1015 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1016 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1020 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1021 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1026 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1027 pa_proplist_sets(p, "alsa.mixer_name", t);
1029 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1030 pa_proplist_sets(p, "alsa.components", t);
1035 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1036 snd_pcm_state_t state;
1041 if (revents & POLLERR)
1042 pa_log_debug("Got POLLERR from ALSA");
1043 if (revents & POLLNVAL)
1044 pa_log_warn("Got POLLNVAL from ALSA");
1045 if (revents & POLLHUP)
1046 pa_log_warn("Got POLLHUP from ALSA");
1047 if (revents & POLLPRI)
1048 pa_log_warn("Got POLLPRI from ALSA");
1049 if (revents & POLLIN)
1050 pa_log_debug("Got POLLIN from ALSA");
1051 if (revents & POLLOUT)
1052 pa_log_debug("Got POLLOUT from ALSA");
1054 state = snd_pcm_state(pcm);
1055 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1057 /* Try to recover from this error */
1061 case SND_PCM_STATE_XRUN:
1062 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1063 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1068 case SND_PCM_STATE_SUSPENDED:
1069 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1070 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1079 if ((err = snd_pcm_prepare(pcm)) < 0) {
1080 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1089 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1091 struct pollfd *pollfd;
1092 pa_rtpoll_item *item;
1096 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1097 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1101 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1102 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1104 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1105 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1106 pa_rtpoll_item_free(item);
1113 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1114 snd_pcm_sframes_t n;
1118 pa_assert(hwbuf_size > 0);
1121 /* Some ALSA driver expose weird bugs, let's inform the user about
1122 * what is going on */
1124 n = snd_pcm_avail(pcm);
1129 k = (size_t) n * pa_frame_size(ss);
1131 if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1132 k >= pa_bytes_per_second(ss)*10)) {
1135 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1136 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1137 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1139 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1142 pa_alsa_dump(PA_LOG_ERROR, pcm);
1145 /* Mhmm, let's try not to fail completely */
1146 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1152 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture) {
1156 snd_pcm_sframes_t avail = 0;
1160 pa_assert(hwbuf_size > 0);
1163 /* Some ALSA driver expose weird bugs, let's inform the user about
1164 * what is going on. We're going to get both the avail and delay values so
1165 * that we can compare and check them for capture */
1167 if ((r = snd_pcm_avail_delay(pcm, &avail, delay)) < 0)
1170 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1172 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1174 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1175 abs_k >= pa_bytes_per_second(ss)*10)) {
1178 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1179 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1180 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1183 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1186 pa_alsa_dump(PA_LOG_ERROR, pcm);
1189 /* Mhmm, let's try not to fail completely */
1191 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1193 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1197 abs_k = (size_t) avail * pa_frame_size(ss);
1199 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1200 abs_k >= pa_bytes_per_second(ss)*10)) {
1203 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1204 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1205 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1207 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1210 pa_alsa_dump(PA_LOG_ERROR, pcm);
1213 /* Mhmm, let's try not to fail completely */
1214 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1217 if (PA_UNLIKELY(*delay < avail)) {
1219 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1220 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1221 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1222 (unsigned long) *delay,
1223 (unsigned long) avail,
1226 pa_alsa_dump(PA_LOG_ERROR, pcm);
1237 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) {
1239 snd_pcm_uframes_t before;
1246 pa_assert(hwbuf_size > 0);
1251 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1256 k = (size_t) *frames * pa_frame_size(ss);
1258 if (PA_UNLIKELY(*frames > before ||
1259 k >= hwbuf_size * 3 ||
1260 k >= pa_bytes_per_second(ss)*10))
1262 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1263 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1264 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1266 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1269 pa_alsa_dump(PA_LOG_ERROR, pcm);
1275 char *pa_alsa_get_driver_name(int card) {
1278 pa_assert(card >= 0);
1280 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1287 n = pa_xstrdup(pa_path_get_filename(m));
1293 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1295 snd_pcm_info_t* info;
1296 snd_pcm_info_alloca(&info);
1300 if (snd_pcm_info(pcm, info) < 0)
1303 if ((card = snd_pcm_info_get_card(info)) < 0)
1306 return pa_alsa_get_driver_name(card);
1309 char *pa_alsa_get_reserve_name(const char *device) {
1315 if ((t = strchr(device, ':')))
1318 if ((i = snd_card_get_index(device)) < 0) {
1321 if (pa_atoi(device, &k) < 0)
1327 return pa_sprintf_malloc("Audio%i", i);
1330 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm) {
1331 static unsigned int all_rates[] = { 8000, 11025, 12000,
1332 16000, 22050, 24000,
1333 32000, 44100, 48000,
1334 64000, 88200, 96000,
1335 128000, 176400, 192000,
1337 pa_bool_t supported[PA_ELEMENTSOF(all_rates)] = { FALSE, };
1338 snd_pcm_hw_params_t *hwparams;
1339 unsigned int i, j, n, *rates = NULL;
1342 snd_pcm_hw_params_alloca(&hwparams);
1344 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1345 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1349 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1350 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1351 supported[i] = TRUE;
1359 rates = pa_xnew(unsigned int, n + 1);
1361 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1363 rates[j++] = all_rates[i];
1371 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1372 snd_pcm_info_t* info;
1373 snd_pcm_info_alloca(&info);
1377 if (snd_pcm_info(pcm, info) < 0)
1380 return snd_pcm_info_get_card(info) >= 0;
1383 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1384 snd_pcm_info_t* info;
1385 snd_pcm_info_alloca(&info);
1389 if (snd_pcm_info(pcm, info) < 0)
1392 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1395 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1397 const char* pa_alsa_strerror(int errnum) {
1398 const char *original = NULL;
1399 char *translated, *t;
1402 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1405 original = snd_strerror(errnum);
1408 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1412 if (!(translated = pa_locale_to_utf8(original))) {
1413 pa_log_warn("Unable to convert error string to locale, filtering.");
1414 translated = pa_utf8_filter(original);
1417 PA_STATIC_TLS_SET(cstrerror, translated);
1422 pa_bool_t pa_alsa_may_tsched(pa_bool_t want) {
1427 if (!pa_rtclock_hrtimer()) {
1428 /* We cannot depend on being woken up in time when the timers
1429 are inaccurate, so let's fallback to classic IO based playback
1431 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1434 if (pa_running_in_vm()) {
1435 /* We cannot depend on being woken up when we ask for in a VM,
1436 * so let's fallback to classic IO based playback then. */
1437 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");