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 snd_pcm_uframes_t buffer_size
;
338 unsigned int r
= ss
->rate
;
339 unsigned int c
= ss
->channels
;
340 pa_sample_format_t f
= ss
->format
;
341 snd_pcm_hw_params_t
*hwparams
;
342 pa_bool_t _use_mmap
= use_mmap
&& *use_mmap
;
343 pa_bool_t _use_tsched
= use_tsched
&& *use_tsched
;
346 pa_assert(pcm_handle
);
349 snd_pcm_hw_params_alloca(&hwparams
);
351 if ((ret
= snd_pcm_hw_params_any(pcm_handle
, hwparams
)) < 0)
354 if ((ret
= snd_pcm_hw_params_set_rate_resample(pcm_handle
, hwparams
, 0)) < 0)
359 if (snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) < 0) {
361 /* mmap() didn't work, fall back to interleaved */
363 if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
369 } else if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
375 if ((ret
= set_format(pcm_handle
, hwparams
, &f
)) < 0)
378 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &r
, NULL
)) < 0)
381 if (require_exact_channel_number
) {
382 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, c
)) < 0)
385 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0)
389 if ((ret
= snd_pcm_hw_params_set_periods_integer(pcm_handle
, hwparams
)) < 0)
392 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 _period_size
= tsched_size
;
401 pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams
, &buffer_size
) == 0);
402 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size
* 1000 / r
);
405 buffer_size
= _periods
* _period_size
;
409 /* First we pass 0 as direction to get exactly what we asked
410 * for. That this is necessary is presumably a bug in ALSA */
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) {
417 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0)
423 if (_period_size
> 0)
424 if ((ret
= snd_pcm_hw_params_set_buffer_size_near(pcm_handle
, hwparams
, &buffer_size
)) < 0)
428 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0)
432 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, r
);
434 if (ss
->channels
!= c
)
435 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, c
);
438 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
));
440 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0)
443 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
444 (ret
= snd_pcm_hw_params_get_periods(hwparams
, &_periods
, &dir
)) < 0)
447 /* If the sample rate deviates too much, we need to resample */
448 if (r
< ss
->rate
*.95 || r
> ss
->rate
*1.05)
450 ss
->channels
= (uint8_t) c
;
453 pa_assert(_periods
> 0);
454 pa_assert(_period_size
> 0);
460 *period_size
= _period_size
;
463 *use_mmap
= _use_mmap
;
466 *use_tsched
= _use_tsched
;
470 snd_pcm_nonblock(pcm_handle
, 1);
477 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
) {
478 snd_pcm_sw_params_t
*swparams
;
479 snd_pcm_uframes_t boundary
;
484 snd_pcm_sw_params_alloca(&swparams
);
486 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
487 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err
));
491 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 0)) < 0) {
492 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err
));
496 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
497 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err
));
501 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
502 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err
));
506 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
507 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err
));
511 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
512 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err
));
516 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
517 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err
));
521 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
522 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err
));
529 static const struct pa_alsa_profile_info device_table
[] = {
530 {{ 1, { PA_CHANNEL_POSITION_MONO
}},
538 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
546 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
548 N_("Digital Stereo (IEC958)"),
554 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
556 N_("Digital Stereo (HDMI)"),
562 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
563 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
565 N_("Analog Surround 4.0"),
566 "analog-surround-40",
571 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
572 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
574 N_("Digital Surround 4.0 (IEC958/AC3)"),
575 "iec958-ac3-surround-40",
580 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
581 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
582 PA_CHANNEL_POSITION_LFE
}},
584 N_("Analog Surround 4.1"),
585 "analog-surround-41",
590 {{ 5, { 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_CENTER
}},
594 N_("Analog Surround 5.0"),
595 "analog-surround-50",
600 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
601 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
602 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
}},
604 N_("Analog Surround 5.1"),
605 "analog-surround-51",
610 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
611 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
612 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
}},
614 N_("Digital Surround 5.1 (IEC958/AC3)"),
615 "iec958-ac3-surround-51",
620 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
621 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
622 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
,
623 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
}},
625 N_("Analog Surround 7.1"),
626 "analog-surround-71",
631 {{ 0, { 0 }}, NULL
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
}
634 static snd_pcm_t
*open_by_device_string_with_fallback(
636 const char *prefix_fallback
,
643 snd_pcm_uframes_t
*period_size
,
644 snd_pcm_uframes_t tsched_size
,
646 pa_bool_t
*use_tsched
,
647 pa_bool_t require_exact_channel_number
) {
649 snd_pcm_t
*pcm_handle
;
652 d
= pa_sprintf_malloc("%s:%s", prefix
, dev_id
);
654 pcm_handle
= pa_alsa_open_by_device_string(
665 require_exact_channel_number
);
668 if (!pcm_handle
&& prefix_fallback
) {
670 d
= pa_sprintf_malloc("%s:%s", prefix_fallback
, dev_id
);
672 pcm_handle
= pa_alsa_open_by_device_string(
683 require_exact_channel_number
);
690 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
697 snd_pcm_uframes_t
*period_size
,
698 snd_pcm_uframes_t tsched_size
,
700 pa_bool_t
*use_tsched
,
701 const pa_alsa_profile_info
**profile
) {
706 snd_pcm_t
*pcm_handle
;
713 pa_assert(period_size
);
715 /* First we try to find a device string with a superset of the
716 * requested channel map and open it without the plug: prefix. We
717 * iterate through our device table from top to bottom and take
718 * the first that matches. If we didn't find a working device that
719 * way, we iterate backwards, and check all devices that do not
720 * provide a superset of the requested channel map.*/
725 if ((direction
> 0) == pa_channel_map_superset(&device_table
[i
].map
, map
)) {
726 pa_sample_spec try_ss
;
728 pa_log_debug("Checking for %s (%s)", device_table
[i
].name
, device_table
[i
].alsa_name
);
730 try_ss
.channels
= device_table
[i
].map
.channels
;
731 try_ss
.rate
= ss
->rate
;
732 try_ss
.format
= ss
->format
;
734 pcm_handle
= open_by_device_string_with_fallback(
735 device_table
[i
].alsa_name
,
736 device_table
[i
].alsa_name_fallback
,
752 *map
= device_table
[i
].map
;
753 pa_assert(map
->channels
== ss
->channels
);
756 *profile
= &device_table
[i
];
764 if (!device_table
[i
+1].alsa_name
) {
765 /* OK, so we are at the end of our list. Let's turn
769 /* We are not at the end of the list, so let's simply
770 * try the next entry */
777 if (device_table
[i
+1].alsa_name
&&
778 device_table
[i
].map
.channels
== device_table
[i
+1].map
.channels
) {
780 /* OK, the next entry has the same number of channels,
785 /* Hmm, so the next entry does not have the same
786 * number of channels, so let's go backwards until we
787 * find the next entry with a different number of
790 for (i
--; i
>= 0; i
--)
791 if (device_table
[i
].map
.channels
!= device_table
[i
+1].map
.channels
)
794 /* Hmm, there is no entry with a different number of
795 * entries, then we're done */
799 /* OK, now lets find go back as long as we have the same number of channels */
801 if (device_table
[i
].map
.channels
!= device_table
[i
-1].map
.channels
)
807 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
809 d
= pa_sprintf_malloc("hw:%s", dev_id
);
810 pa_log_debug("Trying %s as last resort...", d
);
811 pcm_handle
= pa_alsa_open_by_device_string(d
, dev
, ss
, map
, mode
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, FALSE
);
814 if (pcm_handle
&& profile
)
820 snd_pcm_t
*pa_alsa_open_by_device_id_profile(
827 snd_pcm_uframes_t
*period_size
,
828 snd_pcm_uframes_t tsched_size
,
830 pa_bool_t
*use_tsched
,
831 const pa_alsa_profile_info
*profile
) {
833 snd_pcm_t
*pcm_handle
;
834 pa_sample_spec try_ss
;
841 pa_assert(period_size
);
844 try_ss
.channels
= profile
->map
.channels
;
845 try_ss
.rate
= ss
->rate
;
846 try_ss
.format
= ss
->format
;
848 pcm_handle
= open_by_device_string_with_fallback(
850 profile
->alsa_name_fallback
,
868 pa_assert(map
->channels
== ss
->channels
);
873 snd_pcm_t
*pa_alsa_open_by_device_string(
880 snd_pcm_uframes_t
*period_size
,
881 snd_pcm_uframes_t tsched_size
,
883 pa_bool_t
*use_tsched
,
884 pa_bool_t require_exact_channel_number
) {
888 snd_pcm_t
*pcm_handle
;
889 pa_bool_t reformat
= FALSE
;
895 d
= pa_xstrdup(device
);
898 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
900 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
901 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
902 * we enable nonblock mode afterwards via
903 * snd_pcm_nonblock(). Also see
904 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
906 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
907 /*SND_PCM_NONBLOCK|*/
908 SND_PCM_NO_AUTO_RESAMPLE
|
909 SND_PCM_NO_AUTO_CHANNELS
|
910 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
911 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
915 pa_log_debug("Managed to open %s", d
);
917 if ((err
= pa_alsa_set_hw_params(pcm_handle
, ss
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, require_exact_channel_number
)) < 0) {
922 snd_pcm_close(pcm_handle
);
926 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
928 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
931 t
= pa_sprintf_malloc("plug:%s", d
);
937 snd_pcm_close(pcm_handle
);
941 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
942 snd_pcm_close(pcm_handle
);
952 if (ss
->channels
!= map
->channels
)
953 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
964 int pa_alsa_probe_profiles(
966 const pa_sample_spec
*ss
,
967 void (*cb
)(const pa_alsa_profile_info
*sink
, const pa_alsa_profile_info
*source
, void *userdata
),
970 const pa_alsa_profile_info
*i
;
976 /* We try each combination of playback/capture. We also try to
977 * open only for capture resp. only for sink. Don't get confused
978 * by the trailing entry in device_table we use for this! */
980 for (i
= device_table
; i
< device_table
+ PA_ELEMENTSOF(device_table
); i
++) {
981 const pa_alsa_profile_info
*j
;
982 snd_pcm_t
*pcm_i
= NULL
;
985 pa_sample_spec try_ss
;
986 pa_channel_map try_map
;
988 pa_log_debug("Checking for playback on %s (%s)", i
->name
, i
->alsa_name
);
991 try_ss
.channels
= i
->map
.channels
;
994 pcm_i
= open_by_device_string_with_fallback(
996 i
->alsa_name_fallback
,
1000 SND_PCM_STREAM_PLAYBACK
,
1001 NULL
, NULL
, 0, NULL
, NULL
,
1008 for (j
= device_table
; j
< device_table
+ PA_ELEMENTSOF(device_table
); j
++) {
1009 snd_pcm_t
*pcm_j
= NULL
;
1012 pa_sample_spec try_ss
;
1013 pa_channel_map try_map
;
1015 pa_log_debug("Checking for capture on %s (%s)", j
->name
, j
->alsa_name
);
1018 try_ss
.channels
= j
->map
.channels
;
1021 pcm_j
= open_by_device_string_with_fallback(
1023 j
->alsa_name_fallback
,
1027 SND_PCM_STREAM_CAPTURE
,
1028 NULL
, NULL
, 0, NULL
, NULL
,
1036 snd_pcm_close(pcm_j
);
1038 if (i
->alsa_name
|| j
->alsa_name
)
1039 cb(i
->alsa_name
? i
: NULL
,
1040 j
->alsa_name
? j
: NULL
, userdata
);
1044 snd_pcm_close(pcm_i
);
1050 int pa_alsa_prepare_mixer(snd_mixer_t
*mixer
, const char *dev
) {
1056 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
1057 pa_log_info("Unable to attach to mixer %s: %s", dev
, pa_alsa_strerror(err
));
1061 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
1062 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err
));
1066 if ((err
= snd_mixer_load(mixer
)) < 0) {
1067 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err
));
1071 pa_log_info("Successfully attached to mixer '%s'", dev
);
1076 static pa_bool_t
elem_has_volume(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1079 if (playback
&& snd_mixer_selem_has_playback_volume(elem
))
1082 if (!playback
&& snd_mixer_selem_has_capture_volume(elem
))
1088 static pa_bool_t
elem_has_switch(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1091 if (playback
&& snd_mixer_selem_has_playback_switch(elem
))
1094 if (!playback
&& snd_mixer_selem_has_capture_switch(elem
))
1100 snd_mixer_elem_t
*pa_alsa_find_elem(snd_mixer_t
*mixer
, const char *name
, const char *fallback
, pa_bool_t playback
) {
1101 snd_mixer_elem_t
*elem
= NULL
, *fallback_elem
= NULL
;
1102 snd_mixer_selem_id_t
*sid
= NULL
;
1104 snd_mixer_selem_id_alloca(&sid
);
1109 snd_mixer_selem_id_set_name(sid
, name
);
1110 snd_mixer_selem_id_set_index(sid
, 0);
1112 if ((elem
= snd_mixer_find_selem(mixer
, sid
))) {
1114 if (elem_has_volume(elem
, playback
) &&
1115 elem_has_switch(elem
, playback
))
1118 if (!elem_has_volume(elem
, playback
) &&
1119 !elem_has_switch(elem
, playback
))
1123 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1126 snd_mixer_selem_id_set_name(sid
, fallback
);
1127 snd_mixer_selem_id_set_index(sid
, 0);
1129 if ((fallback_elem
= snd_mixer_find_selem(mixer
, sid
))) {
1131 if (elem_has_volume(fallback_elem
, playback
) &&
1132 elem_has_switch(fallback_elem
, playback
)) {
1133 elem
= fallback_elem
;
1137 if (!elem_has_volume(fallback_elem
, playback
) &&
1138 !elem_has_switch(fallback_elem
, playback
))
1139 fallback_elem
= NULL
;
1142 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
));
1145 if (elem
&& fallback_elem
) {
1147 /* Hmm, so we have both elements, but neither has both mute
1148 * and volume. Let's prefer the one with the volume */
1150 if (elem_has_volume(elem
, playback
))
1153 if (elem_has_volume(fallback_elem
, playback
)) {
1154 elem
= fallback_elem
;
1159 if (!elem
&& fallback_elem
)
1160 elem
= fallback_elem
;
1165 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid
));
1170 int pa_alsa_find_mixer_and_elem(
1173 snd_mixer_elem_t
**_e
,
1174 const char *control_name
,
1175 const pa_alsa_profile_info
*profile
) {
1179 snd_mixer_elem_t
*e
;
1180 pa_bool_t found
= FALSE
;
1187 if (control_name
&& *control_name
== 0) {
1188 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1192 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1193 pa_log("Error opening mixer: %s", pa_alsa_strerror(err
));
1197 /* First, try by name */
1198 if ((dev
= snd_pcm_name(pcm
)))
1199 if (pa_alsa_prepare_mixer(m
, dev
) >= 0)
1202 /* Then, try by card index */
1204 snd_pcm_info_t
* info
;
1205 snd_pcm_info_alloca(&info
);
1207 if (snd_pcm_info(pcm
, info
) >= 0) {
1211 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1213 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1215 if (!dev
|| !pa_streq(dev
, md
))
1216 if (pa_alsa_prepare_mixer(m
, md
) >= 0)
1229 switch (snd_pcm_stream(pcm
)) {
1231 case SND_PCM_STREAM_PLAYBACK
:
1233 e
= pa_alsa_find_elem(m
, control_name
, NULL
, TRUE
);
1235 e
= pa_alsa_find_elem(m
, profile
->playback_control_name
, profile
->playback_control_fallback
, TRUE
);
1237 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1240 case SND_PCM_STREAM_CAPTURE
:
1242 e
= pa_alsa_find_elem(m
, control_name
, NULL
, FALSE
);
1244 e
= pa_alsa_find_elem(m
, profile
->record_control_name
, profile
->record_control_fallback
, FALSE
);
1246 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1250 pa_assert_not_reached();
1266 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1267 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1269 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1270 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1271 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1273 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1274 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1275 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1277 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1279 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1280 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1282 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1283 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1285 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1286 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1287 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1288 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1289 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1290 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1291 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1292 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1293 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1294 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1295 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1296 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1297 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1298 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1299 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1300 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1301 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1302 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1303 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1304 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1305 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1306 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1307 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1308 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1309 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1310 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1311 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1312 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1313 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1314 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1315 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1316 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1318 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1320 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1321 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1322 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1324 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1325 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1326 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1330 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
) {
1332 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1333 pa_bool_t mono_used
= FALSE
;
1336 pa_assert(channel_map
);
1337 pa_assert(mixer_map
);
1339 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1341 if (channel_map
->channels
> 1 &&
1342 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1343 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1344 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1348 for (i
= 0; i
< channel_map
->channels
; i
++) {
1349 snd_mixer_selem_channel_id_t id
;
1352 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1353 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1355 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1356 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
]));
1360 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1361 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1365 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1366 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1368 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1373 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1377 alsa_channel_used
[id
] = TRUE
;
1381 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1386 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
1392 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1394 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1395 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1398 snd_output_buffer_string(out
, &s
);
1399 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
1402 pa_assert_se(snd_output_close(out
) == 0);
1405 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1408 snd_pcm_status_t
*status
;
1412 snd_pcm_status_alloca(&status
);
1414 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1416 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1418 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1419 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1422 snd_output_buffer_string(out
, &s
);
1423 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1426 pa_assert_se(snd_output_close(out
) == 0);
1429 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1433 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1437 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1441 pa_xfree(alsa_file
);
1444 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1446 void pa_alsa_redirect_errors_inc(void) {
1447 /* This is not really thread safe, but we do our best */
1449 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1450 snd_lib_error_set_handler(alsa_error_handler
);
1453 void pa_alsa_redirect_errors_dec(void) {
1456 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1459 snd_lib_error_set_handler(NULL
);
1462 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1466 if (pa_device_init_description(p
))
1469 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1470 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1474 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1475 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1482 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1483 char *cn
, *lcn
, *dn
;
1486 pa_assert(card
>= 0);
1488 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1490 if (snd_card_get_name(card
, &cn
) >= 0) {
1491 pa_proplist_sets(p
, "alsa.card_name", cn
);
1495 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1496 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1500 if ((dn
= pa_alsa_get_driver_name(card
))) {
1501 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1506 pa_udev_get_info(c
, p
, card
);
1510 pa_hal_get_info(c
, p
, card
);
1514 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1516 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1517 [SND_PCM_CLASS_GENERIC
] = "generic",
1518 [SND_PCM_CLASS_MULTI
] = "multi",
1519 [SND_PCM_CLASS_MODEM
] = "modem",
1520 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1522 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1523 [SND_PCM_CLASS_GENERIC
] = "sound",
1524 [SND_PCM_CLASS_MULTI
] = NULL
,
1525 [SND_PCM_CLASS_MODEM
] = "modem",
1526 [SND_PCM_CLASS_DIGITIZER
] = NULL
1528 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1529 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1530 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1533 snd_pcm_class_t
class;
1534 snd_pcm_subclass_t subclass
;
1535 const char *n
, *id
, *sdn
;
1539 pa_assert(pcm_info
);
1541 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1543 class = snd_pcm_info_get_class(pcm_info
);
1544 if (class <= SND_PCM_CLASS_LAST
) {
1545 if (class_table
[class])
1546 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1547 if (alsa_class_table
[class])
1548 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1551 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1552 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1553 if (alsa_subclass_table
[subclass
])
1554 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1556 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1557 pa_proplist_sets(p
, "alsa.name", n
);
1559 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1560 pa_proplist_sets(p
, "alsa.id", id
);
1562 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1563 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1564 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1566 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1568 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1569 pa_alsa_init_proplist_card(c
, p
, card
);
1572 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
, snd_mixer_elem_t
*elem
) {
1573 snd_pcm_hw_params_t
*hwparams
;
1574 snd_pcm_info_t
*info
;
1577 snd_pcm_hw_params_alloca(&hwparams
);
1578 snd_pcm_info_alloca(&info
);
1580 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1581 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
1584 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1585 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1589 pa_proplist_sets(p
, "alsa.mixer_element", snd_mixer_selem_get_name(elem
));
1591 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1592 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
1594 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1597 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1598 snd_pcm_state_t state
;
1603 if (revents
& POLLERR
)
1604 pa_log_debug("Got POLLERR from ALSA");
1605 if (revents
& POLLNVAL
)
1606 pa_log_warn("Got POLLNVAL from ALSA");
1607 if (revents
& POLLHUP
)
1608 pa_log_warn("Got POLLHUP from ALSA");
1609 if (revents
& POLLPRI
)
1610 pa_log_warn("Got POLLPRI from ALSA");
1611 if (revents
& POLLIN
)
1612 pa_log_debug("Got POLLIN from ALSA");
1613 if (revents
& POLLOUT
)
1614 pa_log_debug("Got POLLOUT from ALSA");
1616 state
= snd_pcm_state(pcm
);
1617 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1619 /* Try to recover from this error */
1623 case SND_PCM_STATE_XRUN
:
1624 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1625 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1630 case SND_PCM_STATE_SUSPENDED
:
1631 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1632 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1641 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1642 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1651 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1653 struct pollfd
*pollfd
;
1654 pa_rtpoll_item
*item
;
1658 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1659 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1663 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1664 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1666 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1667 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1668 pa_rtpoll_item_free(item
);
1675 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1676 snd_pcm_sframes_t n
;
1680 pa_assert(hwbuf_size
> 0);
1683 /* Some ALSA driver expose weird bugs, let's inform the user about
1684 * what is going on */
1686 n
= snd_pcm_avail(pcm
);
1691 k
= (size_t) n
* pa_frame_size(ss
);
1693 if (k
>= hwbuf_size
* 5 ||
1694 k
>= pa_bytes_per_second(ss
)*10) {
1697 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1698 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1699 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1701 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1704 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1707 /* Mhmm, let's try not to fail completely */
1708 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1714 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1721 pa_assert(hwbuf_size
> 0);
1724 /* Some ALSA driver expose weird bugs, let's inform the user about
1725 * what is going on */
1727 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1730 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1732 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1734 if (abs_k
>= hwbuf_size
* 5 ||
1735 abs_k
>= pa_bytes_per_second(ss
)*10) {
1738 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1739 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1740 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1743 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1746 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1749 /* Mhmm, let's try not to fail completely */
1751 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1753 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1759 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
) {
1761 snd_pcm_uframes_t before
;
1768 pa_assert(hwbuf_size
> 0);
1773 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1778 k
= (size_t) *frames
* pa_frame_size(ss
);
1780 if (*frames
> before
||
1781 k
>= hwbuf_size
* 3 ||
1782 k
>= pa_bytes_per_second(ss
)*10)
1785 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1786 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1787 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1789 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1792 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1798 char *pa_alsa_get_driver_name(int card
) {
1801 pa_assert(card
>= 0);
1803 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1810 n
= pa_xstrdup(pa_path_get_filename(m
));
1816 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1818 snd_pcm_info_t
* info
;
1819 snd_pcm_info_alloca(&info
);
1823 if (snd_pcm_info(pcm
, info
) < 0)
1826 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1829 return pa_alsa_get_driver_name(card
);
1832 char *pa_alsa_get_reserve_name(const char *device
) {
1838 if ((t
= strchr(device
, ':')))
1841 if ((i
= snd_card_get_index(device
)) < 0) {
1844 if (pa_atoi(device
, &k
) < 0)
1850 return pa_sprintf_malloc("Audio%i", i
);
1853 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1854 snd_pcm_info_t
* info
;
1855 snd_pcm_info_alloca(&info
);
1859 if (snd_pcm_info(pcm
, info
) < 0)
1862 return snd_pcm_info_get_card(info
) >= 0;
1865 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1866 snd_pcm_info_t
* info
;
1867 snd_pcm_info_alloca(&info
);
1871 if (snd_pcm_info(pcm
, info
) < 0)
1874 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1877 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1879 const char* pa_alsa_strerror(int errnum
) {
1880 const char *original
= NULL
;
1881 char *translated
, *t
;
1884 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1887 original
= snd_strerror(errnum
);
1890 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1894 if (!(translated
= pa_locale_to_utf8(original
))) {
1895 pa_log_warn("Unable to convert error string to locale, filtering.");
1896 translated
= pa_utf8_filter(original
);
1899 PA_STATIC_TLS_SET(cstrerror
, translated
);