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_RIGHT
,
591 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
592 PA_CHANNEL_POSITION_FRONT_CENTER
, 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_info("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
,
1098 const char *control_name
) {
1102 snd_mixer_elem_t
*e
;
1103 pa_bool_t found
= FALSE
;
1110 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1111 pa_log("Error opening mixer: %s", snd_strerror(err
));
1115 /* First, try by name */
1116 if ((dev
= snd_pcm_name(pcm
)))
1117 if (pa_alsa_prepare_mixer(m
, dev
) >= 0)
1120 /* Then, try by card index */
1122 snd_pcm_info_t
* info
;
1123 snd_pcm_info_alloca(&info
);
1125 if (snd_pcm_info(pcm
, info
) >= 0) {
1129 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1131 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1133 if (!dev
|| !pa_streq(dev
, md
))
1134 if (pa_alsa_prepare_mixer(m
, md
) >= 0)
1147 switch (snd_pcm_stream(pcm
)) {
1149 case SND_PCM_STREAM_PLAYBACK
:
1151 e
= pa_alsa_find_elem(m
, control_name
, NULL
, TRUE
);
1153 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1156 case SND_PCM_STREAM_CAPTURE
:
1158 e
= pa_alsa_find_elem(m
, control_name
, NULL
, FALSE
);
1160 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1164 pa_assert_not_reached();
1180 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1181 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1183 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1184 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1185 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1187 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1188 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1189 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1191 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1193 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1194 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1196 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1197 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1199 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1200 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1201 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1202 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1203 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1204 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1205 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1206 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1207 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1208 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1209 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1210 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1211 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1212 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1213 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1214 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1215 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1216 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1217 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1218 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1219 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1220 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1221 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1222 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1223 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1224 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1225 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1226 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1227 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1228 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1229 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1230 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1232 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1234 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1235 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1236 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1238 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1239 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1240 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1244 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
) {
1246 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1247 pa_bool_t mono_used
= FALSE
;
1250 pa_assert(channel_map
);
1251 pa_assert(mixer_map
);
1253 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1255 if (channel_map
->channels
> 1 &&
1256 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1257 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1258 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1262 for (i
= 0; i
< channel_map
->channels
; i
++) {
1263 snd_mixer_selem_channel_id_t id
;
1266 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1267 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1269 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1270 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
]));
1274 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1275 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1279 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1280 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1282 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1287 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1291 alsa_channel_used
[id
] = TRUE
;
1295 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1300 void pa_alsa_dump(snd_pcm_t
*pcm
) {
1306 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1308 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1309 pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err
));
1312 snd_output_buffer_string(out
, &s
);
1313 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1316 pa_assert_se(snd_output_close(out
) == 0);
1319 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1322 snd_pcm_status_t
*status
;
1326 snd_pcm_status_alloca(&status
);
1328 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1330 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1332 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1333 pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err
));
1336 snd_output_buffer_string(out
, &s
);
1337 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1340 pa_assert_se(snd_output_close(out
) == 0);
1343 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1347 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1351 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1355 pa_xfree(alsa_file
);
1358 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1360 void pa_alsa_redirect_errors_inc(void) {
1361 /* This is not really thread safe, but we do our best */
1363 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1364 snd_lib_error_set_handler(alsa_error_handler
);
1367 void pa_alsa_redirect_errors_dec(void) {
1370 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1373 snd_lib_error_set_handler(NULL
);
1376 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1380 if (pa_device_init_description(p
))
1383 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1384 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1388 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1389 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1396 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1397 char *cn
, *lcn
, *dn
;
1400 pa_assert(card
>= 0);
1402 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1404 if (snd_card_get_name(card
, &cn
) >= 0) {
1405 pa_proplist_sets(p
, "alsa.card_name", cn
);
1409 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1410 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1414 if ((dn
= pa_alsa_get_driver_name(card
))) {
1415 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1420 pa_udev_get_info(c
, p
, card
);
1424 pa_hal_get_info(c
, p
, card
);
1428 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1430 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1431 [SND_PCM_CLASS_GENERIC
] = "generic",
1432 [SND_PCM_CLASS_MULTI
] = "multi",
1433 [SND_PCM_CLASS_MODEM
] = "modem",
1434 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1436 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1437 [SND_PCM_CLASS_GENERIC
] = "sound",
1438 [SND_PCM_CLASS_MULTI
] = NULL
,
1439 [SND_PCM_CLASS_MODEM
] = "modem",
1440 [SND_PCM_CLASS_DIGITIZER
] = NULL
1442 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1443 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1444 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1447 snd_pcm_class_t
class;
1448 snd_pcm_subclass_t subclass
;
1449 const char *n
, *id
, *sdn
;
1453 pa_assert(pcm_info
);
1455 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1457 class = snd_pcm_info_get_class(pcm_info
);
1458 if (class <= SND_PCM_CLASS_LAST
) {
1459 if (class_table
[class])
1460 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1461 if (alsa_class_table
[class])
1462 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1465 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1466 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1467 if (alsa_subclass_table
[subclass
])
1468 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1470 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1471 pa_proplist_sets(p
, "alsa.name", n
);
1473 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1474 pa_proplist_sets(p
, "alsa.id", id
);
1476 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1477 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1478 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1480 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1482 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1483 pa_alsa_init_proplist_card(c
, p
, card
);
1486 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
) {
1487 snd_pcm_hw_params_t
*hwparams
;
1488 snd_pcm_info_t
*info
;
1491 snd_pcm_hw_params_alloca(&hwparams
);
1492 snd_pcm_info_alloca(&info
);
1494 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1495 pa_log_warn("Error fetching hardware parameter info: %s", snd_strerror(err
));
1498 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1499 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1502 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1503 pa_log_warn("Error fetching PCM info: %s", snd_strerror(err
));
1505 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1508 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1509 snd_pcm_state_t state
;
1514 if (revents
& POLLERR
)
1515 pa_log_debug("Got POLLERR from ALSA");
1516 if (revents
& POLLNVAL
)
1517 pa_log_warn("Got POLLNVAL from ALSA");
1518 if (revents
& POLLHUP
)
1519 pa_log_warn("Got POLLHUP from ALSA");
1520 if (revents
& POLLPRI
)
1521 pa_log_warn("Got POLLPRI from ALSA");
1522 if (revents
& POLLIN
)
1523 pa_log_debug("Got POLLIN from ALSA");
1524 if (revents
& POLLOUT
)
1525 pa_log_debug("Got POLLOUT from ALSA");
1527 state
= snd_pcm_state(pcm
);
1528 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1530 /* Try to recover from this error */
1534 case SND_PCM_STATE_XRUN
:
1535 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1536 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err
));
1541 case SND_PCM_STATE_SUSPENDED
:
1542 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1543 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err
));
1552 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1553 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err
));
1562 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1564 struct pollfd
*pollfd
;
1565 pa_rtpoll_item
*item
;
1569 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1570 pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n
));
1574 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1575 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1577 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1578 pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err
));
1579 pa_rtpoll_item_free(item
);
1586 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1587 snd_pcm_sframes_t n
;
1591 pa_assert(hwbuf_size
> 0);
1594 /* Some ALSA driver expose weird bugs, let's inform the user about
1595 * what is going on */
1597 n
= snd_pcm_avail(pcm
);
1602 k
= (size_t) n
* pa_frame_size(ss
);
1604 if (k
>= hwbuf_size
* 5 ||
1605 k
>= pa_bytes_per_second(ss
)*10) {
1608 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1609 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1610 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1612 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1617 /* Mhmm, let's try not to fail completely */
1618 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1624 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1631 pa_assert(hwbuf_size
> 0);
1634 /* Some ALSA driver expose weird bugs, let's inform the user about
1635 * what is going on */
1637 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1640 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1642 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1644 if (abs_k
>= hwbuf_size
* 5 ||
1645 abs_k
>= pa_bytes_per_second(ss
)*10) {
1648 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1649 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1650 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1653 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1658 /* Mhmm, let's try not to fail completely */
1660 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1662 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1668 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
) {
1670 snd_pcm_uframes_t before
;
1677 pa_assert(hwbuf_size
> 0);
1682 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1687 k
= (size_t) *frames
* pa_frame_size(ss
);
1689 if (*frames
> before
||
1690 k
>= hwbuf_size
* 3 ||
1691 k
>= pa_bytes_per_second(ss
)*10)
1694 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1695 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1696 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1698 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1706 char *pa_alsa_get_driver_name(int card
) {
1709 pa_assert(card
>= 0);
1711 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1718 n
= pa_xstrdup(pa_path_get_filename(m
));
1724 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1726 snd_pcm_info_t
* info
;
1727 snd_pcm_info_alloca(&info
);
1731 if (snd_pcm_info(pcm
, info
) < 0)
1734 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1737 return pa_alsa_get_driver_name(card
);
1740 char *pa_alsa_get_reserve_name(const char *device
) {
1746 if ((t
= strchr(device
, ':')))
1749 if ((i
= snd_card_get_index(device
)) < 0) {
1752 if (pa_atoi(device
, &k
) < 0)
1758 return pa_sprintf_malloc("Audio%i", i
);
1761 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1762 snd_pcm_info_t
* info
;
1763 snd_pcm_info_alloca(&info
);
1767 if (snd_pcm_info(pcm
, info
) < 0)
1770 return snd_pcm_info_get_card(info
) >= 0;