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 (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
257 /* try to disable period wakeups if hardware can do so */
258 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams
)) {
260 if (snd_pcm_hw_params_set_period_wakeup(pcm_handle
, hwparams
, FALSE
) < 0)
261 /* don't bail, keep going with default mode with period wakeups */
262 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret
));
264 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
266 pa_log_info("cannot disable ALSA period wakeups");
270 if ((ret
= set_format(pcm_handle
, hwparams
, &_ss
.format
)) < 0)
273 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &_ss
.rate
, NULL
)) < 0) {
274 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret
));
278 /* We ignore very small sampling rate deviations */
279 if (_ss
.rate
>= ss
->rate
*.95 && _ss
.rate
<= ss
->rate
*1.05)
282 if (require_exact_channel_number
) {
283 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, _ss
.channels
)) < 0) {
284 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss
.channels
, pa_alsa_strerror(ret
));
288 unsigned int c
= _ss
.channels
;
290 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0) {
291 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss
.channels
, pa_alsa_strerror(ret
));
298 if (_use_tsched
&& tsched_size
> 0) {
299 _buffer_size
= (snd_pcm_uframes_t
) (((uint64_t) tsched_size
* _ss
.rate
) / ss
->rate
);
300 _period_size
= _buffer_size
;
302 _period_size
= (snd_pcm_uframes_t
) (((uint64_t) _period_size
* _ss
.rate
) / ss
->rate
);
303 _buffer_size
= (snd_pcm_uframes_t
) (((uint64_t) _buffer_size
* _ss
.rate
) / ss
->rate
);
306 if (_buffer_size
> 0 || _period_size
> 0) {
307 snd_pcm_uframes_t max_frames
= 0;
309 if ((ret
= snd_pcm_hw_params_get_buffer_size_max(hwparams
, &max_frames
)) < 0)
310 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret
));
312 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames
* PA_MSEC_PER_SEC
/ _ss
.rate
));
314 /* Some ALSA drivers really don't like if we set the buffer
315 * size first and the number of periods second. (which would
316 * make a lot more sense to me) So, try a few combinations
317 * before we give up. */
319 if (_buffer_size
> 0 && _period_size
> 0) {
320 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
322 /* First try: set buffer size first, followed by period size */
323 if (set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
324 set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
325 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
326 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size
, (unsigned long) _period_size
);
330 /* Second try: set period size first, followed by buffer size */
331 if (set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
332 set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
333 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
334 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size
, (unsigned long) _buffer_size
);
339 if (_buffer_size
> 0) {
340 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
342 /* Third try: set only buffer size */
343 if (set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
344 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
345 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size
);
350 if (_period_size
> 0) {
351 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
353 /* Fourth try: set only period size */
354 if (set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
355 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
356 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size
);
362 pa_log_debug("Set neither period nor buffer size.");
364 /* Last chance, set nothing */
365 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0) {
366 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret
));
372 if (ss
->rate
!= _ss
.rate
)
373 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, _ss
.rate
);
375 if (ss
->channels
!= _ss
.channels
)
376 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, _ss
.channels
);
378 if (ss
->format
!= _ss
.format
)
379 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
));
381 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0) {
382 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret
));
386 if ((ret
= snd_pcm_hw_params_current(pcm_handle
, hwparams
)) < 0) {
387 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret
));
391 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
392 (ret
= snd_pcm_hw_params_get_buffer_size(hwparams
, &_buffer_size
)) < 0) {
393 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret
));
397 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
399 unsigned int no_wakeup
;
400 /* see if period wakeups were disabled */
401 snd_pcm_hw_params_get_period_wakeup(pcm_handle
, hwparams
, &no_wakeup
);
403 pa_log_info("ALSA period wakeups disabled");
405 pa_log_info("ALSA period wakeups were not disabled");
410 ss
->channels
= _ss
.channels
;
411 ss
->format
= _ss
.format
;
413 pa_assert(_period_size
> 0);
414 pa_assert(_buffer_size
> 0);
417 *buffer_size
= _buffer_size
;
420 *period_size
= _period_size
;
423 *use_mmap
= _use_mmap
;
426 *use_tsched
= _use_tsched
;
435 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
, pa_bool_t period_event
) {
436 snd_pcm_sw_params_t
*swparams
;
437 snd_pcm_uframes_t boundary
;
442 snd_pcm_sw_params_alloca(&swparams
);
444 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
445 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err
));
449 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, period_event
)) < 0) {
450 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err
));
454 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
455 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err
));
459 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
460 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err
));
464 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
465 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err
));
469 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
470 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err
));
474 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
475 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err
));
479 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
480 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err
));
487 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
493 snd_pcm_uframes_t
*period_size
,
494 snd_pcm_uframes_t
*buffer_size
,
495 snd_pcm_uframes_t tsched_size
,
497 pa_bool_t
*use_tsched
,
498 pa_alsa_profile_set
*ps
,
499 pa_alsa_mapping
**mapping
) {
502 snd_pcm_t
*pcm_handle
;
512 /* First we try to find a device string with a superset of the
513 * requested channel map. We iterate through our device table from
514 * top to bottom and take the first that matches. If we didn't
515 * find a working device that way, we iterate backwards, and check
516 * all devices that do not provide a superset of the requested
519 PA_HASHMAP_FOREACH(m
, ps
->mappings
, state
) {
520 if (!pa_channel_map_superset(&m
->channel_map
, map
))
523 pa_log_debug("Checking for superset %s (%s)", m
->name
, m
->device_strings
[0]);
525 pcm_handle
= pa_alsa_open_by_device_id_mapping(
546 PA_HASHMAP_FOREACH_BACKWARDS(m
, ps
->mappings
, state
) {
547 if (pa_channel_map_superset(&m
->channel_map
, map
))
550 pa_log_debug("Checking for subset %s (%s)", m
->name
, m
->device_strings
[0]);
552 pcm_handle
= pa_alsa_open_by_device_id_mapping(
573 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
574 d
= pa_sprintf_malloc("hw:%s", dev_id
);
575 pa_log_debug("Trying %s as last resort...", d
);
576 pcm_handle
= pa_alsa_open_by_device_string(
590 if (pcm_handle
&& mapping
)
596 snd_pcm_t
*pa_alsa_open_by_device_id_mapping(
602 snd_pcm_uframes_t
*period_size
,
603 snd_pcm_uframes_t
*buffer_size
,
604 snd_pcm_uframes_t tsched_size
,
606 pa_bool_t
*use_tsched
,
607 pa_alsa_mapping
*m
) {
609 snd_pcm_t
*pcm_handle
;
610 pa_sample_spec try_ss
;
611 pa_channel_map try_map
;
619 try_ss
.channels
= m
->channel_map
.channels
;
620 try_ss
.rate
= ss
->rate
;
621 try_ss
.format
= ss
->format
;
622 try_map
= m
->channel_map
;
624 pcm_handle
= pa_alsa_open_by_template(
643 pa_assert(map
->channels
== ss
->channels
);
648 snd_pcm_t
*pa_alsa_open_by_device_string(
654 snd_pcm_uframes_t
*period_size
,
655 snd_pcm_uframes_t
*buffer_size
,
656 snd_pcm_uframes_t tsched_size
,
658 pa_bool_t
*use_tsched
,
659 pa_bool_t require_exact_channel_number
) {
663 snd_pcm_t
*pcm_handle
;
664 pa_bool_t reformat
= FALSE
;
670 d
= pa_xstrdup(device
);
673 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
675 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
677 SND_PCM_NO_AUTO_RESAMPLE
|
678 SND_PCM_NO_AUTO_CHANNELS
|
679 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
680 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
684 pa_log_debug("Managed to open %s", d
);
686 if ((err
= pa_alsa_set_hw_params(
694 require_exact_channel_number
)) < 0) {
699 snd_pcm_close(pcm_handle
);
703 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
704 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
707 t
= pa_sprintf_malloc("plug:%s", d
);
713 snd_pcm_close(pcm_handle
);
717 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
718 snd_pcm_close(pcm_handle
);
728 if (ss
->channels
!= map
->channels
)
729 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
740 snd_pcm_t
*pa_alsa_open_by_template(
747 snd_pcm_uframes_t
*period_size
,
748 snd_pcm_uframes_t
*buffer_size
,
749 snd_pcm_uframes_t tsched_size
,
751 pa_bool_t
*use_tsched
,
752 pa_bool_t require_exact_channel_number
) {
754 snd_pcm_t
*pcm_handle
;
757 for (i
= template; *i
; i
++) {
760 d
= pa_replace(*i
, "%f", dev_id
);
762 pcm_handle
= pa_alsa_open_by_device_string(
773 require_exact_channel_number
);
784 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
790 pa_assert_se(snd_output_buffer_open(&out
) == 0);
792 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
793 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
796 snd_output_buffer_string(out
, &s
);
797 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
800 pa_assert_se(snd_output_close(out
) == 0);
803 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
806 snd_pcm_status_t
*status
;
811 snd_pcm_status_alloca(&status
);
813 if ((err
= snd_output_buffer_open(&out
)) < 0) {
814 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err
));
818 if ((err
= snd_pcm_status(pcm
, status
)) < 0) {
819 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err
));
823 if ((err
= snd_pcm_status_dump(status
, out
)) < 0) {
824 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
828 snd_output_buffer_string(out
, &s
);
829 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
833 snd_output_close(out
);
836 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
840 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
844 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
851 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
853 void pa_alsa_refcnt_inc(void) {
854 /* This is not really thread safe, but we do our best */
856 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
857 snd_lib_error_set_handler(alsa_error_handler
);
860 void pa_alsa_refcnt_dec(void) {
863 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
866 snd_lib_error_set_handler(NULL
);
867 snd_config_update_free_global();
871 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
875 if (pa_device_init_description(p
))
878 if (!(d
= pa_proplist_gets(p
, "alsa.card_name")))
879 d
= pa_proplist_gets(p
, "alsa.name");
884 k
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
);
887 pa_proplist_setf(p
, PA_PROP_DEVICE_DESCRIPTION
, _("%s %s"), d
, k
);
889 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, d
);
894 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
898 pa_assert(card
>= 0);
900 pa_proplist_setf(p
, "alsa.card", "%i", card
);
902 if (snd_card_get_name(card
, &cn
) >= 0) {
903 pa_proplist_sets(p
, "alsa.card_name", pa_strip(cn
));
907 if (snd_card_get_longname(card
, &lcn
) >= 0) {
908 pa_proplist_sets(p
, "alsa.long_card_name", pa_strip(lcn
));
912 if ((dn
= pa_alsa_get_driver_name(card
))) {
913 pa_proplist_sets(p
, "alsa.driver_name", dn
);
918 pa_udev_get_info(card
, p
);
922 pa_hal_get_info(c
, p
, card
);
926 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
928 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
929 [SND_PCM_CLASS_GENERIC
] = "generic",
930 [SND_PCM_CLASS_MULTI
] = "multi",
931 [SND_PCM_CLASS_MODEM
] = "modem",
932 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
934 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
935 [SND_PCM_CLASS_GENERIC
] = "sound",
936 [SND_PCM_CLASS_MULTI
] = NULL
,
937 [SND_PCM_CLASS_MODEM
] = "modem",
938 [SND_PCM_CLASS_DIGITIZER
] = NULL
940 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
941 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
942 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
945 snd_pcm_class_t
class;
946 snd_pcm_subclass_t subclass
;
947 const char *n
, *id
, *sdn
;
953 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
955 if ((class = snd_pcm_info_get_class(pcm_info
)) <= SND_PCM_CLASS_LAST
) {
956 if (class_table
[class])
957 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
958 if (alsa_class_table
[class])
959 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
962 if ((subclass
= snd_pcm_info_get_subclass(pcm_info
)) <= SND_PCM_SUBCLASS_LAST
)
963 if (alsa_subclass_table
[subclass
])
964 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
966 if ((n
= snd_pcm_info_get_name(pcm_info
))) {
967 char *t
= pa_xstrdup(n
);
968 pa_proplist_sets(p
, "alsa.name", pa_strip(t
));
972 if ((id
= snd_pcm_info_get_id(pcm_info
)))
973 pa_proplist_sets(p
, "alsa.id", id
);
975 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
976 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
977 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
979 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
981 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
982 pa_alsa_init_proplist_card(c
, p
, card
);
985 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
) {
986 snd_pcm_hw_params_t
*hwparams
;
987 snd_pcm_info_t
*info
;
990 snd_pcm_hw_params_alloca(&hwparams
);
991 snd_pcm_info_alloca(&info
);
993 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
994 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
997 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
998 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1001 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1002 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
1004 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1007 void pa_alsa_init_proplist_ctl(pa_proplist
*p
, const char *name
) {
1010 snd_ctl_card_info_t
*info
;
1015 snd_ctl_card_info_alloca(&info
);
1017 if ((err
= snd_ctl_open(&ctl
, name
, 0)) < 0) {
1018 pa_log_warn("Error opening low-level control device '%s': %s", name
, snd_strerror(err
));
1022 if ((err
= snd_ctl_card_info(ctl
, info
)) < 0) {
1023 pa_log_warn("Control device %s card info: %s", name
, snd_strerror(err
));
1028 if ((t
= snd_ctl_card_info_get_mixername(info
)) && *t
)
1029 pa_proplist_sets(p
, "alsa.mixer_name", t
);
1031 if ((t
= snd_ctl_card_info_get_components(info
)) && *t
)
1032 pa_proplist_sets(p
, "alsa.components", t
);
1037 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1038 snd_pcm_state_t state
;
1043 if (revents
& POLLERR
)
1044 pa_log_debug("Got POLLERR from ALSA");
1045 if (revents
& POLLNVAL
)
1046 pa_log_warn("Got POLLNVAL from ALSA");
1047 if (revents
& POLLHUP
)
1048 pa_log_warn("Got POLLHUP from ALSA");
1049 if (revents
& POLLPRI
)
1050 pa_log_warn("Got POLLPRI from ALSA");
1051 if (revents
& POLLIN
)
1052 pa_log_debug("Got POLLIN from ALSA");
1053 if (revents
& POLLOUT
)
1054 pa_log_debug("Got POLLOUT from ALSA");
1056 state
= snd_pcm_state(pcm
);
1057 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1059 /* Try to recover from this error */
1063 case SND_PCM_STATE_XRUN
:
1064 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1065 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1070 case SND_PCM_STATE_SUSPENDED
:
1071 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1072 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1081 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1082 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1091 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1093 struct pollfd
*pollfd
;
1094 pa_rtpoll_item
*item
;
1098 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1099 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1103 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1104 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1106 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1107 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1108 pa_rtpoll_item_free(item
);
1115 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1116 snd_pcm_sframes_t n
;
1120 pa_assert(hwbuf_size
> 0);
1123 /* Some ALSA driver expose weird bugs, let's inform the user about
1124 * what is going on */
1126 n
= snd_pcm_avail(pcm
);
1131 k
= (size_t) n
* pa_frame_size(ss
);
1133 if (PA_UNLIKELY(k
>= hwbuf_size
* 5 ||
1134 k
>= pa_bytes_per_second(ss
)*10)) {
1137 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1138 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1139 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1141 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1144 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1147 /* Mhmm, let's try not to fail completely */
1148 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1154 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
) {
1158 snd_pcm_sframes_t avail
= 0;
1162 pa_assert(hwbuf_size
> 0);
1165 /* Some ALSA driver expose weird bugs, let's inform the user about
1166 * what is going on. We're going to get both the avail and delay values so
1167 * that we can compare and check them for capture */
1169 if ((r
= snd_pcm_avail_delay(pcm
, &avail
, delay
)) < 0)
1172 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1174 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1176 if (PA_UNLIKELY(abs_k
>= hwbuf_size
* 5 ||
1177 abs_k
>= pa_bytes_per_second(ss
)*10)) {
1180 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1181 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1182 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1185 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1188 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1191 /* Mhmm, let's try not to fail completely */
1193 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1195 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1199 abs_k
= (size_t) avail
* pa_frame_size(ss
);
1201 if (PA_UNLIKELY(abs_k
>= hwbuf_size
* 5 ||
1202 abs_k
>= pa_bytes_per_second(ss
)*10)) {
1205 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1206 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1207 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1209 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1212 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1215 /* Mhmm, let's try not to fail completely */
1216 avail
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1219 if (PA_UNLIKELY(*delay
< avail
)) {
1221 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1222 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1223 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1224 (unsigned long) *delay
,
1225 (unsigned long) avail
,
1228 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1239 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
) {
1241 snd_pcm_uframes_t before
;
1248 pa_assert(hwbuf_size
> 0);
1253 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1258 k
= (size_t) *frames
* pa_frame_size(ss
);
1260 if (PA_UNLIKELY(*frames
> before
||
1261 k
>= hwbuf_size
* 3 ||
1262 k
>= pa_bytes_per_second(ss
)*10))
1264 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1265 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1266 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1268 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1271 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1277 char *pa_alsa_get_driver_name(int card
) {
1280 pa_assert(card
>= 0);
1282 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1289 n
= pa_xstrdup(pa_path_get_filename(m
));
1295 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1297 snd_pcm_info_t
* info
;
1298 snd_pcm_info_alloca(&info
);
1302 if (snd_pcm_info(pcm
, info
) < 0)
1305 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1308 return pa_alsa_get_driver_name(card
);
1311 char *pa_alsa_get_reserve_name(const char *device
) {
1317 if ((t
= strchr(device
, ':')))
1320 if ((i
= snd_card_get_index(device
)) < 0) {
1323 if (pa_atoi(device
, &k
) < 0)
1329 return pa_sprintf_malloc("Audio%i", i
);
1332 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1333 snd_pcm_info_t
* info
;
1334 snd_pcm_info_alloca(&info
);
1338 if (snd_pcm_info(pcm
, info
) < 0)
1341 return snd_pcm_info_get_card(info
) >= 0;
1344 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1345 snd_pcm_info_t
* info
;
1346 snd_pcm_info_alloca(&info
);
1350 if (snd_pcm_info(pcm
, info
) < 0)
1353 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1356 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1358 const char* pa_alsa_strerror(int errnum
) {
1359 const char *original
= NULL
;
1360 char *translated
, *t
;
1363 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1366 original
= snd_strerror(errnum
);
1369 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1373 if (!(translated
= pa_locale_to_utf8(original
))) {
1374 pa_log_warn("Unable to convert error string to locale, filtering.");
1375 translated
= pa_utf8_filter(original
);
1378 PA_STATIC_TLS_SET(cstrerror
, translated
);
1383 pa_bool_t
pa_alsa_may_tsched(pa_bool_t want
) {
1388 if (!pa_rtclock_hrtimer()) {
1389 /* We cannot depend on being woken up in time when the timers
1390 are inaccurate, so let's fallback to classic IO based playback
1392 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1395 if (pa_running_in_vm()) {
1396 /* We cannot depend on being woken up when we ask for in a VM,
1397 * so let's fallback to classic IO based playback then. */
1398 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");