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 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
);