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>
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>
47 #include "alsa-util.h"
48 #include "alsa-mixer.h"
55 #include "udev-util.h"
58 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
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,
76 static const pa_sample_format_t try_order[] = {
95 pa_assert(pcm_handle);
99 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
102 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
103 snd_pcm_format_description(format_trans[*f]),
104 pa_alsa_strerror(ret));
106 if (*f == PA_SAMPLE_FLOAT32BE)
107 *f = PA_SAMPLE_FLOAT32LE;
108 else if (*f == PA_SAMPLE_FLOAT32LE)
109 *f = PA_SAMPLE_FLOAT32BE;
110 else if (*f == PA_SAMPLE_S24BE)
111 *f = PA_SAMPLE_S24LE;
112 else if (*f == PA_SAMPLE_S24LE)
113 *f = PA_SAMPLE_S24BE;
114 else if (*f == PA_SAMPLE_S24_32BE)
115 *f = PA_SAMPLE_S24_32LE;
116 else if (*f == PA_SAMPLE_S24_32LE)
117 *f = PA_SAMPLE_S24_32BE;
118 else if (*f == PA_SAMPLE_S16BE)
119 *f = PA_SAMPLE_S16LE;
120 else if (*f == PA_SAMPLE_S16LE)
121 *f = PA_SAMPLE_S16BE;
122 else if (*f == PA_SAMPLE_S32BE)
123 *f = PA_SAMPLE_S32LE;
124 else if (*f == PA_SAMPLE_S32LE)
125 *f = PA_SAMPLE_S32BE;
129 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
132 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
133 snd_pcm_format_description(format_trans[*f]),
134 pa_alsa_strerror(ret));
138 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
141 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
144 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
145 snd_pcm_format_description(format_trans[*f]),
146 pa_alsa_strerror(ret));
152 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
156 pa_assert(pcm_handle);
161 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
164 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
167 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
168 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
177 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
180 pa_assert(pcm_handle);
183 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
184 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
191 /* Set the hardware parameters of the given ALSA device. Returns the
192 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
193 int pa_alsa_set_hw_params(
194 snd_pcm_t *pcm_handle,
196 snd_pcm_uframes_t *period_size,
197 snd_pcm_uframes_t *buffer_size,
198 snd_pcm_uframes_t tsched_size,
200 pa_bool_t *use_tsched,
201 pa_bool_t require_exact_channel_number) {
204 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
206 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
207 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
208 pa_bool_t _use_mmap = use_mmap && *use_mmap;
209 pa_bool_t _use_tsched = use_tsched && *use_tsched;
210 pa_sample_spec _ss = *ss;
212 pa_assert(pcm_handle);
215 snd_pcm_hw_params_alloca(&hwparams);
216 snd_pcm_hw_params_alloca(&hwparams_copy);
218 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
219 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
223 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
224 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
230 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
232 /* mmap() didn't work, fall back to interleaved */
234 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
235 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
242 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
243 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
250 if (!pa_alsa_pcm_is_hw(pcm_handle))
253 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
256 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
257 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
261 if (require_exact_channel_number) {
262 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
263 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
267 unsigned int c = _ss.channels;
269 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
270 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
277 if (_use_tsched && tsched_size > 0) {
278 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
279 _period_size = _buffer_size;
281 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
282 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
285 if (_buffer_size > 0 || _period_size > 0) {
286 snd_pcm_uframes_t max_frames = 0;
288 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
289 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
291 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
293 /* Some ALSA drivers really don't like if we set the buffer
294 * size first and the number of periods second. (which would
295 * make a lot more sense to me) So, try a few combinations
296 * before we give up. */
298 if (_buffer_size > 0 && _period_size > 0) {
299 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
301 /* First try: set buffer size first, followed by period size */
302 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
303 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
304 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
305 pa_log_debug("Set buffer size first, period size second.");
309 /* Second try: set period size first, followed by buffer size */
310 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
311 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
312 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
313 pa_log_debug("Set period size first, buffer size second.");
318 if (_buffer_size > 0) {
319 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
321 /* Third try: set only buffer size */
322 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
323 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
324 pa_log_debug("Set only buffer size second.");
329 if (_period_size > 0) {
330 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
332 /* Fourth try: set only period size */
333 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
334 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
335 pa_log_debug("Set only period size second.");
341 pa_log_debug("Set neither period nor buffer size.");
343 /* Last chance, set nothing */
344 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
345 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
351 if (ss->rate != _ss.rate)
352 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
354 if (ss->channels != _ss.channels)
355 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
357 if (ss->format != _ss.format)
358 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));
360 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
361 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
365 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
366 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
370 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
371 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
372 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
376 /* If the sample rate deviates too much, we need to resample */
377 if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
379 ss->channels = _ss.channels;
380 ss->format = _ss.format;
382 pa_assert(_period_size > 0);
383 pa_assert(_buffer_size > 0);
386 *buffer_size = _buffer_size;
389 *period_size = _period_size;
392 *use_mmap = _use_mmap;
395 *use_tsched = _use_tsched;
399 snd_pcm_nonblock(pcm_handle, 1);
406 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, pa_bool_t period_event) {
407 snd_pcm_sw_params_t *swparams;
408 snd_pcm_uframes_t boundary;
413 snd_pcm_sw_params_alloca(&swparams);
415 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
416 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
420 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
421 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
425 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
426 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
430 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
431 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
435 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
436 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
440 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
441 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
445 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
446 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
450 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
451 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
458 snd_pcm_t *pa_alsa_open_by_device_id_auto(
464 snd_pcm_uframes_t *period_size,
465 snd_pcm_uframes_t *buffer_size,
466 snd_pcm_uframes_t tsched_size,
468 pa_bool_t *use_tsched,
469 pa_alsa_profile_set *ps,
470 pa_alsa_mapping **mapping) {
473 snd_pcm_t *pcm_handle;
483 /* First we try to find a device string with a superset of the
484 * requested channel map. We iterate through our device table from
485 * top to bottom and take the first that matches. If we didn't
486 * find a working device that way, we iterate backwards, and check
487 * all devices that do not provide a superset of the requested
490 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
491 if (!pa_channel_map_superset(&m->channel_map, map))
494 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
496 pcm_handle = pa_alsa_open_by_device_id_mapping(
517 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
518 if (pa_channel_map_superset(&m->channel_map, map))
521 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
523 pcm_handle = pa_alsa_open_by_device_id_mapping(
544 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
545 d = pa_sprintf_malloc("hw:%s", dev_id);
546 pa_log_debug("Trying %s as last resort...", d);
547 pcm_handle = pa_alsa_open_by_device_string(
561 if (pcm_handle && mapping)
567 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
573 snd_pcm_uframes_t *period_size,
574 snd_pcm_uframes_t *buffer_size,
575 snd_pcm_uframes_t tsched_size,
577 pa_bool_t *use_tsched,
578 pa_alsa_mapping *m) {
580 snd_pcm_t *pcm_handle;
581 pa_sample_spec try_ss;
582 pa_channel_map try_map;
590 try_ss.channels = m->channel_map.channels;
591 try_ss.rate = ss->rate;
592 try_ss.format = ss->format;
593 try_map = m->channel_map;
595 pcm_handle = pa_alsa_open_by_template(
614 pa_assert(map->channels == ss->channels);
619 snd_pcm_t *pa_alsa_open_by_device_string(
625 snd_pcm_uframes_t *period_size,
626 snd_pcm_uframes_t *buffer_size,
627 snd_pcm_uframes_t tsched_size,
629 pa_bool_t *use_tsched,
630 pa_bool_t require_exact_channel_number) {
634 snd_pcm_t *pcm_handle;
635 pa_bool_t reformat = FALSE;
641 d = pa_xstrdup(device);
644 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
646 if ((err = snd_pcm_open(&pcm_handle, d, mode,
648 SND_PCM_NO_AUTO_RESAMPLE|
649 SND_PCM_NO_AUTO_CHANNELS|
650 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
651 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
655 pa_log_debug("Managed to open %s", d);
657 if ((err = pa_alsa_set_hw_params(
665 require_exact_channel_number)) < 0) {
670 snd_pcm_close(pcm_handle);
674 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
675 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
678 t = pa_sprintf_malloc("plug:%s", d);
684 snd_pcm_close(pcm_handle);
688 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
689 snd_pcm_close(pcm_handle);
699 if (ss->channels != map->channels)
700 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
711 snd_pcm_t *pa_alsa_open_by_template(
718 snd_pcm_uframes_t *period_size,
719 snd_pcm_uframes_t *buffer_size,
720 snd_pcm_uframes_t tsched_size,
722 pa_bool_t *use_tsched,
723 pa_bool_t require_exact_channel_number) {
725 snd_pcm_t *pcm_handle;
728 for (i = template; *i; i++) {
731 d = pa_replace(*i, "%f", dev_id);
733 pcm_handle = pa_alsa_open_by_device_string(
744 require_exact_channel_number);
755 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
761 pa_assert_se(snd_output_buffer_open(&out) == 0);
763 if ((err = snd_pcm_dump(pcm, out)) < 0)
764 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
767 snd_output_buffer_string(out, &s);
768 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
771 pa_assert_se(snd_output_close(out) == 0);
774 void pa_alsa_dump_status(snd_pcm_t *pcm) {
777 snd_pcm_status_t *status;
782 snd_pcm_status_alloca(&status);
784 if ((err = snd_output_buffer_open(&out)) < 0) {
785 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
789 if ((err = snd_pcm_status(pcm, status)) < 0) {
790 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
794 if ((err = snd_pcm_status_dump(status, out)) < 0) {
795 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
799 snd_output_buffer_string(out, &s);
800 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
804 snd_output_close(out);
807 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
811 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
815 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
822 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
824 void pa_alsa_refcnt_inc(void) {
825 /* This is not really thread safe, but we do our best */
827 if (pa_atomic_inc(&n_error_handler_installed) == 0)
828 snd_lib_error_set_handler(alsa_error_handler);
831 void pa_alsa_refcnt_dec(void) {
834 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
837 snd_lib_error_set_handler(NULL);
838 snd_config_update_free_global();
842 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
846 if (pa_device_init_description(p))
849 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
850 d = pa_proplist_gets(p, "alsa.name");
855 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
858 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k);
860 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
865 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
869 pa_assert(card >= 0);
871 pa_proplist_setf(p, "alsa.card", "%i", card);
873 if (snd_card_get_name(card, &cn) >= 0) {
874 pa_proplist_sets(p, "alsa.card_name", cn);
878 if (snd_card_get_longname(card, &lcn) >= 0) {
879 pa_proplist_sets(p, "alsa.long_card_name", lcn);
883 if ((dn = pa_alsa_get_driver_name(card))) {
884 pa_proplist_sets(p, "alsa.driver_name", dn);
889 pa_udev_get_info(card, p);
893 pa_hal_get_info(c, p, card);
897 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
899 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
900 [SND_PCM_CLASS_GENERIC] = "generic",
901 [SND_PCM_CLASS_MULTI] = "multi",
902 [SND_PCM_CLASS_MODEM] = "modem",
903 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
905 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
906 [SND_PCM_CLASS_GENERIC] = "sound",
907 [SND_PCM_CLASS_MULTI] = NULL,
908 [SND_PCM_CLASS_MODEM] = "modem",
909 [SND_PCM_CLASS_DIGITIZER] = NULL
911 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
912 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
913 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
916 snd_pcm_class_t class;
917 snd_pcm_subclass_t subclass;
918 const char *n, *id, *sdn;
924 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
926 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
927 if (class_table[class])
928 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
929 if (alsa_class_table[class])
930 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
933 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
934 if (alsa_subclass_table[subclass])
935 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
937 if ((n = snd_pcm_info_get_name(pcm_info)))
938 pa_proplist_sets(p, "alsa.name", n);
940 if ((id = snd_pcm_info_get_id(pcm_info)))
941 pa_proplist_sets(p, "alsa.id", id);
943 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
944 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
945 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
947 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
949 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
950 pa_alsa_init_proplist_card(c, p, card);
953 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
954 snd_pcm_hw_params_t *hwparams;
955 snd_pcm_info_t *info;
958 snd_pcm_hw_params_alloca(&hwparams);
959 snd_pcm_info_alloca(&info);
961 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
962 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
965 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
966 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
969 if ((err = snd_pcm_info(pcm, info)) < 0)
970 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
972 pa_alsa_init_proplist_pcm_info(c, p, info);
975 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
978 snd_ctl_card_info_t *info;
983 snd_ctl_card_info_alloca(&info);
985 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
986 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
990 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
991 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
996 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
997 pa_proplist_sets(p, "alsa.mixer_name", t);
999 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1000 pa_proplist_sets(p, "alsa.components", t);
1005 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1006 snd_pcm_state_t state;
1011 if (revents & POLLERR)
1012 pa_log_debug("Got POLLERR from ALSA");
1013 if (revents & POLLNVAL)
1014 pa_log_warn("Got POLLNVAL from ALSA");
1015 if (revents & POLLHUP)
1016 pa_log_warn("Got POLLHUP from ALSA");
1017 if (revents & POLLPRI)
1018 pa_log_warn("Got POLLPRI from ALSA");
1019 if (revents & POLLIN)
1020 pa_log_debug("Got POLLIN from ALSA");
1021 if (revents & POLLOUT)
1022 pa_log_debug("Got POLLOUT from ALSA");
1024 state = snd_pcm_state(pcm);
1025 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1027 /* Try to recover from this error */
1031 case SND_PCM_STATE_XRUN:
1032 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1033 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1038 case SND_PCM_STATE_SUSPENDED:
1039 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1040 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1049 if ((err = snd_pcm_prepare(pcm)) < 0) {
1050 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1059 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1061 struct pollfd *pollfd;
1062 pa_rtpoll_item *item;
1066 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1067 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1071 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1072 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1074 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1075 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1076 pa_rtpoll_item_free(item);
1083 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1084 snd_pcm_sframes_t n;
1088 pa_assert(hwbuf_size > 0);
1091 /* Some ALSA driver expose weird bugs, let's inform the user about
1092 * what is going on */
1094 n = snd_pcm_avail(pcm);
1099 k = (size_t) n * pa_frame_size(ss);
1101 if (k >= hwbuf_size * 5 ||
1102 k >= pa_bytes_per_second(ss)*10) {
1105 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1106 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1107 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1109 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1112 pa_alsa_dump(PA_LOG_ERROR, pcm);
1115 /* Mhmm, let's try not to fail completely */
1116 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1122 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1129 pa_assert(hwbuf_size > 0);
1132 /* Some ALSA driver expose weird bugs, let's inform the user about
1133 * what is going on */
1135 if ((r = snd_pcm_delay(pcm, delay)) < 0)
1138 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1140 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1142 if (abs_k >= hwbuf_size * 5 ||
1143 abs_k >= pa_bytes_per_second(ss)*10) {
1146 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1147 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1148 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1151 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1154 pa_alsa_dump(PA_LOG_ERROR, pcm);
1157 /* Mhmm, let's try not to fail completely */
1159 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1161 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1167 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 snd_pcm_uframes_t before;
1176 pa_assert(hwbuf_size > 0);
1181 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1186 k = (size_t) *frames * pa_frame_size(ss);
1188 if (*frames > before ||
1189 k >= hwbuf_size * 3 ||
1190 k >= pa_bytes_per_second(ss)*10)
1193 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1194 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1195 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1197 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1200 pa_alsa_dump(PA_LOG_ERROR, pcm);
1206 char *pa_alsa_get_driver_name(int card) {
1209 pa_assert(card >= 0);
1211 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1218 n = pa_xstrdup(pa_path_get_filename(m));
1224 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1226 snd_pcm_info_t* info;
1227 snd_pcm_info_alloca(&info);
1231 if (snd_pcm_info(pcm, info) < 0)
1234 if ((card = snd_pcm_info_get_card(info)) < 0)
1237 return pa_alsa_get_driver_name(card);
1240 char *pa_alsa_get_reserve_name(const char *device) {
1246 if ((t = strchr(device, ':')))
1249 if ((i = snd_card_get_index(device)) < 0) {
1252 if (pa_atoi(device, &k) < 0)
1258 return pa_sprintf_malloc("Audio%i", i);
1261 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1262 snd_pcm_info_t* info;
1263 snd_pcm_info_alloca(&info);
1267 if (snd_pcm_info(pcm, info) < 0)
1270 return snd_pcm_info_get_card(info) >= 0;
1273 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1274 snd_pcm_info_t* info;
1275 snd_pcm_info_alloca(&info);
1279 if (snd_pcm_info(pcm, info) < 0)
1282 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1285 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1287 const char* pa_alsa_strerror(int errnum) {
1288 const char *original = NULL;
1289 char *translated, *t;
1292 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1295 original = snd_strerror(errnum);
1298 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1302 if (!(translated = pa_locale_to_utf8(original))) {
1303 pa_log_warn("Unable to convert error string to locale, filtering.");
1304 translated = pa_utf8_filter(original);
1307 PA_STATIC_TLS_SET(cstrerror, translated);