2 This file is part of PulseAudio.
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/types.h>
29 #include <asoundlib.h>
31 #include <pulse/sample.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/i18n.h>
36 #include <pulse/utf8.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/macro.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/atomic.h>
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/once.h>
44 #include <pulsecore/thread.h>
46 #include "alsa-util.h"
53 #include "udev-util.h"
56 struct pa_alsa_fdlist
{
59 /* This is a temporary buffer used to avoid lots of mallocs */
60 struct pollfd
*work_fds
;
65 pa_defer_event
*defer
;
70 void (*cb
)(void *userdata
);
74 static void io_cb(pa_mainloop_api
*a
, pa_io_event
* e
, int fd
, pa_io_event_flags_t events
, void *userdata
) {
76 struct pa_alsa_fdlist
*fdl
= userdata
;
79 unsigned short revents
;
83 pa_assert(fdl
->mixer
);
85 pa_assert(fdl
->work_fds
);
92 memcpy(fdl
->work_fds
, fdl
->fds
, sizeof(struct pollfd
) * fdl
->num_fds
);
94 for (i
= 0; i
< fdl
->num_fds
; i
++) {
95 if (e
== fdl
->ios
[i
]) {
96 if (events
& PA_IO_EVENT_INPUT
)
97 fdl
->work_fds
[i
].revents
|= POLLIN
;
98 if (events
& PA_IO_EVENT_OUTPUT
)
99 fdl
->work_fds
[i
].revents
|= POLLOUT
;
100 if (events
& PA_IO_EVENT_ERROR
)
101 fdl
->work_fds
[i
].revents
|= POLLERR
;
102 if (events
& PA_IO_EVENT_HANGUP
)
103 fdl
->work_fds
[i
].revents
|= POLLHUP
;
108 pa_assert(i
!= fdl
->num_fds
);
110 if ((err
= snd_mixer_poll_descriptors_revents(fdl
->mixer
, fdl
->work_fds
, fdl
->num_fds
, &revents
)) < 0) {
111 pa_log_error("Unable to get poll revent: %s", pa_alsa_strerror(err
));
115 a
->defer_enable(fdl
->defer
, 1);
118 snd_mixer_handle_events(fdl
->mixer
);
121 static void defer_cb(pa_mainloop_api
*a
, pa_defer_event
* e
, void *userdata
) {
122 struct pa_alsa_fdlist
*fdl
= userdata
;
129 pa_assert(fdl
->mixer
);
131 a
->defer_enable(fdl
->defer
, 0);
133 if ((n
= snd_mixer_poll_descriptors_count(fdl
->mixer
)) < 0) {
134 pa_log("snd_mixer_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
137 num_fds
= (unsigned) n
;
139 if (num_fds
!= fdl
->num_fds
) {
143 pa_xfree(fdl
->work_fds
);
144 fdl
->fds
= pa_xnew0(struct pollfd
, num_fds
);
145 fdl
->work_fds
= pa_xnew(struct pollfd
, num_fds
);
148 memset(fdl
->work_fds
, 0, sizeof(struct pollfd
) * num_fds
);
150 if ((err
= snd_mixer_poll_descriptors(fdl
->mixer
, fdl
->work_fds
, num_fds
)) < 0) {
151 pa_log_error("Unable to get poll descriptors: %s", pa_alsa_strerror(err
));
157 if (memcmp(fdl
->fds
, fdl
->work_fds
, sizeof(struct pollfd
) * num_fds
) == 0)
161 for (i
= 0; i
< fdl
->num_fds
; i
++)
162 a
->io_free(fdl
->ios
[i
]);
164 if (num_fds
!= fdl
->num_fds
) {
171 fdl
->ios
= pa_xnew(pa_io_event
*, num_fds
);
174 temp
= fdl
->work_fds
;
175 fdl
->work_fds
= fdl
->fds
;
178 fdl
->num_fds
= num_fds
;
180 for (i
= 0;i
< num_fds
;i
++)
181 fdl
->ios
[i
] = a
->io_new(a
, fdl
->fds
[i
].fd
,
182 ((fdl
->fds
[i
].events
& POLLIN
) ? PA_IO_EVENT_INPUT
: 0) |
183 ((fdl
->fds
[i
].events
& POLLOUT
) ? PA_IO_EVENT_OUTPUT
: 0),
187 struct pa_alsa_fdlist
*pa_alsa_fdlist_new(void) {
188 struct pa_alsa_fdlist
*fdl
;
190 fdl
= pa_xnew0(struct pa_alsa_fdlist
, 1);
194 fdl
->work_fds
= NULL
;
204 void pa_alsa_fdlist_free(struct pa_alsa_fdlist
*fdl
) {
209 fdl
->m
->defer_free(fdl
->defer
);
215 for (i
= 0; i
< fdl
->num_fds
; i
++)
216 fdl
->m
->io_free(fdl
->ios
[i
]);
223 pa_xfree(fdl
->work_fds
);
228 int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist
*fdl
, snd_mixer_t
*mixer_handle
, pa_mainloop_api
* m
) {
230 pa_assert(mixer_handle
);
234 fdl
->mixer
= mixer_handle
;
236 fdl
->defer
= m
->defer_new(m
, defer_cb
, fdl
);
241 static int set_format(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, pa_sample_format_t
*f
) {
243 static const snd_pcm_format_t format_trans
[] = {
244 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
245 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
246 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
247 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
248 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
249 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
250 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
251 [PA_SAMPLE_S32LE
] = SND_PCM_FORMAT_S32_LE
,
252 [PA_SAMPLE_S32BE
] = SND_PCM_FORMAT_S32_BE
,
253 [PA_SAMPLE_S24LE
] = SND_PCM_FORMAT_S24_3LE
,
254 [PA_SAMPLE_S24BE
] = SND_PCM_FORMAT_S24_3BE
,
255 [PA_SAMPLE_S24_32LE
] = SND_PCM_FORMAT_S24_LE
,
256 [PA_SAMPLE_S24_32BE
] = SND_PCM_FORMAT_S24_BE
,
259 static const pa_sample_format_t try_order
[] = {
278 pa_assert(pcm_handle
);
281 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
284 if (*f
== PA_SAMPLE_FLOAT32BE
)
285 *f
= PA_SAMPLE_FLOAT32LE
;
286 else if (*f
== PA_SAMPLE_FLOAT32LE
)
287 *f
= PA_SAMPLE_FLOAT32BE
;
288 else if (*f
== PA_SAMPLE_S24BE
)
289 *f
= PA_SAMPLE_S24LE
;
290 else if (*f
== PA_SAMPLE_S24LE
)
291 *f
= PA_SAMPLE_S24BE
;
292 else if (*f
== PA_SAMPLE_S24_32BE
)
293 *f
= PA_SAMPLE_S24_32LE
;
294 else if (*f
== PA_SAMPLE_S24_32LE
)
295 *f
= PA_SAMPLE_S24_32BE
;
296 else if (*f
== PA_SAMPLE_S16BE
)
297 *f
= PA_SAMPLE_S16LE
;
298 else if (*f
== PA_SAMPLE_S16LE
)
299 *f
= PA_SAMPLE_S16BE
;
300 else if (*f
== PA_SAMPLE_S32BE
)
301 *f
= PA_SAMPLE_S32LE
;
302 else if (*f
== PA_SAMPLE_S32LE
)
303 *f
= PA_SAMPLE_S32BE
;
307 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
312 for (i
= 0; try_order
[i
] != PA_SAMPLE_INVALID
; i
++) {
315 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
322 /* Set the hardware parameters of the given ALSA device. Returns the
323 * selected fragment settings in *period and *period_size */
324 int pa_alsa_set_hw_params(
325 snd_pcm_t
*pcm_handle
,
328 snd_pcm_uframes_t
*period_size
,
329 snd_pcm_uframes_t tsched_size
,
331 pa_bool_t
*use_tsched
,
332 pa_bool_t require_exact_channel_number
) {
335 snd_pcm_uframes_t _period_size
= period_size
? *period_size
: 0;
336 unsigned int _periods
= periods
? *periods
: 0;
337 unsigned int r
= ss
->rate
;
338 unsigned int c
= ss
->channels
;
339 pa_sample_format_t f
= ss
->format
;
340 snd_pcm_hw_params_t
*hwparams
;
341 pa_bool_t _use_mmap
= use_mmap
&& *use_mmap
;
342 pa_bool_t _use_tsched
= use_tsched
&& *use_tsched
;
345 pa_assert(pcm_handle
);
348 snd_pcm_hw_params_alloca(&hwparams
);
350 if ((ret
= snd_pcm_hw_params_any(pcm_handle
, hwparams
)) < 0)
353 if ((ret
= snd_pcm_hw_params_set_rate_resample(pcm_handle
, hwparams
, 0)) < 0)
358 if (snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) < 0) {
360 /* mmap() didn't work, fall back to interleaved */
362 if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
368 } else if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
374 if ((ret
= set_format(pcm_handle
, hwparams
, &f
)) < 0)
377 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &r
, NULL
)) < 0)
380 if (require_exact_channel_number
) {
381 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, c
)) < 0)
384 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0)
388 if ((ret
= snd_pcm_hw_params_set_periods_integer(pcm_handle
, hwparams
)) < 0)
391 if (_period_size
&& tsched_size
&& _periods
) {
393 /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
394 _period_size
= (snd_pcm_uframes_t
) (((uint64_t) _period_size
* r
) / ss
->rate
);
395 tsched_size
= (snd_pcm_uframes_t
) (((uint64_t) tsched_size
* r
) / ss
->rate
);
398 snd_pcm_uframes_t buffer_size
;
400 pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams
, &buffer_size
) == 0);
401 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size
* 1000 / r
);
403 _period_size
= tsched_size
;
407 if (_period_size
> 0 && _periods
> 0) {
408 snd_pcm_uframes_t buffer_size
;
410 buffer_size
= _periods
* _period_size
;
412 if ((ret
= snd_pcm_hw_params_set_buffer_size_near(pcm_handle
, hwparams
, &buffer_size
)) < 0)
413 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret
));
418 /* First we pass 0 as direction to get exactly what we
419 * asked for. That this is necessary is presumably a bug
420 * in ALSA. All in all this is mostly a hint to ALSA, so
421 * we don't care if this fails. */
424 if (snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
) < 0) {
426 if (snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
) < 0) {
428 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0)
429 pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret
));
435 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0)
439 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, r
);
441 if (ss
->channels
!= c
)
442 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, c
);
445 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
));
447 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0)
450 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
451 (ret
= snd_pcm_hw_params_get_periods(hwparams
, &_periods
, &dir
)) < 0)
454 /* If the sample rate deviates too much, we need to resample */
455 if (r
< ss
->rate
*.95 || r
> ss
->rate
*1.05)
457 ss
->channels
= (uint8_t) c
;
460 pa_assert(_periods
> 0);
461 pa_assert(_period_size
> 0);
467 *period_size
= _period_size
;
470 *use_mmap
= _use_mmap
;
473 *use_tsched
= _use_tsched
;
477 snd_pcm_nonblock(pcm_handle
, 1);
484 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
) {
485 snd_pcm_sw_params_t
*swparams
;
486 snd_pcm_uframes_t boundary
;
491 snd_pcm_sw_params_alloca(&swparams
);
493 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
494 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err
));
498 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 0)) < 0) {
499 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err
));
503 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
504 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err
));
508 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
509 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err
));
513 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
514 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err
));
518 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
519 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err
));
523 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
524 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err
));
528 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
529 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err
));
536 static const struct pa_alsa_profile_info device_table
[] = {
537 {{ 1, { PA_CHANNEL_POSITION_MONO
}},
545 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
553 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
555 N_("Digital Stereo (IEC958)"),
561 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
563 N_("Digital Stereo (HDMI)"),
569 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
570 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
572 N_("Analog Surround 4.0"),
573 "analog-surround-40",
578 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
579 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
581 N_("Digital Surround 4.0 (IEC958/AC3)"),
582 "iec958-ac3-surround-40",
587 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
588 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
589 PA_CHANNEL_POSITION_LFE
}},
591 N_("Analog Surround 4.1"),
592 "analog-surround-41",
597 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
598 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
599 PA_CHANNEL_POSITION_CENTER
}},
601 N_("Analog Surround 5.0"),
602 "analog-surround-50",
607 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
608 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
609 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
}},
611 N_("Analog Surround 5.1"),
612 "analog-surround-51",
617 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
618 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
619 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
}},
621 N_("Digital Surround 5.1 (IEC958/AC3)"),
622 "iec958-ac3-surround-51",
627 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
628 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
629 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
,
630 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
}},
632 N_("Analog Surround 7.1"),
633 "analog-surround-71",
638 {{ 0, { 0 }}, NULL
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
}
641 static snd_pcm_t
*open_by_device_string_with_fallback(
643 const char *prefix_fallback
,
650 snd_pcm_uframes_t
*period_size
,
651 snd_pcm_uframes_t tsched_size
,
653 pa_bool_t
*use_tsched
,
654 pa_bool_t require_exact_channel_number
) {
656 snd_pcm_t
*pcm_handle
;
659 d
= pa_sprintf_malloc("%s:%s", prefix
, dev_id
);
661 pcm_handle
= pa_alsa_open_by_device_string(
672 require_exact_channel_number
);
675 if (!pcm_handle
&& prefix_fallback
) {
677 d
= pa_sprintf_malloc("%s:%s", prefix_fallback
, dev_id
);
679 pcm_handle
= pa_alsa_open_by_device_string(
690 require_exact_channel_number
);
697 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
704 snd_pcm_uframes_t
*period_size
,
705 snd_pcm_uframes_t tsched_size
,
707 pa_bool_t
*use_tsched
,
708 const pa_alsa_profile_info
**profile
) {
713 snd_pcm_t
*pcm_handle
;
720 pa_assert(period_size
);
722 /* First we try to find a device string with a superset of the
723 * requested channel map and open it without the plug: prefix. We
724 * iterate through our device table from top to bottom and take
725 * the first that matches. If we didn't find a working device that
726 * way, we iterate backwards, and check all devices that do not
727 * provide a superset of the requested channel map.*/
732 if ((direction
> 0) == pa_channel_map_superset(&device_table
[i
].map
, map
)) {
733 pa_sample_spec try_ss
;
735 pa_log_debug("Checking for %s (%s)", device_table
[i
].name
, device_table
[i
].alsa_name
);
737 try_ss
.channels
= device_table
[i
].map
.channels
;
738 try_ss
.rate
= ss
->rate
;
739 try_ss
.format
= ss
->format
;
741 pcm_handle
= open_by_device_string_with_fallback(
742 device_table
[i
].alsa_name
,
743 device_table
[i
].alsa_name_fallback
,
759 *map
= device_table
[i
].map
;
760 pa_assert(map
->channels
== ss
->channels
);
763 *profile
= &device_table
[i
];
771 if (!device_table
[i
+1].alsa_name
) {
772 /* OK, so we are at the end of our list. Let's turn
776 /* We are not at the end of the list, so let's simply
777 * try the next entry */
784 if (device_table
[i
+1].alsa_name
&&
785 device_table
[i
].map
.channels
== device_table
[i
+1].map
.channels
) {
787 /* OK, the next entry has the same number of channels,
792 /* Hmm, so the next entry does not have the same
793 * number of channels, so let's go backwards until we
794 * find the next entry with a different number of
797 for (i
--; i
>= 0; i
--)
798 if (device_table
[i
].map
.channels
!= device_table
[i
+1].map
.channels
)
801 /* Hmm, there is no entry with a different number of
802 * entries, then we're done */
806 /* OK, now lets find go back as long as we have the same number of channels */
808 if (device_table
[i
].map
.channels
!= device_table
[i
-1].map
.channels
)
814 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
816 d
= pa_sprintf_malloc("hw:%s", dev_id
);
817 pa_log_debug("Trying %s as last resort...", d
);
818 pcm_handle
= pa_alsa_open_by_device_string(d
, dev
, ss
, map
, mode
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, FALSE
);
821 if (pcm_handle
&& profile
)
827 snd_pcm_t
*pa_alsa_open_by_device_id_profile(
834 snd_pcm_uframes_t
*period_size
,
835 snd_pcm_uframes_t tsched_size
,
837 pa_bool_t
*use_tsched
,
838 const pa_alsa_profile_info
*profile
) {
840 snd_pcm_t
*pcm_handle
;
841 pa_sample_spec try_ss
;
848 pa_assert(period_size
);
851 try_ss
.channels
= profile
->map
.channels
;
852 try_ss
.rate
= ss
->rate
;
853 try_ss
.format
= ss
->format
;
855 pcm_handle
= open_by_device_string_with_fallback(
857 profile
->alsa_name_fallback
,
875 pa_assert(map
->channels
== ss
->channels
);
880 snd_pcm_t
*pa_alsa_open_by_device_string(
887 snd_pcm_uframes_t
*period_size
,
888 snd_pcm_uframes_t tsched_size
,
890 pa_bool_t
*use_tsched
,
891 pa_bool_t require_exact_channel_number
) {
895 snd_pcm_t
*pcm_handle
;
896 pa_bool_t reformat
= FALSE
;
902 d
= pa_xstrdup(device
);
905 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
907 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
908 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
909 * we enable nonblock mode afterwards via
910 * snd_pcm_nonblock(). Also see
911 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
913 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
914 /*SND_PCM_NONBLOCK|*/
915 SND_PCM_NO_AUTO_RESAMPLE
|
916 SND_PCM_NO_AUTO_CHANNELS
|
917 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
918 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
922 pa_log_debug("Managed to open %s", d
);
924 if ((err
= pa_alsa_set_hw_params(pcm_handle
, ss
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, require_exact_channel_number
)) < 0) {
929 snd_pcm_close(pcm_handle
);
933 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
935 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
938 t
= pa_sprintf_malloc("plug:%s", d
);
944 snd_pcm_close(pcm_handle
);
948 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
949 snd_pcm_close(pcm_handle
);
959 if (ss
->channels
!= map
->channels
)
960 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
971 int pa_alsa_probe_profiles(
973 const pa_sample_spec
*ss
,
974 void (*cb
)(const pa_alsa_profile_info
*sink
, const pa_alsa_profile_info
*source
, void *userdata
),
977 const pa_alsa_profile_info
*i
;
983 /* We try each combination of playback/capture. We also try to
984 * open only for capture resp. only for sink. Don't get confused
985 * by the trailing entry in device_table we use for this! */
987 for (i
= device_table
; i
< device_table
+ PA_ELEMENTSOF(device_table
); i
++) {
988 const pa_alsa_profile_info
*j
;
989 snd_pcm_t
*pcm_i
= NULL
;
992 pa_sample_spec try_ss
;
993 pa_channel_map try_map
;
995 pa_log_debug("Checking for playback on %s (%s)", i
->name
, i
->alsa_name
);
998 try_ss
.channels
= i
->map
.channels
;
1001 pcm_i
= open_by_device_string_with_fallback(
1003 i
->alsa_name_fallback
,
1007 SND_PCM_STREAM_PLAYBACK
,
1008 NULL
, NULL
, 0, NULL
, NULL
,
1015 for (j
= device_table
; j
< device_table
+ PA_ELEMENTSOF(device_table
); j
++) {
1016 snd_pcm_t
*pcm_j
= NULL
;
1019 pa_sample_spec try_ss
;
1020 pa_channel_map try_map
;
1022 pa_log_debug("Checking for capture on %s (%s)", j
->name
, j
->alsa_name
);
1025 try_ss
.channels
= j
->map
.channels
;
1028 pcm_j
= open_by_device_string_with_fallback(
1030 j
->alsa_name_fallback
,
1034 SND_PCM_STREAM_CAPTURE
,
1035 NULL
, NULL
, 0, NULL
, NULL
,
1043 snd_pcm_close(pcm_j
);
1045 if (i
->alsa_name
|| j
->alsa_name
)
1046 cb(i
->alsa_name
? i
: NULL
,
1047 j
->alsa_name
? j
: NULL
, userdata
);
1051 snd_pcm_close(pcm_i
);
1057 int pa_alsa_prepare_mixer(snd_mixer_t
*mixer
, const char *dev
) {
1063 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
1064 pa_log_info("Unable to attach to mixer %s: %s", dev
, pa_alsa_strerror(err
));
1068 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
1069 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err
));
1073 if ((err
= snd_mixer_load(mixer
)) < 0) {
1074 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err
));
1078 pa_log_info("Successfully attached to mixer '%s'", dev
);
1083 static pa_bool_t
elem_has_volume(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1086 if (playback
&& snd_mixer_selem_has_playback_volume(elem
))
1089 if (!playback
&& snd_mixer_selem_has_capture_volume(elem
))
1095 static pa_bool_t
elem_has_switch(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1098 if (playback
&& snd_mixer_selem_has_playback_switch(elem
))
1101 if (!playback
&& snd_mixer_selem_has_capture_switch(elem
))
1107 snd_mixer_elem_t
*pa_alsa_find_elem(snd_mixer_t
*mixer
, const char *name
, const char *fallback
, pa_bool_t playback
) {
1108 snd_mixer_elem_t
*elem
= NULL
, *fallback_elem
= NULL
;
1109 snd_mixer_selem_id_t
*sid
= NULL
;
1111 snd_mixer_selem_id_alloca(&sid
);
1116 snd_mixer_selem_id_set_name(sid
, name
);
1117 snd_mixer_selem_id_set_index(sid
, 0);
1119 if ((elem
= snd_mixer_find_selem(mixer
, sid
))) {
1121 if (elem_has_volume(elem
, playback
) &&
1122 elem_has_switch(elem
, playback
))
1125 if (!elem_has_volume(elem
, playback
) &&
1126 !elem_has_switch(elem
, playback
))
1130 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1133 snd_mixer_selem_id_set_name(sid
, fallback
);
1134 snd_mixer_selem_id_set_index(sid
, 0);
1136 if ((fallback_elem
= snd_mixer_find_selem(mixer
, sid
))) {
1138 if (elem_has_volume(fallback_elem
, playback
) &&
1139 elem_has_switch(fallback_elem
, playback
)) {
1140 elem
= fallback_elem
;
1144 if (!elem_has_volume(fallback_elem
, playback
) &&
1145 !elem_has_switch(fallback_elem
, playback
))
1146 fallback_elem
= NULL
;
1149 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
));
1152 if (elem
&& fallback_elem
) {
1154 /* Hmm, so we have both elements, but neither has both mute
1155 * and volume. Let's prefer the one with the volume */
1157 if (elem_has_volume(elem
, playback
))
1160 if (elem_has_volume(fallback_elem
, playback
)) {
1161 elem
= fallback_elem
;
1166 if (!elem
&& fallback_elem
)
1167 elem
= fallback_elem
;
1172 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid
));
1177 int pa_alsa_find_mixer_and_elem(
1180 snd_mixer_elem_t
**_e
,
1181 const char *control_name
,
1182 const pa_alsa_profile_info
*profile
) {
1186 snd_mixer_elem_t
*e
;
1187 pa_bool_t found
= FALSE
;
1194 if (control_name
&& *control_name
== 0) {
1195 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1199 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1200 pa_log("Error opening mixer: %s", pa_alsa_strerror(err
));
1204 /* First, try by name */
1205 if ((dev
= snd_pcm_name(pcm
)))
1206 if (pa_alsa_prepare_mixer(m
, dev
) >= 0)
1209 /* Then, try by card index */
1211 snd_pcm_info_t
* info
;
1212 snd_pcm_info_alloca(&info
);
1214 if (snd_pcm_info(pcm
, info
) >= 0) {
1218 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1220 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1222 if (!dev
|| !pa_streq(dev
, md
))
1223 if (pa_alsa_prepare_mixer(m
, md
) >= 0)
1236 switch (snd_pcm_stream(pcm
)) {
1238 case SND_PCM_STREAM_PLAYBACK
:
1240 e
= pa_alsa_find_elem(m
, control_name
, NULL
, TRUE
);
1242 e
= pa_alsa_find_elem(m
, profile
->playback_control_name
, profile
->playback_control_fallback
, TRUE
);
1244 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1247 case SND_PCM_STREAM_CAPTURE
:
1249 e
= pa_alsa_find_elem(m
, control_name
, NULL
, FALSE
);
1251 e
= pa_alsa_find_elem(m
, profile
->record_control_name
, profile
->record_control_fallback
, FALSE
);
1253 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1257 pa_assert_not_reached();
1273 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1274 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1276 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1277 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1278 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1280 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1281 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1282 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1284 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1286 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1287 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1289 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1290 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1292 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1293 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1294 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1295 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1296 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1297 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1298 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1299 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1300 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1301 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1302 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1303 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1304 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1305 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1306 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1307 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1308 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1309 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1310 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1311 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1312 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1313 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1314 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1315 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1316 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1317 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1318 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1319 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1320 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1321 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1322 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1323 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1325 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1327 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1328 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1329 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1331 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1332 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1333 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1337 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
) {
1339 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1340 pa_bool_t mono_used
= FALSE
;
1343 pa_assert(channel_map
);
1344 pa_assert(mixer_map
);
1346 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1348 if (channel_map
->channels
> 1 &&
1349 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1350 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1351 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1355 for (i
= 0; i
< channel_map
->channels
; i
++) {
1356 snd_mixer_selem_channel_id_t id
;
1359 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1360 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1362 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1363 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
]));
1367 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1368 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1372 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1373 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1375 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1380 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1384 alsa_channel_used
[id
] = TRUE
;
1388 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1393 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
1399 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1401 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1402 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1405 snd_output_buffer_string(out
, &s
);
1406 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
1409 pa_assert_se(snd_output_close(out
) == 0);
1412 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1415 snd_pcm_status_t
*status
;
1419 snd_pcm_status_alloca(&status
);
1421 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1423 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1425 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1426 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1429 snd_output_buffer_string(out
, &s
);
1430 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1433 pa_assert_se(snd_output_close(out
) == 0);
1436 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1440 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1444 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1448 pa_xfree(alsa_file
);
1451 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1453 void pa_alsa_redirect_errors_inc(void) {
1454 /* This is not really thread safe, but we do our best */
1456 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1457 snd_lib_error_set_handler(alsa_error_handler
);
1460 void pa_alsa_redirect_errors_dec(void) {
1463 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1466 snd_lib_error_set_handler(NULL
);
1469 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1473 if (pa_device_init_description(p
))
1476 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1477 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1481 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1482 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1489 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1490 char *cn
, *lcn
, *dn
;
1493 pa_assert(card
>= 0);
1495 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1497 if (snd_card_get_name(card
, &cn
) >= 0) {
1498 pa_proplist_sets(p
, "alsa.card_name", cn
);
1502 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1503 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1507 if ((dn
= pa_alsa_get_driver_name(card
))) {
1508 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1513 pa_udev_get_info(c
, p
, card
);
1517 pa_hal_get_info(c
, p
, card
);
1521 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1523 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1524 [SND_PCM_CLASS_GENERIC
] = "generic",
1525 [SND_PCM_CLASS_MULTI
] = "multi",
1526 [SND_PCM_CLASS_MODEM
] = "modem",
1527 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1529 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1530 [SND_PCM_CLASS_GENERIC
] = "sound",
1531 [SND_PCM_CLASS_MULTI
] = NULL
,
1532 [SND_PCM_CLASS_MODEM
] = "modem",
1533 [SND_PCM_CLASS_DIGITIZER
] = NULL
1535 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1536 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1537 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1540 snd_pcm_class_t
class;
1541 snd_pcm_subclass_t subclass
;
1542 const char *n
, *id
, *sdn
;
1546 pa_assert(pcm_info
);
1548 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1550 class = snd_pcm_info_get_class(pcm_info
);
1551 if (class <= SND_PCM_CLASS_LAST
) {
1552 if (class_table
[class])
1553 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1554 if (alsa_class_table
[class])
1555 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1558 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1559 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1560 if (alsa_subclass_table
[subclass
])
1561 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1563 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1564 pa_proplist_sets(p
, "alsa.name", n
);
1566 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1567 pa_proplist_sets(p
, "alsa.id", id
);
1569 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1570 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1571 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1573 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1575 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1576 pa_alsa_init_proplist_card(c
, p
, card
);
1579 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
, snd_mixer_elem_t
*elem
) {
1580 snd_pcm_hw_params_t
*hwparams
;
1581 snd_pcm_info_t
*info
;
1584 snd_pcm_hw_params_alloca(&hwparams
);
1585 snd_pcm_info_alloca(&info
);
1587 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1588 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
1591 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1592 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1596 pa_proplist_sets(p
, "alsa.mixer_element", snd_mixer_selem_get_name(elem
));
1598 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1599 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
1601 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1604 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1605 snd_pcm_state_t state
;
1610 if (revents
& POLLERR
)
1611 pa_log_debug("Got POLLERR from ALSA");
1612 if (revents
& POLLNVAL
)
1613 pa_log_warn("Got POLLNVAL from ALSA");
1614 if (revents
& POLLHUP
)
1615 pa_log_warn("Got POLLHUP from ALSA");
1616 if (revents
& POLLPRI
)
1617 pa_log_warn("Got POLLPRI from ALSA");
1618 if (revents
& POLLIN
)
1619 pa_log_debug("Got POLLIN from ALSA");
1620 if (revents
& POLLOUT
)
1621 pa_log_debug("Got POLLOUT from ALSA");
1623 state
= snd_pcm_state(pcm
);
1624 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1626 /* Try to recover from this error */
1630 case SND_PCM_STATE_XRUN
:
1631 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1632 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1637 case SND_PCM_STATE_SUSPENDED
:
1638 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1639 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1648 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1649 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1658 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1660 struct pollfd
*pollfd
;
1661 pa_rtpoll_item
*item
;
1665 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1666 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1670 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1671 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1673 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1674 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1675 pa_rtpoll_item_free(item
);
1682 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1683 snd_pcm_sframes_t n
;
1687 pa_assert(hwbuf_size
> 0);
1690 /* Some ALSA driver expose weird bugs, let's inform the user about
1691 * what is going on */
1693 n
= snd_pcm_avail(pcm
);
1698 k
= (size_t) n
* pa_frame_size(ss
);
1700 if (k
>= hwbuf_size
* 5 ||
1701 k
>= pa_bytes_per_second(ss
)*10) {
1704 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1705 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1706 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1708 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1711 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1714 /* Mhmm, let's try not to fail completely */
1715 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1721 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1728 pa_assert(hwbuf_size
> 0);
1731 /* Some ALSA driver expose weird bugs, let's inform the user about
1732 * what is going on */
1734 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1737 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1739 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1741 if (abs_k
>= hwbuf_size
* 5 ||
1742 abs_k
>= pa_bytes_per_second(ss
)*10) {
1745 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1746 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1747 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1750 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1753 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1756 /* Mhmm, let's try not to fail completely */
1758 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1760 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1766 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
) {
1768 snd_pcm_uframes_t before
;
1775 pa_assert(hwbuf_size
> 0);
1780 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1785 k
= (size_t) *frames
* pa_frame_size(ss
);
1787 if (*frames
> before
||
1788 k
>= hwbuf_size
* 3 ||
1789 k
>= pa_bytes_per_second(ss
)*10)
1792 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1793 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1794 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1796 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1799 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1805 char *pa_alsa_get_driver_name(int card
) {
1808 pa_assert(card
>= 0);
1810 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1817 n
= pa_xstrdup(pa_path_get_filename(m
));
1823 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1825 snd_pcm_info_t
* info
;
1826 snd_pcm_info_alloca(&info
);
1830 if (snd_pcm_info(pcm
, info
) < 0)
1833 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1836 return pa_alsa_get_driver_name(card
);
1839 char *pa_alsa_get_reserve_name(const char *device
) {
1845 if ((t
= strchr(device
, ':')))
1848 if ((i
= snd_card_get_index(device
)) < 0) {
1851 if (pa_atoi(device
, &k
) < 0)
1857 return pa_sprintf_malloc("Audio%i", i
);
1860 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1861 snd_pcm_info_t
* info
;
1862 snd_pcm_info_alloca(&info
);
1866 if (snd_pcm_info(pcm
, info
) < 0)
1869 return snd_pcm_info_get_card(info
) >= 0;
1872 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1873 snd_pcm_info_t
* info
;
1874 snd_pcm_info_alloca(&info
);
1878 if (snd_pcm_info(pcm
, info
) < 0)
1881 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1884 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1886 const char* pa_alsa_strerror(int errnum
) {
1887 const char *original
= NULL
;
1888 char *translated
, *t
;
1891 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1894 original
= snd_strerror(errnum
);
1897 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1901 if (!(translated
= pa_locale_to_utf8(original
))) {
1902 pa_log_warn("Unable to convert error string to locale, filtering.");
1903 translated
= pa_utf8_filter(original
);
1906 PA_STATIC_TLS_SET(cstrerror
, translated
);