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>
46 #include <pulsecore/core-rtclock.h>
48 #include "alsa-util.h"
49 #include "alsa-mixer.h"
56 #include "udev-util.h"
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
[] = {
96 pa_assert(pcm_handle
);
100 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
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
;
130 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
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
));
139 for (i
= 0; i
< PA_ELEMENTSOF(try_order
); i
++) {
142 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
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
));
153 static int set_period_size(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, snd_pcm_uframes_t size
) {
157 pa_assert(pcm_handle
);
162 if (snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, &s
, &d
) < 0) {
165 if (snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, &s
, &d
) < 0) {
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
));
178 static int set_buffer_size(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, snd_pcm_uframes_t size
) {
181 pa_assert(pcm_handle
);
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
));
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
,
197 snd_pcm_uframes_t
*period_size
,
198 snd_pcm_uframes_t
*buffer_size
,
199 snd_pcm_uframes_t tsched_size
,
201 pa_bool_t
*use_tsched
,
202 pa_bool_t require_exact_channel_number
) {
205 snd_pcm_hw_params_t
*hwparams
, *hwparams_copy
;
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
);
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
));
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
));
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
));
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
));
251 if (!pa_alsa_pcm_is_hw(pcm_handle
))
254 if ((ret
= set_format(pcm_handle
, hwparams
, &_ss
.format
)) < 0)
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
));
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
));
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
));
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
;
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
));
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.");
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.");
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.");
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.");
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
));
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
));
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
));
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
));
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)
380 ss
->channels
= _ss
.channels
;
381 ss
->format
= _ss
.format
;
383 pa_assert(_period_size
> 0);
384 pa_assert(_buffer_size
> 0);
387 *buffer_size
= _buffer_size
;
390 *period_size
= _period_size
;
393 *use_mmap
= _use_mmap
;
396 *use_tsched
= _use_tsched
;
400 snd_pcm_nonblock(pcm_handle
, 1);
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
;
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
459 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
465 snd_pcm_uframes_t
*period_size
,
466 snd_pcm_uframes_t
*buffer_size
,
467 snd_pcm_uframes_t tsched_size
,
469 pa_bool_t
*use_tsched
,
470 pa_alsa_profile_set
*ps
,
471 pa_alsa_mapping
**mapping
) {
474 snd_pcm_t
*pcm_handle
;
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
491 PA_HASHMAP_FOREACH(m
, ps
->mappings
, state
) {
492 if (!pa_channel_map_superset(&m
->channel_map
, map
))
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(
518 PA_HASHMAP_FOREACH_BACKWARDS(m
, ps
->mappings
, state
) {
519 if (pa_channel_map_superset(&m
->channel_map
, map
))
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(
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(
562 if (pcm_handle
&& mapping
)
568 snd_pcm_t
*pa_alsa_open_by_device_id_mapping(
574 snd_pcm_uframes_t
*period_size
,
575 snd_pcm_uframes_t
*buffer_size
,
576 snd_pcm_uframes_t tsched_size
,
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
;
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(
615 pa_assert(map
->channels
== ss
->channels
);
620 snd_pcm_t
*pa_alsa_open_by_device_string(
626 snd_pcm_uframes_t
*period_size
,
627 snd_pcm_uframes_t
*buffer_size
,
628 snd_pcm_uframes_t tsched_size
,
630 pa_bool_t
*use_tsched
,
631 pa_bool_t require_exact_channel_number
) {
635 snd_pcm_t
*pcm_handle
;
636 pa_bool_t reformat
= FALSE
;
642 d
= pa_xstrdup(device
);
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
,
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
));
656 pa_log_debug("Managed to open %s", d
);
658 if ((err
= pa_alsa_set_hw_params(
666 require_exact_channel_number
)) < 0) {
671 snd_pcm_close(pcm_handle
);
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:")) {
679 t
= pa_sprintf_malloc("plug:%s", d
);
685 snd_pcm_close(pcm_handle
);
689 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
690 snd_pcm_close(pcm_handle
);
700 if (ss
->channels
!= map
->channels
)
701 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
712 snd_pcm_t
*pa_alsa_open_by_template(
719 snd_pcm_uframes_t
*period_size
,
720 snd_pcm_uframes_t
*buffer_size
,
721 snd_pcm_uframes_t tsched_size
,
723 pa_bool_t
*use_tsched
,
724 pa_bool_t require_exact_channel_number
) {
726 snd_pcm_t
*pcm_handle
;
729 for (i
= template; *i
; i
++) {
732 d
= pa_replace(*i
, "%f", dev_id
);
734 pcm_handle
= pa_alsa_open_by_device_string(
745 require_exact_channel_number
);
756 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*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
));
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
) {
778 snd_pcm_status_t
*status
;
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
));
790 if ((err
= snd_pcm_status(pcm
, status
)) < 0) {
791 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err
));
795 if ((err
= snd_pcm_status_dump(status
, out
)) < 0) {
796 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
800 snd_output_buffer_string(out
, &s
);
801 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
805 snd_output_close(out
);
808 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
812 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
816 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
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) {
835 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 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
) {
847 if (pa_device_init_description(p
))
850 if (!(d
= pa_proplist_gets(p
, "alsa.card_name")))
851 d
= pa_proplist_gets(p
, "alsa.name");
856 k
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
);
859 pa_proplist_setf(p
, PA_PROP_DEVICE_DESCRIPTION
, _("%s %s"), d
, k
);
861 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, d
);
866 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
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
);
879 if (snd_card_get_longname(card
, &lcn
) >= 0) {
880 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
884 if ((dn
= pa_alsa_get_driver_name(card
))) {
885 pa_proplist_sets(p
, "alsa.driver_name", dn
);
890 pa_udev_get_info(card
, p
);
894 pa_hal_get_info(c
, p
, card
);
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
;
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
;
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
));
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
));
973 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
976 void pa_alsa_init_proplist_ctl(pa_proplist
*p
, const char *name
) {
979 snd_ctl_card_info_t
*info
;
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
));
991 if ((err
= snd_ctl_card_info(ctl
, info
)) < 0) {
992 pa_log_warn("Control device %s card info: %s", name
, snd_strerror(err
));
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
);
1006 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1007 snd_pcm_state_t state
;
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 */
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
));
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
));
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
));
1060 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1062 struct pollfd
*pollfd
;
1063 pa_rtpoll_item
*item
;
1067 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1068 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
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
);
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
;
1089 pa_assert(hwbuf_size
> 0);
1092 /* Some ALSA driver expose weird bugs, let's inform the user about
1093 * what is going on */
1095 n
= snd_pcm_avail(pcm
);
1100 k
= (size_t) n
* pa_frame_size(ss
);
1102 if (k
>= hwbuf_size
* 5 ||
1103 k
>= pa_bytes_per_second(ss
)*10) {
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."),
1110 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1113 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1116 /* Mhmm, let's try not to fail completely */
1117 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1123 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1130 pa_assert(hwbuf_size
> 0);
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)
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) {
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."),
1152 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1155 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1158 /* Mhmm, let's try not to fail completely */
1160 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1162 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
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
) {
1170 snd_pcm_uframes_t before
;
1177 pa_assert(hwbuf_size
> 0);
1182 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
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)
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."),
1198 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1201 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1207 char *pa_alsa_get_driver_name(int card
) {
1210 pa_assert(card
>= 0);
1212 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1219 n
= pa_xstrdup(pa_path_get_filename(m
));
1225 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1227 snd_pcm_info_t
* info
;
1228 snd_pcm_info_alloca(&info
);
1232 if (snd_pcm_info(pcm
, info
) < 0)
1235 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1238 return pa_alsa_get_driver_name(card
);
1241 char *pa_alsa_get_reserve_name(const char *device
) {
1247 if ((t
= strchr(device
, ':')))
1250 if ((i
= snd_card_get_index(device
)) < 0) {
1253 if (pa_atoi(device
, &k
) < 0)
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
);
1268 if (snd_pcm_info(pcm
, info
) < 0)
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
);
1280 if (snd_pcm_info(pcm
, info
) < 0)
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
;
1293 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1296 original
= snd_strerror(errnum
);
1299 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
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
);
1313 pa_bool_t
pa_alsa_may_tsched(pa_bool_t want
) {
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
1322 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
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.");