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 *period and *period_size */
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 ((ret
= set_format(pcm_handle
, hwparams
, &_ss
.format
)) < 0)
253 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &_ss
.rate
, NULL
)) < 0) {
254 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret
));
258 if (require_exact_channel_number
) {
259 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, _ss
.channels
)) < 0) {
260 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss
.channels
, pa_alsa_strerror(ret
));
264 unsigned int c
= _ss
.channels
;
266 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0) {
267 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss
.channels
, pa_alsa_strerror(ret
));
274 if (_use_tsched
&& tsched_size
> 0) {
275 _buffer_size
= pa_convert_size(tsched_size
, ss
, &_ss
);
276 _period_size
= _buffer_size
;
278 _period_size
= pa_convert_size(_period_size
, ss
, &_ss
);
279 _buffer_size
= pa_convert_size(_buffer_size
, ss
, &_ss
);
282 if (_buffer_size
> 0 || _period_size
> 0) {
283 snd_pcm_uframes_t max_frames
= 0;
285 if ((ret
= snd_pcm_hw_params_get_buffer_size_max(hwparams
, &max_frames
)) < 0)
286 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret
));
288 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) max_frames
* PA_MSEC_PER_SEC
/ _ss
.rate
);
290 /* Some ALSA drivers really don't like if we set the buffer
291 * size first and the number of periods second. (which would
292 * make a lot more sense to me) So, try a few combinations
293 * before we give up. */
295 if (_buffer_size
> 0 && _period_size
> 0) {
296 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
298 /* First try: set buffer size first, followed by period size */
299 if (set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
300 set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
301 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
302 pa_log_debug("Set buffer size first, period size second.");
306 /* Second try: set period size first, followed by buffer size */
307 if (set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
308 set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
309 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
310 pa_log_debug("Set period size first, buffer size second.");
315 if (_buffer_size
> 0) {
316 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
318 /* Third try: set only buffer size */
319 if (set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
320 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
321 pa_log_debug("Set only buffer size second.");
326 if (_period_size
> 0) {
327 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
329 /* Fourth try: set only period size */
330 if (set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
331 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
332 pa_log_debug("Set only period size second.");
338 pa_log_debug("Set neither period nor buffer size.");
340 /* Last chance, set nothing */
341 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0) {
342 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret
));
348 if (ss
->rate
!= _ss
.rate
)
349 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, _ss
.rate
);
351 if (ss
->channels
!= _ss
.channels
)
352 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, _ss
.channels
);
354 if (ss
->format
!= _ss
.format
)
355 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
));
357 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0) {
358 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret
));
362 if ((ret
= snd_pcm_hw_params_current(pcm_handle
, hwparams
)) < 0) {
363 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret
));
367 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
368 (ret
= snd_pcm_hw_params_get_buffer_size(hwparams
, &_buffer_size
)) < 0) {
369 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret
));
373 /* If the sample rate deviates too much, we need to resample */
374 if (_ss
.rate
< ss
->rate
*.95 || _ss
.rate
> ss
->rate
*1.05)
376 ss
->channels
= _ss
.channels
;
377 ss
->format
= _ss
.format
;
379 pa_assert(_period_size
> 0);
380 pa_assert(_buffer_size
> 0);
383 *buffer_size
= _buffer_size
;
386 *period_size
= _period_size
;
389 *use_mmap
= _use_mmap
;
392 *use_tsched
= _use_tsched
;
396 snd_pcm_nonblock(pcm_handle
, 1);
403 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
) {
404 snd_pcm_sw_params_t
*swparams
;
405 snd_pcm_uframes_t boundary
;
410 snd_pcm_sw_params_alloca(&swparams
);
412 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
413 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err
));
417 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 0)) < 0) {
418 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err
));
422 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
423 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err
));
427 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
428 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err
));
432 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
433 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err
));
437 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
438 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err
));
442 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
443 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err
));
447 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
448 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err
));
455 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
461 snd_pcm_uframes_t
*period_size
,
462 snd_pcm_uframes_t
*buffer_size
,
463 snd_pcm_uframes_t tsched_size
,
465 pa_bool_t
*use_tsched
,
466 pa_alsa_profile_set
*ps
,
467 pa_alsa_mapping
**mapping
) {
470 snd_pcm_t
*pcm_handle
;
480 /* First we try to find a device string with a superset of the
481 * requested channel map. We iterate through our device table from
482 * top to bottom and take the first that matches. If we didn't
483 * find a working device that way, we iterate backwards, and check
484 * all devices that do not provide a superset of the requested
487 PA_HASHMAP_FOREACH(m
, ps
->mappings
, state
) {
488 if (!pa_channel_map_superset(&m
->channel_map
, map
))
491 pa_log_debug("Checking for superset %s (%s)", m
->name
, m
->device_strings
[0]);
493 pcm_handle
= pa_alsa_open_by_device_id_mapping(
514 PA_HASHMAP_FOREACH_BACKWARDS(m
, ps
->mappings
, state
) {
515 if (pa_channel_map_superset(&m
->channel_map
, map
))
518 pa_log_debug("Checking for subset %s (%s)", m
->name
, m
->device_strings
[0]);
520 pcm_handle
= pa_alsa_open_by_device_id_mapping(
541 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
542 d
= pa_sprintf_malloc("hw:%s", dev_id
);
543 pa_log_debug("Trying %s as last resort...", d
);
544 pcm_handle
= pa_alsa_open_by_device_string(
558 if (pcm_handle
&& mapping
)
564 snd_pcm_t
*pa_alsa_open_by_device_id_mapping(
570 snd_pcm_uframes_t
*period_size
,
571 snd_pcm_uframes_t
*buffer_size
,
572 snd_pcm_uframes_t tsched_size
,
574 pa_bool_t
*use_tsched
,
575 pa_alsa_mapping
*m
) {
577 snd_pcm_t
*pcm_handle
;
578 pa_sample_spec try_ss
;
579 pa_channel_map try_map
;
587 try_ss
.channels
= m
->channel_map
.channels
;
588 try_ss
.rate
= ss
->rate
;
589 try_ss
.format
= ss
->format
;
590 try_map
= m
->channel_map
;
592 pcm_handle
= pa_alsa_open_by_template(
611 pa_assert(map
->channels
== ss
->channels
);
616 snd_pcm_t
*pa_alsa_open_by_device_string(
622 snd_pcm_uframes_t
*period_size
,
623 snd_pcm_uframes_t
*buffer_size
,
624 snd_pcm_uframes_t tsched_size
,
626 pa_bool_t
*use_tsched
,
627 pa_bool_t require_exact_channel_number
) {
631 snd_pcm_t
*pcm_handle
;
632 pa_bool_t reformat
= FALSE
;
638 d
= pa_xstrdup(device
);
641 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
643 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
645 SND_PCM_NO_AUTO_RESAMPLE
|
646 SND_PCM_NO_AUTO_CHANNELS
|
647 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
648 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
652 pa_log_debug("Managed to open %s", d
);
654 if ((err
= pa_alsa_set_hw_params(
662 require_exact_channel_number
)) < 0) {
667 snd_pcm_close(pcm_handle
);
671 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
672 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
675 t
= pa_sprintf_malloc("plug:%s", d
);
681 snd_pcm_close(pcm_handle
);
685 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
686 snd_pcm_close(pcm_handle
);
696 if (ss
->channels
!= map
->channels
)
697 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
708 snd_pcm_t
*pa_alsa_open_by_template(
715 snd_pcm_uframes_t
*period_size
,
716 snd_pcm_uframes_t
*buffer_size
,
717 snd_pcm_uframes_t tsched_size
,
719 pa_bool_t
*use_tsched
,
720 pa_bool_t require_exact_channel_number
) {
722 snd_pcm_t
*pcm_handle
;
725 for (i
= template; *i
; i
++) {
728 d
= pa_replace(*i
, "%f", dev_id
);
730 pcm_handle
= pa_alsa_open_by_device_string(
741 require_exact_channel_number
);
752 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
758 pa_assert_se(snd_output_buffer_open(&out
) == 0);
760 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
761 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
764 snd_output_buffer_string(out
, &s
);
765 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
768 pa_assert_se(snd_output_close(out
) == 0);
771 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
774 snd_pcm_status_t
*status
;
779 snd_pcm_status_alloca(&status
);
781 if ((err
= snd_output_buffer_open(&out
)) < 0) {
782 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err
));
786 if ((err
= snd_pcm_status(pcm
, status
)) < 0) {
787 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err
));
791 if ((err
= snd_pcm_status_dump(status
, out
)) < 0) {
792 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
796 snd_output_buffer_string(out
, &s
);
797 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
801 snd_output_close(out
);
804 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
808 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
812 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
819 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
821 void pa_alsa_refcnt_inc(void) {
822 /* This is not really thread safe, but we do our best */
824 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
825 snd_lib_error_set_handler(alsa_error_handler
);
828 void pa_alsa_refcnt_dec(void) {
831 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
834 snd_lib_error_set_handler(NULL
);
835 snd_config_update_free_global();
839 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
843 if (pa_device_init_description(p
))
846 if (!(d
= pa_proplist_gets(p
, "alsa.card_name")))
847 d
= pa_proplist_gets(p
, "alsa.name");
852 k
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
);
855 pa_proplist_setf(p
, PA_PROP_DEVICE_DESCRIPTION
, _("%s %s"), d
, k
);
857 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, d
);
862 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
866 pa_assert(card
>= 0);
868 pa_proplist_setf(p
, "alsa.card", "%i", card
);
870 if (snd_card_get_name(card
, &cn
) >= 0) {
871 pa_proplist_sets(p
, "alsa.card_name", cn
);
875 if (snd_card_get_longname(card
, &lcn
) >= 0) {
876 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
880 if ((dn
= pa_alsa_get_driver_name(card
))) {
881 pa_proplist_sets(p
, "alsa.driver_name", dn
);
886 pa_udev_get_info(card
, p
);
890 pa_hal_get_info(c
, p
, card
);
894 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
896 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
897 [SND_PCM_CLASS_GENERIC
] = "generic",
898 [SND_PCM_CLASS_MULTI
] = "multi",
899 [SND_PCM_CLASS_MODEM
] = "modem",
900 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
902 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
903 [SND_PCM_CLASS_GENERIC
] = "sound",
904 [SND_PCM_CLASS_MULTI
] = NULL
,
905 [SND_PCM_CLASS_MODEM
] = "modem",
906 [SND_PCM_CLASS_DIGITIZER
] = NULL
908 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
909 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
910 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
913 snd_pcm_class_t
class;
914 snd_pcm_subclass_t subclass
;
915 const char *n
, *id
, *sdn
;
921 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
923 if ((class = snd_pcm_info_get_class(pcm_info
)) <= SND_PCM_CLASS_LAST
) {
924 if (class_table
[class])
925 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
926 if (alsa_class_table
[class])
927 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
930 if ((subclass
= snd_pcm_info_get_subclass(pcm_info
)) <= SND_PCM_SUBCLASS_LAST
)
931 if (alsa_subclass_table
[subclass
])
932 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
934 if ((n
= snd_pcm_info_get_name(pcm_info
)))
935 pa_proplist_sets(p
, "alsa.name", n
);
937 if ((id
= snd_pcm_info_get_id(pcm_info
)))
938 pa_proplist_sets(p
, "alsa.id", id
);
940 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
941 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
942 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
944 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
946 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
947 pa_alsa_init_proplist_card(c
, p
, card
);
950 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
) {
951 snd_pcm_hw_params_t
*hwparams
;
952 snd_pcm_info_t
*info
;
955 snd_pcm_hw_params_alloca(&hwparams
);
956 snd_pcm_info_alloca(&info
);
958 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
959 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
962 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
963 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
966 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
967 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
969 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
972 void pa_alsa_init_proplist_ctl(pa_proplist
*p
, const char *name
) {
975 snd_ctl_card_info_t
*info
;
980 snd_ctl_card_info_alloca(&info
);
982 if ((err
= snd_ctl_open(&ctl
, name
, 0)) < 0) {
983 pa_log_warn("Error opening low-level control device '%s': %s", name
, snd_strerror(err
));
987 if ((err
= snd_ctl_card_info(ctl
, info
)) < 0) {
988 pa_log_warn("Control device %s card info: %s", name
, snd_strerror(err
));
993 if ((t
= snd_ctl_card_info_get_mixername(info
)) && *t
)
994 pa_proplist_sets(p
, "alsa.mixer_name", t
);
996 if ((t
= snd_ctl_card_info_get_components(info
)) && *t
)
997 pa_proplist_sets(p
, "alsa.components", t
);
1002 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1003 snd_pcm_state_t state
;
1008 if (revents
& POLLERR
)
1009 pa_log_debug("Got POLLERR from ALSA");
1010 if (revents
& POLLNVAL
)
1011 pa_log_warn("Got POLLNVAL from ALSA");
1012 if (revents
& POLLHUP
)
1013 pa_log_warn("Got POLLHUP from ALSA");
1014 if (revents
& POLLPRI
)
1015 pa_log_warn("Got POLLPRI from ALSA");
1016 if (revents
& POLLIN
)
1017 pa_log_debug("Got POLLIN from ALSA");
1018 if (revents
& POLLOUT
)
1019 pa_log_debug("Got POLLOUT from ALSA");
1021 state
= snd_pcm_state(pcm
);
1022 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1024 /* Try to recover from this error */
1028 case SND_PCM_STATE_XRUN
:
1029 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1030 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1035 case SND_PCM_STATE_SUSPENDED
:
1036 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1037 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1046 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1047 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1056 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1058 struct pollfd
*pollfd
;
1059 pa_rtpoll_item
*item
;
1063 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1064 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1068 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1069 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1071 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1072 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1073 pa_rtpoll_item_free(item
);
1080 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1081 snd_pcm_sframes_t n
;
1085 pa_assert(hwbuf_size
> 0);
1088 /* Some ALSA driver expose weird bugs, let's inform the user about
1089 * what is going on */
1091 n
= snd_pcm_avail(pcm
);
1096 k
= (size_t) n
* pa_frame_size(ss
);
1098 if (k
>= hwbuf_size
* 5 ||
1099 k
>= pa_bytes_per_second(ss
)*10) {
1102 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1103 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1104 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1106 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1109 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1112 /* Mhmm, let's try not to fail completely */
1113 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1119 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1126 pa_assert(hwbuf_size
> 0);
1129 /* Some ALSA driver expose weird bugs, let's inform the user about
1130 * what is going on */
1132 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1135 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1137 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1139 if (abs_k
>= hwbuf_size
* 5 ||
1140 abs_k
>= pa_bytes_per_second(ss
)*10) {
1143 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1144 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1145 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1148 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1151 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1154 /* Mhmm, let's try not to fail completely */
1156 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1158 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1164 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
) {
1166 snd_pcm_uframes_t before
;
1173 pa_assert(hwbuf_size
> 0);
1178 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1183 k
= (size_t) *frames
* pa_frame_size(ss
);
1185 if (*frames
> before
||
1186 k
>= hwbuf_size
* 3 ||
1187 k
>= pa_bytes_per_second(ss
)*10)
1190 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1191 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1192 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1194 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1197 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1203 char *pa_alsa_get_driver_name(int card
) {
1206 pa_assert(card
>= 0);
1208 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1215 n
= pa_xstrdup(pa_path_get_filename(m
));
1221 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1223 snd_pcm_info_t
* info
;
1224 snd_pcm_info_alloca(&info
);
1228 if (snd_pcm_info(pcm
, info
) < 0)
1231 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1234 return pa_alsa_get_driver_name(card
);
1237 char *pa_alsa_get_reserve_name(const char *device
) {
1243 if ((t
= strchr(device
, ':')))
1246 if ((i
= snd_card_get_index(device
)) < 0) {
1249 if (pa_atoi(device
, &k
) < 0)
1255 return pa_sprintf_malloc("Audio%i", i
);
1258 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1259 snd_pcm_info_t
* info
;
1260 snd_pcm_info_alloca(&info
);
1264 if (snd_pcm_info(pcm
, info
) < 0)
1267 return snd_pcm_info_get_card(info
) >= 0;
1270 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1271 snd_pcm_info_t
* info
;
1272 snd_pcm_info_alloca(&info
);
1276 if (snd_pcm_info(pcm
, info
) < 0)
1279 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1282 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1284 const char* pa_alsa_strerror(int errnum
) {
1285 const char *original
= NULL
;
1286 char *translated
, *t
;
1289 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1292 original
= snd_strerror(errnum
);
1295 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1299 if (!(translated
= pa_locale_to_utf8(original
))) {
1300 pa_log_warn("Unable to convert error string to locale, filtering.");
1301 translated
= pa_utf8_filter(original
);
1304 PA_STATIC_TLS_SET(cstrerror
, translated
);