2 This file is part of PulseAudio.
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/types.h>
28 #include <asoundlib.h>
30 #include <pulse/sample.h>
31 #include <pulse/xmalloc.h>
32 #include <pulse/timeval.h>
33 #include <pulse/util.h>
34 #include <pulse/utf8.h>
36 #include <pulsecore/i18n.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/atomic.h>
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/thread.h>
43 #include <pulsecore/conf-parser.h>
44 #include <pulsecore/core-rtclock.h>
46 #include "alsa-util.h"
47 #include "alsa-mixer.h"
50 #include "udev-util.h"
53 static int set_format(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, pa_sample_format_t
*f
) {
55 static const snd_pcm_format_t format_trans
[] = {
56 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
57 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
58 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
59 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
60 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
61 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
62 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
63 [PA_SAMPLE_S32LE
] = SND_PCM_FORMAT_S32_LE
,
64 [PA_SAMPLE_S32BE
] = SND_PCM_FORMAT_S32_BE
,
65 [PA_SAMPLE_S24LE
] = SND_PCM_FORMAT_S24_3LE
,
66 [PA_SAMPLE_S24BE
] = SND_PCM_FORMAT_S24_3BE
,
67 [PA_SAMPLE_S24_32LE
] = SND_PCM_FORMAT_S24_LE
,
68 [PA_SAMPLE_S24_32BE
] = SND_PCM_FORMAT_S24_BE
,
71 static const pa_sample_format_t try_order
[] = {
90 pa_assert(pcm_handle
);
94 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
97 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
98 snd_pcm_format_description(format_trans
[*f
]),
99 pa_alsa_strerror(ret
));
101 if (*f
== PA_SAMPLE_FLOAT32BE
)
102 *f
= PA_SAMPLE_FLOAT32LE
;
103 else if (*f
== PA_SAMPLE_FLOAT32LE
)
104 *f
= PA_SAMPLE_FLOAT32BE
;
105 else if (*f
== PA_SAMPLE_S24BE
)
106 *f
= PA_SAMPLE_S24LE
;
107 else if (*f
== PA_SAMPLE_S24LE
)
108 *f
= PA_SAMPLE_S24BE
;
109 else if (*f
== PA_SAMPLE_S24_32BE
)
110 *f
= PA_SAMPLE_S24_32LE
;
111 else if (*f
== PA_SAMPLE_S24_32LE
)
112 *f
= PA_SAMPLE_S24_32BE
;
113 else if (*f
== PA_SAMPLE_S16BE
)
114 *f
= PA_SAMPLE_S16LE
;
115 else if (*f
== PA_SAMPLE_S16LE
)
116 *f
= PA_SAMPLE_S16BE
;
117 else if (*f
== PA_SAMPLE_S32BE
)
118 *f
= PA_SAMPLE_S32LE
;
119 else if (*f
== PA_SAMPLE_S32LE
)
120 *f
= PA_SAMPLE_S32BE
;
124 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
127 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
128 snd_pcm_format_description(format_trans
[*f
]),
129 pa_alsa_strerror(ret
));
133 for (i
= 0; i
< PA_ELEMENTSOF(try_order
); i
++) {
136 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
139 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
140 snd_pcm_format_description(format_trans
[*f
]),
141 pa_alsa_strerror(ret
));
147 static int set_period_size(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, snd_pcm_uframes_t size
) {
151 pa_assert(pcm_handle
);
156 if (snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, &s
, &d
) < 0) {
159 if (snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, &s
, &d
) < 0) {
162 if ((ret
= snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, &s
, &d
)) < 0) {
163 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret
));
172 static int set_buffer_size(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, snd_pcm_uframes_t size
) {
175 pa_assert(pcm_handle
);
178 if ((ret
= snd_pcm_hw_params_set_buffer_size_near(pcm_handle
, hwparams
, &size
)) < 0) {
179 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret
));
186 /* Set the hardware parameters of the given ALSA device. Returns the
187 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
188 int pa_alsa_set_hw_params(
189 snd_pcm_t
*pcm_handle
,
191 snd_pcm_uframes_t
*period_size
,
192 snd_pcm_uframes_t
*buffer_size
,
193 snd_pcm_uframes_t tsched_size
,
195 pa_bool_t
*use_tsched
,
196 pa_bool_t require_exact_channel_number
) {
199 snd_pcm_hw_params_t
*hwparams
, *hwparams_copy
;
201 snd_pcm_uframes_t _period_size
= period_size
? *period_size
: 0;
202 snd_pcm_uframes_t _buffer_size
= buffer_size
? *buffer_size
: 0;
203 pa_bool_t _use_mmap
= use_mmap
&& *use_mmap
;
204 pa_bool_t _use_tsched
= use_tsched
&& *use_tsched
;
205 pa_sample_spec _ss
= *ss
;
207 pa_assert(pcm_handle
);
210 snd_pcm_hw_params_alloca(&hwparams
);
211 snd_pcm_hw_params_alloca(&hwparams_copy
);
213 if ((ret
= snd_pcm_hw_params_any(pcm_handle
, hwparams
)) < 0) {
214 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret
));
218 if ((ret
= snd_pcm_hw_params_set_rate_resample(pcm_handle
, hwparams
, 0)) < 0) {
219 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret
));
225 if (snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) < 0) {
227 /* mmap() didn't work, fall back to interleaved */
229 if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0) {
230 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret
));
237 } else if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0) {
238 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret
));
245 if (!pa_alsa_pcm_is_hw(pcm_handle
))
248 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
251 /* try to disable period wakeups if hardware can do so */
252 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams
)) {
254 if ((ret
= snd_pcm_hw_params_set_period_wakeup(pcm_handle
, hwparams
, FALSE
)) < 0)
255 /* don't bail, keep going with default mode with period wakeups */
256 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret
));
258 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
260 pa_log_info("cannot disable ALSA period wakeups");
264 if ((ret
= set_format(pcm_handle
, hwparams
, &_ss
.format
)) < 0)
267 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &_ss
.rate
, NULL
)) < 0) {
268 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret
));
272 /* We ignore very small sampling rate deviations */
273 if (_ss
.rate
>= ss
->rate
*.95 && _ss
.rate
<= ss
->rate
*1.05)
276 if (require_exact_channel_number
) {
277 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, _ss
.channels
)) < 0) {
278 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss
.channels
, pa_alsa_strerror(ret
));
282 unsigned int c
= _ss
.channels
;
284 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0) {
285 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss
.channels
, pa_alsa_strerror(ret
));
292 if (_use_tsched
&& tsched_size
> 0) {
293 _buffer_size
= (snd_pcm_uframes_t
) (((uint64_t) tsched_size
* _ss
.rate
) / ss
->rate
);
294 _period_size
= _buffer_size
;
296 _period_size
= (snd_pcm_uframes_t
) (((uint64_t) _period_size
* _ss
.rate
) / ss
->rate
);
297 _buffer_size
= (snd_pcm_uframes_t
) (((uint64_t) _buffer_size
* _ss
.rate
) / ss
->rate
);
300 if (_buffer_size
> 0 || _period_size
> 0) {
301 snd_pcm_uframes_t max_frames
= 0;
303 if ((ret
= snd_pcm_hw_params_get_buffer_size_max(hwparams
, &max_frames
)) < 0)
304 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret
));
306 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames
* PA_MSEC_PER_SEC
/ _ss
.rate
));
308 /* Some ALSA drivers really don't like if we set the buffer
309 * size first and the number of periods second (which would
310 * make a lot more sense to me). So, try a few combinations
311 * before we give up. */
313 if (_buffer_size
> 0 && _period_size
> 0) {
314 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
316 /* First try: set buffer size first, followed by period size */
317 if (set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
318 set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
319 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
320 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size
, (unsigned long) _period_size
);
324 /* Second try: set period size first, followed by buffer size */
325 if (set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
326 set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
327 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
328 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size
, (unsigned long) _buffer_size
);
333 if (_buffer_size
> 0) {
334 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
336 /* Third try: set only buffer size */
337 if (set_buffer_size(pcm_handle
, hwparams_copy
, _buffer_size
) >= 0 &&
338 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
339 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size
);
344 if (_period_size
> 0) {
345 snd_pcm_hw_params_copy(hwparams_copy
, hwparams
);
347 /* Fourth try: set only period size */
348 if (set_period_size(pcm_handle
, hwparams_copy
, _period_size
) >= 0 &&
349 snd_pcm_hw_params(pcm_handle
, hwparams_copy
) >= 0) {
350 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size
);
356 pa_log_debug("Set neither period nor buffer size.");
358 /* Last chance, set nothing */
359 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0) {
360 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret
));
366 if (ss
->rate
!= _ss
.rate
)
367 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, _ss
.rate
);
369 if (ss
->channels
!= _ss
.channels
)
370 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, _ss
.channels
);
372 if (ss
->format
!= _ss
.format
)
373 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
));
375 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0) {
376 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret
));
380 if ((ret
= snd_pcm_hw_params_current(pcm_handle
, hwparams
)) < 0) {
381 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret
));
385 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
386 (ret
= snd_pcm_hw_params_get_buffer_size(hwparams
, &_buffer_size
)) < 0) {
387 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret
));
391 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
393 unsigned int no_wakeup
;
394 /* see if period wakeups were disabled */
395 snd_pcm_hw_params_get_period_wakeup(pcm_handle
, hwparams
, &no_wakeup
);
397 pa_log_info("ALSA period wakeups disabled");
399 pa_log_info("ALSA period wakeups were not disabled");
404 ss
->channels
= _ss
.channels
;
405 ss
->format
= _ss
.format
;
407 pa_assert(_period_size
> 0);
408 pa_assert(_buffer_size
> 0);
411 *buffer_size
= _buffer_size
;
414 *period_size
= _period_size
;
417 *use_mmap
= _use_mmap
;
420 *use_tsched
= _use_tsched
;
429 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
, pa_bool_t period_event
) {
430 snd_pcm_sw_params_t
*swparams
;
431 snd_pcm_uframes_t boundary
;
436 snd_pcm_sw_params_alloca(&swparams
);
438 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
439 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err
));
443 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, period_event
)) < 0) {
444 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err
));
448 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
449 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err
));
453 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
454 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err
));
458 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
459 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err
));
463 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
464 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err
));
468 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
469 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err
));
473 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
474 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err
));
481 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
487 snd_pcm_uframes_t
*period_size
,
488 snd_pcm_uframes_t
*buffer_size
,
489 snd_pcm_uframes_t tsched_size
,
491 pa_bool_t
*use_tsched
,
492 pa_alsa_profile_set
*ps
,
493 pa_alsa_mapping
**mapping
) {
496 snd_pcm_t
*pcm_handle
;
506 /* First we try to find a device string with a superset of the
507 * requested channel map. We iterate through our device table from
508 * top to bottom and take the first that matches. If we didn't
509 * find a working device that way, we iterate backwards, and check
510 * all devices that do not provide a superset of the requested
513 PA_HASHMAP_FOREACH(m
, ps
->mappings
, state
) {
514 if (!pa_channel_map_superset(&m
->channel_map
, map
))
517 pa_log_debug("Checking for superset %s (%s)", m
->name
, m
->device_strings
[0]);
519 pcm_handle
= pa_alsa_open_by_device_id_mapping(
540 PA_HASHMAP_FOREACH_BACKWARDS(m
, ps
->mappings
, state
) {
541 if (pa_channel_map_superset(&m
->channel_map
, map
))
544 pa_log_debug("Checking for subset %s (%s)", m
->name
, m
->device_strings
[0]);
546 pcm_handle
= pa_alsa_open_by_device_id_mapping(
567 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
568 d
= pa_sprintf_malloc("hw:%s", dev_id
);
569 pa_log_debug("Trying %s as last resort...", d
);
570 pcm_handle
= pa_alsa_open_by_device_string(
584 if (pcm_handle
&& mapping
)
590 snd_pcm_t
*pa_alsa_open_by_device_id_mapping(
596 snd_pcm_uframes_t
*period_size
,
597 snd_pcm_uframes_t
*buffer_size
,
598 snd_pcm_uframes_t tsched_size
,
600 pa_bool_t
*use_tsched
,
601 pa_alsa_mapping
*m
) {
603 snd_pcm_t
*pcm_handle
;
604 pa_sample_spec try_ss
;
605 pa_channel_map try_map
;
613 try_ss
.channels
= m
->channel_map
.channels
;
614 try_ss
.rate
= ss
->rate
;
615 try_ss
.format
= ss
->format
;
616 try_map
= m
->channel_map
;
618 pcm_handle
= pa_alsa_open_by_template(
637 pa_assert(map
->channels
== ss
->channels
);
642 snd_pcm_t
*pa_alsa_open_by_device_string(
648 snd_pcm_uframes_t
*period_size
,
649 snd_pcm_uframes_t
*buffer_size
,
650 snd_pcm_uframes_t tsched_size
,
652 pa_bool_t
*use_tsched
,
653 pa_bool_t require_exact_channel_number
) {
657 snd_pcm_t
*pcm_handle
;
658 pa_bool_t reformat
= FALSE
;
664 d
= pa_xstrdup(device
);
667 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
669 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
671 SND_PCM_NO_AUTO_RESAMPLE
|
672 SND_PCM_NO_AUTO_CHANNELS
|
673 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
674 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
678 pa_log_debug("Managed to open %s", d
);
680 if ((err
= pa_alsa_set_hw_params(
688 require_exact_channel_number
)) < 0) {
693 snd_pcm_close(pcm_handle
);
697 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
698 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
701 t
= pa_sprintf_malloc("plug:%s", d
);
707 snd_pcm_close(pcm_handle
);
711 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
712 snd_pcm_close(pcm_handle
);
722 if (ss
->channels
!= map
->channels
)
723 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
734 snd_pcm_t
*pa_alsa_open_by_template(
741 snd_pcm_uframes_t
*period_size
,
742 snd_pcm_uframes_t
*buffer_size
,
743 snd_pcm_uframes_t tsched_size
,
745 pa_bool_t
*use_tsched
,
746 pa_bool_t require_exact_channel_number
) {
748 snd_pcm_t
*pcm_handle
;
751 for (i
= template; *i
; i
++) {
754 d
= pa_replace(*i
, "%f", dev_id
);
756 pcm_handle
= pa_alsa_open_by_device_string(
767 require_exact_channel_number
);
778 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
784 pa_assert_se(snd_output_buffer_open(&out
) == 0);
786 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
787 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
790 snd_output_buffer_string(out
, &s
);
791 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
794 pa_assert_se(snd_output_close(out
) == 0);
797 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
800 snd_pcm_status_t
*status
;
805 snd_pcm_status_alloca(&status
);
807 if ((err
= snd_output_buffer_open(&out
)) < 0) {
808 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err
));
812 if ((err
= snd_pcm_status(pcm
, status
)) < 0) {
813 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err
));
817 if ((err
= snd_pcm_status_dump(status
, out
)) < 0) {
818 pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err
));
822 snd_output_buffer_string(out
, &s
);
823 pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s
));
827 snd_output_close(out
);
830 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
834 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
838 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
845 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
847 void pa_alsa_refcnt_inc(void) {
848 /* This is not really thread safe, but we do our best */
850 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
851 snd_lib_error_set_handler(alsa_error_handler
);
854 void pa_alsa_refcnt_dec(void) {
857 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
860 snd_lib_error_set_handler(NULL
);
861 snd_config_update_free_global();
865 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
869 if (pa_device_init_description(p
))
872 if (!(d
= pa_proplist_gets(p
, "alsa.card_name")))
873 d
= pa_proplist_gets(p
, "alsa.name");
878 k
= pa_proplist_gets(p
, PA_PROP_DEVICE_PROFILE_DESCRIPTION
);
881 pa_proplist_setf(p
, PA_PROP_DEVICE_DESCRIPTION
, "%s %s", d
, k
);
883 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, d
);
888 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
892 pa_assert(card
>= 0);
894 pa_proplist_setf(p
, "alsa.card", "%i", card
);
896 if (snd_card_get_name(card
, &cn
) >= 0) {
897 pa_proplist_sets(p
, "alsa.card_name", pa_strip(cn
));
901 if (snd_card_get_longname(card
, &lcn
) >= 0) {
902 pa_proplist_sets(p
, "alsa.long_card_name", pa_strip(lcn
));
906 if ((dn
= pa_alsa_get_driver_name(card
))) {
907 pa_proplist_sets(p
, "alsa.driver_name", dn
);
912 pa_udev_get_info(card
, p
);
916 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
918 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
919 [SND_PCM_CLASS_GENERIC
] = "generic",
920 [SND_PCM_CLASS_MULTI
] = "multi",
921 [SND_PCM_CLASS_MODEM
] = "modem",
922 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
924 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
925 [SND_PCM_CLASS_GENERIC
] = "sound",
926 [SND_PCM_CLASS_MULTI
] = NULL
,
927 [SND_PCM_CLASS_MODEM
] = "modem",
928 [SND_PCM_CLASS_DIGITIZER
] = NULL
930 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
931 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
932 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
935 snd_pcm_class_t
class;
936 snd_pcm_subclass_t subclass
;
937 const char *n
, *id
, *sdn
;
943 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
945 if ((class = snd_pcm_info_get_class(pcm_info
)) <= SND_PCM_CLASS_LAST
) {
946 if (class_table
[class])
947 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
948 if (alsa_class_table
[class])
949 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
952 if ((subclass
= snd_pcm_info_get_subclass(pcm_info
)) <= SND_PCM_SUBCLASS_LAST
)
953 if (alsa_subclass_table
[subclass
])
954 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
956 if ((n
= snd_pcm_info_get_name(pcm_info
))) {
957 char *t
= pa_xstrdup(n
);
958 pa_proplist_sets(p
, "alsa.name", pa_strip(t
));
962 if ((id
= snd_pcm_info_get_id(pcm_info
)))
963 pa_proplist_sets(p
, "alsa.id", id
);
965 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
966 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
967 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
969 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
971 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
972 pa_alsa_init_proplist_card(c
, p
, card
);
975 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
) {
976 snd_pcm_hw_params_t
*hwparams
;
977 snd_pcm_info_t
*info
;
980 snd_pcm_hw_params_alloca(&hwparams
);
981 snd_pcm_info_alloca(&info
);
983 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
984 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
987 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
988 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
991 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
992 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
994 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
997 void pa_alsa_init_proplist_ctl(pa_proplist
*p
, const char *name
) {
1000 snd_ctl_card_info_t
*info
;
1005 snd_ctl_card_info_alloca(&info
);
1007 if ((err
= snd_ctl_open(&ctl
, name
, 0)) < 0) {
1008 pa_log_warn("Error opening low-level control device '%s': %s", name
, snd_strerror(err
));
1012 if ((err
= snd_ctl_card_info(ctl
, info
)) < 0) {
1013 pa_log_warn("Control device %s card info: %s", name
, snd_strerror(err
));
1018 if ((t
= snd_ctl_card_info_get_mixername(info
)) && *t
)
1019 pa_proplist_sets(p
, "alsa.mixer_name", t
);
1021 if ((t
= snd_ctl_card_info_get_components(info
)) && *t
)
1022 pa_proplist_sets(p
, "alsa.components", t
);
1027 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1028 snd_pcm_state_t state
;
1033 if (revents
& POLLERR
)
1034 pa_log_debug("Got POLLERR from ALSA");
1035 if (revents
& POLLNVAL
)
1036 pa_log_warn("Got POLLNVAL from ALSA");
1037 if (revents
& POLLHUP
)
1038 pa_log_warn("Got POLLHUP from ALSA");
1039 if (revents
& POLLPRI
)
1040 pa_log_warn("Got POLLPRI from ALSA");
1041 if (revents
& POLLIN
)
1042 pa_log_debug("Got POLLIN from ALSA");
1043 if (revents
& POLLOUT
)
1044 pa_log_debug("Got POLLOUT from ALSA");
1046 state
= snd_pcm_state(pcm
);
1047 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1049 /* Try to recover from this error */
1053 case SND_PCM_STATE_XRUN
:
1054 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1055 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1060 case SND_PCM_STATE_SUSPENDED
:
1061 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1062 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1071 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1072 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1081 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1083 struct pollfd
*pollfd
;
1084 pa_rtpoll_item
*item
;
1088 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1089 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1093 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1094 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1096 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1097 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1098 pa_rtpoll_item_free(item
);
1105 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1106 snd_pcm_sframes_t n
;
1110 pa_assert(hwbuf_size
> 0);
1113 /* Some ALSA driver expose weird bugs, let's inform the user about
1114 * what is going on */
1116 n
= snd_pcm_avail(pcm
);
1121 k
= (size_t) n
* pa_frame_size(ss
);
1123 if (PA_UNLIKELY(k
>= hwbuf_size
* 5 ||
1124 k
>= pa_bytes_per_second(ss
)*10)) {
1127 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1128 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1129 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1131 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1134 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1137 /* Mhmm, let's try not to fail completely */
1138 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1144 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
) {
1148 snd_pcm_sframes_t avail
= 0;
1152 pa_assert(hwbuf_size
> 0);
1155 /* Some ALSA driver expose weird bugs, let's inform the user about
1156 * what is going on. We're going to get both the avail and delay values so
1157 * that we can compare and check them for capture */
1159 if ((r
= snd_pcm_avail_delay(pcm
, &avail
, delay
)) < 0)
1162 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1164 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1166 if (PA_UNLIKELY(abs_k
>= hwbuf_size
* 5 ||
1167 abs_k
>= pa_bytes_per_second(ss
)*10)) {
1170 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1171 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1172 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1175 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1178 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1181 /* Mhmm, let's try not to fail completely */
1183 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1185 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1189 abs_k
= (size_t) avail
* pa_frame_size(ss
);
1191 if (PA_UNLIKELY(abs_k
>= hwbuf_size
* 5 ||
1192 abs_k
>= pa_bytes_per_second(ss
)*10)) {
1195 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1196 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1197 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1199 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1202 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1205 /* Mhmm, let's try not to fail completely */
1206 avail
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1209 if (PA_UNLIKELY(*delay
< avail
)) {
1211 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1212 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1213 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1214 (unsigned long) *delay
,
1215 (unsigned long) avail
,
1218 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1229 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
) {
1231 snd_pcm_uframes_t before
;
1238 pa_assert(hwbuf_size
> 0);
1243 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1248 k
= (size_t) *frames
* pa_frame_size(ss
);
1250 if (PA_UNLIKELY(*frames
> before
||
1251 k
>= hwbuf_size
* 3 ||
1252 k
>= pa_bytes_per_second(ss
)*10))
1254 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1255 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1256 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1258 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1261 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1267 char *pa_alsa_get_driver_name(int card
) {
1270 pa_assert(card
>= 0);
1272 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1279 n
= pa_xstrdup(pa_path_get_filename(m
));
1285 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1287 snd_pcm_info_t
* info
;
1288 snd_pcm_info_alloca(&info
);
1292 if (snd_pcm_info(pcm
, info
) < 0)
1295 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1298 return pa_alsa_get_driver_name(card
);
1301 char *pa_alsa_get_reserve_name(const char *device
) {
1307 if ((t
= strchr(device
, ':')))
1310 if ((i
= snd_card_get_index(device
)) < 0) {
1313 if (pa_atoi(device
, &k
) < 0)
1319 return pa_sprintf_malloc("Audio%i", i
);
1322 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t
*pcm
) {
1323 static unsigned int all_rates
[] = { 8000, 11025, 12000,
1324 16000, 22050, 24000,
1325 32000, 44100, 48000,
1326 64000, 88200, 96000,
1327 128000, 176400, 192000,
1329 pa_bool_t supported
[PA_ELEMENTSOF(all_rates
)] = { FALSE
, };
1330 snd_pcm_hw_params_t
*hwparams
;
1331 unsigned int i
, j
, n
, *rates
= NULL
;
1334 snd_pcm_hw_params_alloca(&hwparams
);
1336 if ((ret
= snd_pcm_hw_params_any(pcm
, hwparams
)) < 0) {
1337 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret
));
1341 for (i
= 0, n
= 0; i
< PA_ELEMENTSOF(all_rates
); i
++) {
1342 if (snd_pcm_hw_params_test_rate(pcm
, hwparams
, all_rates
[i
], 0) == 0) {
1343 supported
[i
] = TRUE
;
1351 rates
= pa_xnew(unsigned int, n
+ 1);
1353 for (i
= 0, j
= 0; i
< PA_ELEMENTSOF(all_rates
); i
++) {
1355 rates
[j
++] = all_rates
[i
];
1363 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1364 snd_pcm_info_t
* info
;
1365 snd_pcm_info_alloca(&info
);
1369 if (snd_pcm_info(pcm
, info
) < 0)
1372 return snd_pcm_info_get_card(info
) >= 0;
1375 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1376 snd_pcm_info_t
* info
;
1377 snd_pcm_info_alloca(&info
);
1381 if (snd_pcm_info(pcm
, info
) < 0)
1384 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1387 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1389 const char* pa_alsa_strerror(int errnum
) {
1390 const char *original
= NULL
;
1391 char *translated
, *t
;
1394 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1397 original
= snd_strerror(errnum
);
1400 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1404 if (!(translated
= pa_locale_to_utf8(original
))) {
1405 pa_log_warn("Unable to convert error string to locale, filtering.");
1406 translated
= pa_utf8_filter(original
);
1409 PA_STATIC_TLS_SET(cstrerror
, translated
);
1414 pa_bool_t
pa_alsa_may_tsched(pa_bool_t want
) {
1419 if (!pa_rtclock_hrtimer()) {
1420 /* We cannot depend on being woken up in time when the timers
1421 are inaccurate, so let's fallback to classic IO based playback
1423 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1426 if (pa_running_in_vm()) {
1427 /* We cannot depend on being woken up when we ask for in a VM,
1428 * so let's fallback to classic IO based playback then. */
1429 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1436 snd_hctl_elem_t
* pa_alsa_find_jack(snd_hctl_t
*hctl
, const char* jack_name
)
1438 snd_ctl_elem_id_t
*id
;
1440 snd_ctl_elem_id_alloca(&id
);
1441 snd_ctl_elem_id_clear(id
);
1442 snd_ctl_elem_id_set_interface(id
, SND_CTL_ELEM_IFACE_CARD
);
1443 snd_ctl_elem_id_set_name(id
, jack_name
);
1445 return snd_hctl_find_elem(hctl
, id
);
1448 static int prepare_mixer(snd_mixer_t
*mixer
, const char *dev
, snd_hctl_t
**hctl
) {
1454 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
1455 pa_log_info("Unable to attach to mixer %s: %s", dev
, pa_alsa_strerror(err
));
1459 /* Note: The hctl handle returned should not be freed.
1460 It is closed/freed by alsa-lib on snd_mixer_close/free */
1461 if (hctl
&& (err
= snd_mixer_get_hctl(mixer
, dev
, hctl
)) < 0) {
1462 pa_log_info("Unable to get hctl of mixer %s: %s", dev
, pa_alsa_strerror(err
));
1466 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
1467 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err
));
1471 if ((err
= snd_mixer_load(mixer
)) < 0) {
1472 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err
));
1476 pa_log_info("Successfully attached to mixer '%s'", dev
);
1480 snd_mixer_t
*pa_alsa_open_mixer(int alsa_card_index
, char **ctl_device
, snd_hctl_t
**hctl
) {
1484 snd_pcm_info_t
* info
;
1485 snd_pcm_info_alloca(&info
);
1487 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1488 pa_log("Error opening mixer: %s", pa_alsa_strerror(err
));
1492 /* Then, try by card index */
1493 md
= pa_sprintf_malloc("hw:%i", alsa_card_index
);
1494 if (prepare_mixer(m
, md
, hctl
) >= 0) {
1510 snd_mixer_t
*pa_alsa_open_mixer_for_pcm(snd_pcm_t
*pcm
, char **ctl_device
, snd_hctl_t
**hctl
) {
1514 snd_pcm_info_t
* info
;
1515 snd_pcm_info_alloca(&info
);
1519 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1520 pa_log("Error opening mixer: %s", pa_alsa_strerror(err
));
1524 /* First, try by name */
1525 if ((dev
= snd_pcm_name(pcm
)))
1526 if (prepare_mixer(m
, dev
, hctl
) >= 0) {
1528 *ctl_device
= pa_xstrdup(dev
);
1533 /* Then, try by card index */
1534 if (snd_pcm_info(pcm
, info
) >= 0) {
1538 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1540 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1542 if (!dev
|| !pa_streq(dev
, md
))
1543 if (prepare_mixer(m
, md
, hctl
) >= 0) {