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>
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/once.h>
44 #include "alsa-util.h"
51 #include "udev-util.h"
54 struct pa_alsa_fdlist
{
57 /* This is a temporary buffer used to avoid lots of mallocs */
58 struct pollfd
*work_fds
;
63 pa_defer_event
*defer
;
68 void (*cb
)(void *userdata
);
72 static void io_cb(pa_mainloop_api
*a
, pa_io_event
* e
, int fd
, pa_io_event_flags_t events
, void *userdata
) {
74 struct pa_alsa_fdlist
*fdl
= userdata
;
77 unsigned short revents
;
81 pa_assert(fdl
->mixer
);
83 pa_assert(fdl
->work_fds
);
90 memcpy(fdl
->work_fds
, fdl
->fds
, sizeof(struct pollfd
) * fdl
->num_fds
);
92 for (i
= 0; i
< fdl
->num_fds
; i
++) {
93 if (e
== fdl
->ios
[i
]) {
94 if (events
& PA_IO_EVENT_INPUT
)
95 fdl
->work_fds
[i
].revents
|= POLLIN
;
96 if (events
& PA_IO_EVENT_OUTPUT
)
97 fdl
->work_fds
[i
].revents
|= POLLOUT
;
98 if (events
& PA_IO_EVENT_ERROR
)
99 fdl
->work_fds
[i
].revents
|= POLLERR
;
100 if (events
& PA_IO_EVENT_HANGUP
)
101 fdl
->work_fds
[i
].revents
|= POLLHUP
;
106 pa_assert(i
!= fdl
->num_fds
);
108 if ((err
= snd_mixer_poll_descriptors_revents(fdl
->mixer
, fdl
->work_fds
, fdl
->num_fds
, &revents
)) < 0) {
109 pa_log_error("Unable to get poll revent: %s", snd_strerror(err
));
113 a
->defer_enable(fdl
->defer
, 1);
116 snd_mixer_handle_events(fdl
->mixer
);
119 static void defer_cb(pa_mainloop_api
*a
, pa_defer_event
* e
, void *userdata
) {
120 struct pa_alsa_fdlist
*fdl
= userdata
;
127 pa_assert(fdl
->mixer
);
129 a
->defer_enable(fdl
->defer
, 0);
131 if ((n
= snd_mixer_poll_descriptors_count(fdl
->mixer
)) < 0) {
132 pa_log("snd_mixer_poll_descriptors_count() failed: %s", snd_strerror(n
));
135 num_fds
= (unsigned) n
;
137 if (num_fds
!= fdl
->num_fds
) {
141 pa_xfree(fdl
->work_fds
);
142 fdl
->fds
= pa_xnew0(struct pollfd
, num_fds
);
143 fdl
->work_fds
= pa_xnew(struct pollfd
, num_fds
);
146 memset(fdl
->work_fds
, 0, sizeof(struct pollfd
) * num_fds
);
148 if ((err
= snd_mixer_poll_descriptors(fdl
->mixer
, fdl
->work_fds
, num_fds
)) < 0) {
149 pa_log_error("Unable to get poll descriptors: %s", snd_strerror(err
));
155 if (memcmp(fdl
->fds
, fdl
->work_fds
, sizeof(struct pollfd
) * num_fds
) == 0)
159 for (i
= 0; i
< fdl
->num_fds
; i
++)
160 a
->io_free(fdl
->ios
[i
]);
162 if (num_fds
!= fdl
->num_fds
) {
169 fdl
->ios
= pa_xnew(pa_io_event
*, num_fds
);
172 temp
= fdl
->work_fds
;
173 fdl
->work_fds
= fdl
->fds
;
176 fdl
->num_fds
= num_fds
;
178 for (i
= 0;i
< num_fds
;i
++)
179 fdl
->ios
[i
] = a
->io_new(a
, fdl
->fds
[i
].fd
,
180 ((fdl
->fds
[i
].events
& POLLIN
) ? PA_IO_EVENT_INPUT
: 0) |
181 ((fdl
->fds
[i
].events
& POLLOUT
) ? PA_IO_EVENT_OUTPUT
: 0),
185 struct pa_alsa_fdlist
*pa_alsa_fdlist_new(void) {
186 struct pa_alsa_fdlist
*fdl
;
188 fdl
= pa_xnew0(struct pa_alsa_fdlist
, 1);
192 fdl
->work_fds
= NULL
;
202 void pa_alsa_fdlist_free(struct pa_alsa_fdlist
*fdl
) {
207 fdl
->m
->defer_free(fdl
->defer
);
213 for (i
= 0; i
< fdl
->num_fds
; i
++)
214 fdl
->m
->io_free(fdl
->ios
[i
]);
221 pa_xfree(fdl
->work_fds
);
226 int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist
*fdl
, snd_mixer_t
*mixer_handle
, pa_mainloop_api
* m
) {
228 pa_assert(mixer_handle
);
232 fdl
->mixer
= mixer_handle
;
234 fdl
->defer
= m
->defer_new(m
, defer_cb
, fdl
);
239 static int set_format(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, pa_sample_format_t
*f
) {
241 static const snd_pcm_format_t format_trans
[] = {
242 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
243 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
244 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
245 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
246 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
247 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
248 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
249 [PA_SAMPLE_S32LE
] = SND_PCM_FORMAT_S32_LE
,
250 [PA_SAMPLE_S32BE
] = SND_PCM_FORMAT_S32_BE
,
251 [PA_SAMPLE_S24LE
] = SND_PCM_FORMAT_S24_3LE
,
252 [PA_SAMPLE_S24BE
] = SND_PCM_FORMAT_S24_3BE
,
253 [PA_SAMPLE_S24_32LE
] = SND_PCM_FORMAT_S24_LE
,
254 [PA_SAMPLE_S24_32BE
] = SND_PCM_FORMAT_S24_BE
,
257 static const pa_sample_format_t try_order
[] = {
276 pa_assert(pcm_handle
);
279 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
282 if (*f
== PA_SAMPLE_FLOAT32BE
)
283 *f
= PA_SAMPLE_FLOAT32LE
;
284 else if (*f
== PA_SAMPLE_FLOAT32LE
)
285 *f
= PA_SAMPLE_FLOAT32BE
;
286 else if (*f
== PA_SAMPLE_S24BE
)
287 *f
= PA_SAMPLE_S24LE
;
288 else if (*f
== PA_SAMPLE_S24LE
)
289 *f
= PA_SAMPLE_S24BE
;
290 else if (*f
== PA_SAMPLE_S24_32BE
)
291 *f
= PA_SAMPLE_S24_32LE
;
292 else if (*f
== PA_SAMPLE_S24_32LE
)
293 *f
= PA_SAMPLE_S24_32BE
;
294 else if (*f
== PA_SAMPLE_S16BE
)
295 *f
= PA_SAMPLE_S16LE
;
296 else if (*f
== PA_SAMPLE_S16LE
)
297 *f
= PA_SAMPLE_S16BE
;
298 else if (*f
== PA_SAMPLE_S32BE
)
299 *f
= PA_SAMPLE_S32LE
;
300 else if (*f
== PA_SAMPLE_S32LE
)
301 *f
= PA_SAMPLE_S32BE
;
305 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
310 for (i
= 0; try_order
[i
] != PA_SAMPLE_INVALID
; i
++) {
313 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
320 /* Set the hardware parameters of the given ALSA device. Returns the
321 * selected fragment settings in *period and *period_size */
322 int pa_alsa_set_hw_params(
323 snd_pcm_t
*pcm_handle
,
326 snd_pcm_uframes_t
*period_size
,
327 snd_pcm_uframes_t tsched_size
,
329 pa_bool_t
*use_tsched
,
330 pa_bool_t require_exact_channel_number
) {
333 snd_pcm_uframes_t _period_size
= period_size
? *period_size
: 0;
334 unsigned int _periods
= periods
? *periods
: 0;
335 snd_pcm_uframes_t buffer_size
;
336 unsigned int r
= ss
->rate
;
337 unsigned int c
= ss
->channels
;
338 pa_sample_format_t f
= ss
->format
;
339 snd_pcm_hw_params_t
*hwparams
;
340 pa_bool_t _use_mmap
= use_mmap
&& *use_mmap
;
341 pa_bool_t _use_tsched
= use_tsched
&& *use_tsched
;
344 pa_assert(pcm_handle
);
347 snd_pcm_hw_params_alloca(&hwparams
);
349 if ((ret
= snd_pcm_hw_params_any(pcm_handle
, hwparams
)) < 0)
352 if ((ret
= snd_pcm_hw_params_set_rate_resample(pcm_handle
, hwparams
, 0)) < 0)
357 if (snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) < 0) {
359 /* mmap() didn't work, fall back to interleaved */
361 if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
367 } else if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
373 if ((ret
= set_format(pcm_handle
, hwparams
, &f
)) < 0)
376 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &r
, NULL
)) < 0)
379 if (require_exact_channel_number
) {
380 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, c
)) < 0)
383 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0)
387 if ((ret
= snd_pcm_hw_params_set_periods_integer(pcm_handle
, hwparams
)) < 0)
390 if (_period_size
&& tsched_size
&& _periods
) {
391 /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
392 _period_size
= (snd_pcm_uframes_t
) (((uint64_t) _period_size
* r
) / ss
->rate
);
393 tsched_size
= (snd_pcm_uframes_t
) (((uint64_t) tsched_size
* r
) / ss
->rate
);
396 _period_size
= tsched_size
;
399 pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams
, &buffer_size
) == 0);
400 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size
* 1000 / r
);
403 buffer_size
= _periods
* _period_size
;
407 /* First we pass 0 as direction to get exactly what we asked
408 * for. That this is necessary is presumably a bug in ALSA */
411 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0) {
413 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0) {
415 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0)
421 if (_period_size
> 0)
422 if ((ret
= snd_pcm_hw_params_set_buffer_size_near(pcm_handle
, hwparams
, &buffer_size
)) < 0)
426 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0)
430 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, r
);
432 if (ss
->channels
!= c
)
433 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, c
);
436 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(f
));
438 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0)
441 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
442 (ret
= snd_pcm_hw_params_get_periods(hwparams
, &_periods
, &dir
)) < 0)
445 /* If the sample rate deviates too much, we need to resample */
446 if (r
< ss
->rate
*.95 || r
> ss
->rate
*1.05)
448 ss
->channels
= (uint8_t) c
;
451 pa_assert(_periods
> 0);
452 pa_assert(_period_size
> 0);
458 *period_size
= _period_size
;
461 *use_mmap
= _use_mmap
;
464 *use_tsched
= _use_tsched
;
468 snd_pcm_nonblock(pcm_handle
, 1);
475 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
) {
476 snd_pcm_sw_params_t
*swparams
;
477 snd_pcm_uframes_t boundary
;
482 snd_pcm_sw_params_alloca(&swparams
);
484 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
485 pa_log_warn("Unable to determine current swparams: %s\n", snd_strerror(err
));
489 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 0)) < 0) {
490 pa_log_warn("Unable to disable period event: %s\n", snd_strerror(err
));
494 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
495 pa_log_warn("Unable to enable time stamping: %s\n", snd_strerror(err
));
499 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
500 pa_log_warn("Unable to get boundary: %s\n", snd_strerror(err
));
504 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
505 pa_log_warn("Unable to set stop threshold: %s\n", snd_strerror(err
));
509 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
510 pa_log_warn("Unable to set start threshold: %s\n", snd_strerror(err
));
514 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
515 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err
));
519 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
520 pa_log_warn("Unable to set sw params: %s\n", snd_strerror(err
));
527 static const struct pa_alsa_profile_info device_table
[] = {
528 {{ 1, { PA_CHANNEL_POSITION_MONO
}},
534 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
540 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
542 N_("Digital Stereo (IEC958)"),
546 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
548 N_("Digital Stereo (HDMI)"),
552 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
553 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
555 N_("Analog Surround 4.0"),
556 "analog-surround-40",
559 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
560 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
562 N_("Digital Surround 4.0 (IEC958/AC3)"),
563 "iec958-ac3-surround-40",
566 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
567 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
568 PA_CHANNEL_POSITION_LFE
}},
570 N_("Analog Surround 4.1"),
571 "analog-surround-41",
574 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
575 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
576 PA_CHANNEL_POSITION_CENTER
}},
578 N_("Analog Surround 5.0"),
579 "analog-surround-50",
582 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
583 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
584 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
}},
586 N_("Analog Surround 5.1"),
587 "analog-surround-51",
590 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_CENTER
,
591 PA_CHANNEL_POSITION_FRONT_RIGHT
, PA_CHANNEL_POSITION_REAR_LEFT
,
592 PA_CHANNEL_POSITION_REAR_RIGHT
, PA_CHANNEL_POSITION_LFE
}},
594 N_("Digital Surround 5.1 (IEC958/AC3)"),
595 "iec958-ac3-surround-51",
598 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
599 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
600 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
,
601 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
}},
603 N_("Analog Surround 7.1"),
604 "analog-surround-71",
607 {{ 0, { 0 }}, NULL
, NULL
, NULL
, 0 }
610 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
617 snd_pcm_uframes_t
*period_size
,
618 snd_pcm_uframes_t tsched_size
,
620 pa_bool_t
*use_tsched
,
621 const pa_alsa_profile_info
**profile
) {
626 snd_pcm_t
*pcm_handle
;
633 pa_assert(period_size
);
635 /* First we try to find a device string with a superset of the
636 * requested channel map and open it without the plug: prefix. We
637 * iterate through our device table from top to bottom and take
638 * the first that matches. If we didn't find a working device that
639 * way, we iterate backwards, and check all devices that do not
640 * provide a superset of the requested channel map.*/
645 if ((direction
> 0) == pa_channel_map_superset(&device_table
[i
].map
, map
)) {
646 pa_sample_spec try_ss
;
648 pa_log_debug("Checking for %s (%s)", device_table
[i
].name
, device_table
[i
].alsa_name
);
650 d
= pa_sprintf_malloc("%s:%s", device_table
[i
].alsa_name
, dev_id
);
652 try_ss
.channels
= device_table
[i
].map
.channels
;
653 try_ss
.rate
= ss
->rate
;
654 try_ss
.format
= ss
->format
;
656 pcm_handle
= pa_alsa_open_by_device_string(
674 *map
= device_table
[i
].map
;
675 pa_assert(map
->channels
== ss
->channels
);
678 *profile
= &device_table
[i
];
685 if (!device_table
[i
+1].alsa_name
) {
686 /* OK, so we are at the end of our list. Let's turn
690 /* We are not at the end of the list, so let's simply
691 * try the next entry */
698 if (device_table
[i
+1].alsa_name
&&
699 device_table
[i
].map
.channels
== device_table
[i
+1].map
.channels
) {
701 /* OK, the next entry has the same number of channels,
706 /* Hmm, so the next entry does not have the same
707 * number of channels, so let's go backwards until we
708 * find the next entry with a differnt number of
711 for (i
--; i
>= 0; i
--)
712 if (device_table
[i
].map
.channels
!= device_table
[i
+1].map
.channels
)
715 /* Hmm, there is no entry with a different number of
716 * entries, then we're done */
720 /* OK, now lets find go back as long as we have the same number of channels */
722 if (device_table
[i
].map
.channels
!= device_table
[i
-1].map
.channels
)
728 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
730 d
= pa_sprintf_malloc("hw:%s", dev_id
);
731 pa_log_debug("Trying %s as last resort...", d
);
732 pcm_handle
= pa_alsa_open_by_device_string(d
, dev
, ss
, map
, mode
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, FALSE
);
735 if (pcm_handle
&& profile
)
741 snd_pcm_t
*pa_alsa_open_by_device_id_profile(
748 snd_pcm_uframes_t
*period_size
,
749 snd_pcm_uframes_t tsched_size
,
751 pa_bool_t
*use_tsched
,
752 const pa_alsa_profile_info
*profile
) {
755 snd_pcm_t
*pcm_handle
;
756 pa_sample_spec try_ss
;
763 pa_assert(period_size
);
766 d
= pa_sprintf_malloc("%s:%s", profile
->alsa_name
, dev_id
);
768 try_ss
.channels
= profile
->map
.channels
;
769 try_ss
.rate
= ss
->rate
;
770 try_ss
.format
= ss
->format
;
772 pcm_handle
= pa_alsa_open_by_device_string(
792 pa_assert(map
->channels
== ss
->channels
);
797 snd_pcm_t
*pa_alsa_open_by_device_string(
804 snd_pcm_uframes_t
*period_size
,
805 snd_pcm_uframes_t tsched_size
,
807 pa_bool_t
*use_tsched
,
808 pa_bool_t require_exact_channel_number
) {
812 snd_pcm_t
*pcm_handle
;
813 pa_bool_t reformat
= FALSE
;
819 d
= pa_xstrdup(device
);
822 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
824 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
825 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
826 * we enable nonblock mode afterwards via
827 * snd_pcm_nonblock(). Also see
828 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
830 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
831 /*SND_PCM_NONBLOCK|*/
832 SND_PCM_NO_AUTO_RESAMPLE
|
833 SND_PCM_NO_AUTO_CHANNELS
|
834 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
835 pa_log_info("Error opening PCM device %s: %s", d
, snd_strerror(err
));
839 if ((err
= pa_alsa_set_hw_params(pcm_handle
, ss
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, require_exact_channel_number
)) < 0) {
844 snd_pcm_close(pcm_handle
);
848 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
850 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
853 t
= pa_sprintf_malloc("plug:%s", d
);
859 snd_pcm_close(pcm_handle
);
863 pa_log_info("Failed to set hardware parameters on %s: %s", d
, snd_strerror(err
));
864 snd_pcm_close(pcm_handle
);
874 if (ss
->channels
!= map
->channels
)
875 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
886 int pa_alsa_probe_profiles(
888 const pa_sample_spec
*ss
,
889 void (*cb
)(const pa_alsa_profile_info
*sink
, const pa_alsa_profile_info
*source
, void *userdata
),
892 const pa_alsa_profile_info
*i
;
898 /* We try each combination of playback/capture. We also try to
899 * open only for capture resp. only for sink. Don't get confused
900 * by the trailing entry in device_table we use for this! */
902 for (i
= device_table
; i
< device_table
+ PA_ELEMENTSOF(device_table
); i
++) {
903 const pa_alsa_profile_info
*j
;
904 snd_pcm_t
*pcm_i
= NULL
;
908 pa_sample_spec try_ss
;
909 pa_channel_map try_map
;
911 pa_log_debug("Checking for playback on %s (%s)", i
->name
, i
->alsa_name
);
912 id
= pa_sprintf_malloc("%s:%s", i
->alsa_name
, dev_id
);
915 try_ss
.channels
= i
->map
.channels
;
918 pcm_i
= pa_alsa_open_by_device_string(
921 SND_PCM_STREAM_PLAYBACK
,
922 NULL
, NULL
, 0, NULL
, NULL
,
931 for (j
= device_table
; j
< device_table
+ PA_ELEMENTSOF(device_table
); j
++) {
932 snd_pcm_t
*pcm_j
= NULL
;
936 pa_sample_spec try_ss
;
937 pa_channel_map try_map
;
939 pa_log_debug("Checking for capture on %s (%s)", j
->name
, j
->alsa_name
);
940 jd
= pa_sprintf_malloc("%s:%s", j
->alsa_name
, dev_id
);
943 try_ss
.channels
= j
->map
.channels
;
946 pcm_j
= pa_alsa_open_by_device_string(
949 SND_PCM_STREAM_CAPTURE
,
950 NULL
, NULL
, 0, NULL
, NULL
,
960 snd_pcm_close(pcm_j
);
962 if (i
->alsa_name
|| j
->alsa_name
)
963 cb(i
->alsa_name
? i
: NULL
,
964 j
->alsa_name
? j
: NULL
, userdata
);
968 snd_pcm_close(pcm_i
);
974 int pa_alsa_prepare_mixer(snd_mixer_t
*mixer
, const char *dev
) {
980 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
981 pa_log_info("Unable to attach to mixer %s: %s", dev
, snd_strerror(err
));
985 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
986 pa_log_warn("Unable to register mixer: %s", snd_strerror(err
));
990 if ((err
= snd_mixer_load(mixer
)) < 0) {
991 pa_log_warn("Unable to load mixer: %s", snd_strerror(err
));
995 pa_log_info("Successfully attached to mixer '%s'", dev
);
1000 static pa_bool_t
elem_has_volume(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1003 if (playback
&& snd_mixer_selem_has_playback_volume(elem
))
1006 if (!playback
&& snd_mixer_selem_has_capture_volume(elem
))
1012 static pa_bool_t
elem_has_switch(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1015 if (playback
&& snd_mixer_selem_has_playback_switch(elem
))
1018 if (!playback
&& snd_mixer_selem_has_capture_switch(elem
))
1024 snd_mixer_elem_t
*pa_alsa_find_elem(snd_mixer_t
*mixer
, const char *name
, const char *fallback
, pa_bool_t playback
) {
1025 snd_mixer_elem_t
*elem
= NULL
, *fallback_elem
= NULL
;
1026 snd_mixer_selem_id_t
*sid
= NULL
;
1028 snd_mixer_selem_id_alloca(&sid
);
1033 snd_mixer_selem_id_set_name(sid
, name
);
1034 snd_mixer_selem_id_set_index(sid
, 0);
1036 if ((elem
= snd_mixer_find_selem(mixer
, sid
))) {
1038 if (elem_has_volume(elem
, playback
) &&
1039 elem_has_switch(elem
, playback
))
1042 if (!elem_has_volume(elem
, playback
) &&
1043 !elem_has_switch(elem
, playback
))
1047 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1050 snd_mixer_selem_id_set_name(sid
, fallback
);
1051 snd_mixer_selem_id_set_index(sid
, 0);
1053 if ((fallback_elem
= snd_mixer_find_selem(mixer
, sid
))) {
1055 if (elem_has_volume(fallback_elem
, playback
) &&
1056 elem_has_switch(fallback_elem
, playback
)) {
1057 elem
= fallback_elem
;
1061 if (!elem_has_volume(fallback_elem
, playback
) &&
1062 !elem_has_switch(fallback_elem
, playback
))
1063 fallback_elem
= NULL
;
1066 pa_log_warn("Cannot find fallback mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1069 if (elem
&& fallback_elem
) {
1071 /* Hmm, so we have both elements, but neither has both mute
1072 * and volume. Let's prefer the one with the volume */
1074 if (elem_has_volume(elem
, playback
))
1077 if (elem_has_volume(fallback_elem
, playback
)) {
1078 elem
= fallback_elem
;
1083 if (!elem
&& fallback_elem
)
1084 elem
= fallback_elem
;
1089 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid
));
1094 int pa_alsa_find_mixer_and_elem(
1097 snd_mixer_elem_t
**_e
) {
1101 snd_mixer_elem_t
*e
;
1102 pa_bool_t found
= FALSE
;
1109 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1110 pa_log("Error opening mixer: %s", snd_strerror(err
));
1114 /* First, try by name */
1115 if ((dev
= snd_pcm_name(pcm
)))
1116 if (pa_alsa_prepare_mixer(m
, dev
) >= 0)
1119 /* Then, try by card index */
1121 snd_pcm_info_t
* info
;
1122 snd_pcm_info_alloca(&info
);
1124 if (snd_pcm_info(pcm
, info
) >= 0) {
1128 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1130 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1132 if (!dev
|| !pa_streq(dev
, md
))
1133 if (pa_alsa_prepare_mixer(m
, md
) >= 0)
1146 switch (snd_pcm_stream(pcm
)) {
1148 case SND_PCM_STREAM_PLAYBACK
:
1149 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1152 case SND_PCM_STREAM_CAPTURE
:
1153 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1157 pa_assert_not_reached();
1173 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1174 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1176 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1177 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1178 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1180 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1181 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1182 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1184 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1186 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1187 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1189 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1190 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1192 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1193 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1194 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1195 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1196 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1197 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1198 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1199 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1200 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1201 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1202 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1203 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1204 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1205 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1206 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1207 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1208 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1209 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1210 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1211 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1212 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1213 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1214 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1215 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1216 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1217 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1218 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1219 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1220 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1221 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1222 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1223 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1225 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1227 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1228 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1229 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1231 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1232 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1233 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1237 int pa_alsa_calc_mixer_map(snd_mixer_elem_t
*elem
, const pa_channel_map
*channel_map
, snd_mixer_selem_channel_id_t mixer_map
[], pa_bool_t playback
) {
1239 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1240 pa_bool_t mono_used
= FALSE
;
1243 pa_assert(channel_map
);
1244 pa_assert(mixer_map
);
1246 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1248 if (channel_map
->channels
> 1 &&
1249 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1250 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1251 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1255 for (i
= 0; i
< channel_map
->channels
; i
++) {
1256 snd_mixer_selem_channel_id_t id
;
1259 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1260 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1262 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1263 pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer.", pa_channel_position_to_string(channel_map
->map
[i
]));
1267 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1268 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1272 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1273 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1275 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1280 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1284 alsa_channel_used
[id
] = TRUE
;
1288 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1293 void pa_alsa_dump(snd_pcm_t
*pcm
) {
1299 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1301 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1302 pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err
));
1305 snd_output_buffer_string(out
, &s
);
1306 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1309 pa_assert_se(snd_output_close(out
) == 0);
1312 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1315 snd_pcm_status_t
*status
;
1319 snd_pcm_status_alloca(&status
);
1321 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1323 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1325 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1326 pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err
));
1329 snd_output_buffer_string(out
, &s
);
1330 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1333 pa_assert_se(snd_output_close(out
) == 0);
1336 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1340 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1344 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1348 pa_xfree(alsa_file
);
1351 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1353 void pa_alsa_redirect_errors_inc(void) {
1354 /* This is not really thread safe, but we do our best */
1356 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1357 snd_lib_error_set_handler(alsa_error_handler
);
1360 void pa_alsa_redirect_errors_dec(void) {
1363 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1366 snd_lib_error_set_handler(NULL
);
1369 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1373 if (pa_device_init_description(p
))
1376 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1377 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1381 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1382 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1389 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1390 char *cn
, *lcn
, *dn
;
1393 pa_assert(card
>= 0);
1395 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1397 if (snd_card_get_name(card
, &cn
) >= 0) {
1398 pa_proplist_sets(p
, "alsa.card_name", cn
);
1402 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1403 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1407 if ((dn
= pa_alsa_get_driver_name(card
))) {
1408 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1413 pa_udev_get_info(c
, p
, card
);
1417 pa_hal_get_info(c
, p
, card
);
1421 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1423 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1424 [SND_PCM_CLASS_GENERIC
] = "generic",
1425 [SND_PCM_CLASS_MULTI
] = "multi",
1426 [SND_PCM_CLASS_MODEM
] = "modem",
1427 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1429 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1430 [SND_PCM_CLASS_GENERIC
] = "sound",
1431 [SND_PCM_CLASS_MULTI
] = NULL
,
1432 [SND_PCM_CLASS_MODEM
] = "modem",
1433 [SND_PCM_CLASS_DIGITIZER
] = NULL
1435 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1436 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1437 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1440 snd_pcm_class_t
class;
1441 snd_pcm_subclass_t subclass
;
1442 const char *n
, *id
, *sdn
;
1446 pa_assert(pcm_info
);
1448 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1450 class = snd_pcm_info_get_class(pcm_info
);
1451 if (class <= SND_PCM_CLASS_LAST
) {
1452 if (class_table
[class])
1453 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1454 if (alsa_class_table
[class])
1455 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1458 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1459 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1460 if (alsa_subclass_table
[subclass
])
1461 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1463 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1464 pa_proplist_sets(p
, "alsa.name", n
);
1466 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1467 pa_proplist_sets(p
, "alsa.id", id
);
1469 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1470 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1471 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1473 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1475 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1476 pa_alsa_init_proplist_card(c
, p
, card
);
1479 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
) {
1480 snd_pcm_hw_params_t
*hwparams
;
1481 snd_pcm_info_t
*info
;
1484 snd_pcm_hw_params_alloca(&hwparams
);
1485 snd_pcm_info_alloca(&info
);
1487 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1488 pa_log_warn("Error fetching hardware parameter info: %s", snd_strerror(err
));
1491 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1492 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1495 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1496 pa_log_warn("Error fetching PCM info: %s", snd_strerror(err
));
1498 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1501 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1502 snd_pcm_state_t state
;
1507 if (revents
& POLLERR
)
1508 pa_log_debug("Got POLLERR from ALSA");
1509 if (revents
& POLLNVAL
)
1510 pa_log_warn("Got POLLNVAL from ALSA");
1511 if (revents
& POLLHUP
)
1512 pa_log_warn("Got POLLHUP from ALSA");
1513 if (revents
& POLLPRI
)
1514 pa_log_warn("Got POLLPRI from ALSA");
1515 if (revents
& POLLIN
)
1516 pa_log_debug("Got POLLIN from ALSA");
1517 if (revents
& POLLOUT
)
1518 pa_log_debug("Got POLLOUT from ALSA");
1520 state
= snd_pcm_state(pcm
);
1521 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1523 /* Try to recover from this error */
1527 case SND_PCM_STATE_XRUN
:
1528 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1529 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err
));
1534 case SND_PCM_STATE_SUSPENDED
:
1535 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1536 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err
));
1545 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1546 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err
));
1555 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1557 struct pollfd
*pollfd
;
1558 pa_rtpoll_item
*item
;
1562 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1563 pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n
));
1567 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1568 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1570 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1571 pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err
));
1572 pa_rtpoll_item_free(item
);
1579 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1580 snd_pcm_sframes_t n
;
1584 pa_assert(hwbuf_size
> 0);
1587 /* Some ALSA driver expose weird bugs, let's inform the user about
1588 * what is going on */
1590 n
= snd_pcm_avail(pcm
);
1595 k
= (size_t) n
* pa_frame_size(ss
);
1597 if (k
>= hwbuf_size
* 5 ||
1598 k
>= pa_bytes_per_second(ss
)*10) {
1601 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1602 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1603 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1605 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1610 /* Mhmm, let's try not to fail completely */
1611 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1617 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1624 pa_assert(hwbuf_size
> 0);
1627 /* Some ALSA driver expose weird bugs, let's inform the user about
1628 * what is going on */
1630 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1633 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1635 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1637 if (abs_k
>= hwbuf_size
* 5 ||
1638 abs_k
>= pa_bytes_per_second(ss
)*10) {
1641 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1642 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1643 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1646 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1651 /* Mhmm, let's try not to fail completely */
1653 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1655 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1661 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
) {
1663 snd_pcm_uframes_t before
;
1670 pa_assert(hwbuf_size
> 0);
1675 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1680 k
= (size_t) *frames
* pa_frame_size(ss
);
1682 if (*frames
> before
||
1683 k
>= hwbuf_size
* 3 ||
1684 k
>= pa_bytes_per_second(ss
)*10)
1687 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1688 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1689 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1691 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1699 char *pa_alsa_get_driver_name(int card
) {
1702 pa_assert(card
>= 0);
1704 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1711 n
= pa_xstrdup(pa_path_get_filename(m
));
1717 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1720 snd_pcm_info_t
* info
;
1721 snd_pcm_info_alloca(&info
);
1723 if (snd_pcm_info(pcm
, info
) < 0)
1726 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1729 return pa_alsa_get_driver_name(card
);
1732 char *pa_alsa_get_reserve_name(const char *device
) {
1738 if ((t
= strchr(device
, ':')))
1741 if ((i
= snd_card_get_index(device
)) < 0) {
1744 if (pa_atoi(device
, &k
) < 0)
1750 return pa_sprintf_malloc("Audio%i", i
);