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
, 0, NULL
, NULL
, NULL
, NULL
}
634 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
641 snd_pcm_uframes_t
*period_size
,
642 snd_pcm_uframes_t tsched_size
,
644 pa_bool_t
*use_tsched
,
645 const pa_alsa_profile_info
**profile
) {
650 snd_pcm_t
*pcm_handle
;
657 pa_assert(period_size
);
659 /* First we try to find a device string with a superset of the
660 * requested channel map and open it without the plug: prefix. We
661 * iterate through our device table from top to bottom and take
662 * the first that matches. If we didn't find a working device that
663 * way, we iterate backwards, and check all devices that do not
664 * provide a superset of the requested channel map.*/
669 if ((direction
> 0) == pa_channel_map_superset(&device_table
[i
].map
, map
)) {
670 pa_sample_spec try_ss
;
672 pa_log_debug("Checking for %s (%s)", device_table
[i
].name
, device_table
[i
].alsa_name
);
674 d
= pa_sprintf_malloc("%s:%s", device_table
[i
].alsa_name
, dev_id
);
676 try_ss
.channels
= device_table
[i
].map
.channels
;
677 try_ss
.rate
= ss
->rate
;
678 try_ss
.format
= ss
->format
;
680 pcm_handle
= pa_alsa_open_by_device_string(
698 *map
= device_table
[i
].map
;
699 pa_assert(map
->channels
== ss
->channels
);
702 *profile
= &device_table
[i
];
709 if (!device_table
[i
+1].alsa_name
) {
710 /* OK, so we are at the end of our list. Let's turn
714 /* We are not at the end of the list, so let's simply
715 * try the next entry */
722 if (device_table
[i
+1].alsa_name
&&
723 device_table
[i
].map
.channels
== device_table
[i
+1].map
.channels
) {
725 /* OK, the next entry has the same number of channels,
730 /* Hmm, so the next entry does not have the same
731 * number of channels, so let's go backwards until we
732 * find the next entry with a different number of
735 for (i
--; i
>= 0; i
--)
736 if (device_table
[i
].map
.channels
!= device_table
[i
+1].map
.channels
)
739 /* Hmm, there is no entry with a different number of
740 * entries, then we're done */
744 /* OK, now lets find go back as long as we have the same number of channels */
746 if (device_table
[i
].map
.channels
!= device_table
[i
-1].map
.channels
)
752 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
754 d
= pa_sprintf_malloc("hw:%s", dev_id
);
755 pa_log_debug("Trying %s as last resort...", d
);
756 pcm_handle
= pa_alsa_open_by_device_string(d
, dev
, ss
, map
, mode
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, FALSE
);
759 if (pcm_handle
&& profile
)
765 snd_pcm_t
*pa_alsa_open_by_device_id_profile(
772 snd_pcm_uframes_t
*period_size
,
773 snd_pcm_uframes_t tsched_size
,
775 pa_bool_t
*use_tsched
,
776 const pa_alsa_profile_info
*profile
) {
779 snd_pcm_t
*pcm_handle
;
780 pa_sample_spec try_ss
;
787 pa_assert(period_size
);
790 d
= pa_sprintf_malloc("%s:%s", profile
->alsa_name
, dev_id
);
792 try_ss
.channels
= profile
->map
.channels
;
793 try_ss
.rate
= ss
->rate
;
794 try_ss
.format
= ss
->format
;
796 pcm_handle
= pa_alsa_open_by_device_string(
816 pa_assert(map
->channels
== ss
->channels
);
821 snd_pcm_t
*pa_alsa_open_by_device_string(
828 snd_pcm_uframes_t
*period_size
,
829 snd_pcm_uframes_t tsched_size
,
831 pa_bool_t
*use_tsched
,
832 pa_bool_t require_exact_channel_number
) {
836 snd_pcm_t
*pcm_handle
;
837 pa_bool_t reformat
= FALSE
;
843 d
= pa_xstrdup(device
);
846 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
848 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
849 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
850 * we enable nonblock mode afterwards via
851 * snd_pcm_nonblock(). Also see
852 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
854 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
855 /*SND_PCM_NONBLOCK|*/
856 SND_PCM_NO_AUTO_RESAMPLE
|
857 SND_PCM_NO_AUTO_CHANNELS
|
858 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
859 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
863 if ((err
= pa_alsa_set_hw_params(pcm_handle
, ss
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, require_exact_channel_number
)) < 0) {
868 snd_pcm_close(pcm_handle
);
872 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
874 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
877 t
= pa_sprintf_malloc("plug:%s", d
);
883 snd_pcm_close(pcm_handle
);
887 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
888 snd_pcm_close(pcm_handle
);
898 if (ss
->channels
!= map
->channels
)
899 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
910 int pa_alsa_probe_profiles(
912 const pa_sample_spec
*ss
,
913 void (*cb
)(const pa_alsa_profile_info
*sink
, const pa_alsa_profile_info
*source
, void *userdata
),
916 const pa_alsa_profile_info
*i
;
922 /* We try each combination of playback/capture. We also try to
923 * open only for capture resp. only for sink. Don't get confused
924 * by the trailing entry in device_table we use for this! */
926 for (i
= device_table
; i
< device_table
+ PA_ELEMENTSOF(device_table
); i
++) {
927 const pa_alsa_profile_info
*j
;
928 snd_pcm_t
*pcm_i
= NULL
;
932 pa_sample_spec try_ss
;
933 pa_channel_map try_map
;
935 pa_log_debug("Checking for playback on %s (%s)", i
->name
, i
->alsa_name
);
936 id
= pa_sprintf_malloc("%s:%s", i
->alsa_name
, dev_id
);
939 try_ss
.channels
= i
->map
.channels
;
942 pcm_i
= pa_alsa_open_by_device_string(
945 SND_PCM_STREAM_PLAYBACK
,
946 NULL
, NULL
, 0, NULL
, NULL
,
955 for (j
= device_table
; j
< device_table
+ PA_ELEMENTSOF(device_table
); j
++) {
956 snd_pcm_t
*pcm_j
= NULL
;
960 pa_sample_spec try_ss
;
961 pa_channel_map try_map
;
963 pa_log_debug("Checking for capture on %s (%s)", j
->name
, j
->alsa_name
);
964 jd
= pa_sprintf_malloc("%s:%s", j
->alsa_name
, dev_id
);
967 try_ss
.channels
= j
->map
.channels
;
970 pcm_j
= pa_alsa_open_by_device_string(
973 SND_PCM_STREAM_CAPTURE
,
974 NULL
, NULL
, 0, NULL
, NULL
,
984 snd_pcm_close(pcm_j
);
986 if (i
->alsa_name
|| j
->alsa_name
)
987 cb(i
->alsa_name
? i
: NULL
,
988 j
->alsa_name
? j
: NULL
, userdata
);
992 snd_pcm_close(pcm_i
);
998 int pa_alsa_prepare_mixer(snd_mixer_t
*mixer
, const char *dev
) {
1004 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
1005 pa_log_info("Unable to attach to mixer %s: %s", dev
, pa_alsa_strerror(err
));
1009 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
1010 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err
));
1014 if ((err
= snd_mixer_load(mixer
)) < 0) {
1015 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err
));
1019 pa_log_info("Successfully attached to mixer '%s'", dev
);
1024 static pa_bool_t
elem_has_volume(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1027 if (playback
&& snd_mixer_selem_has_playback_volume(elem
))
1030 if (!playback
&& snd_mixer_selem_has_capture_volume(elem
))
1036 static pa_bool_t
elem_has_switch(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1039 if (playback
&& snd_mixer_selem_has_playback_switch(elem
))
1042 if (!playback
&& snd_mixer_selem_has_capture_switch(elem
))
1048 snd_mixer_elem_t
*pa_alsa_find_elem(snd_mixer_t
*mixer
, const char *name
, const char *fallback
, pa_bool_t playback
) {
1049 snd_mixer_elem_t
*elem
= NULL
, *fallback_elem
= NULL
;
1050 snd_mixer_selem_id_t
*sid
= NULL
;
1052 snd_mixer_selem_id_alloca(&sid
);
1057 snd_mixer_selem_id_set_name(sid
, name
);
1058 snd_mixer_selem_id_set_index(sid
, 0);
1060 if ((elem
= snd_mixer_find_selem(mixer
, sid
))) {
1062 if (elem_has_volume(elem
, playback
) &&
1063 elem_has_switch(elem
, playback
))
1066 if (!elem_has_volume(elem
, playback
) &&
1067 !elem_has_switch(elem
, playback
))
1071 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1074 snd_mixer_selem_id_set_name(sid
, fallback
);
1075 snd_mixer_selem_id_set_index(sid
, 0);
1077 if ((fallback_elem
= snd_mixer_find_selem(mixer
, sid
))) {
1079 if (elem_has_volume(fallback_elem
, playback
) &&
1080 elem_has_switch(fallback_elem
, playback
)) {
1081 elem
= fallback_elem
;
1085 if (!elem_has_volume(fallback_elem
, playback
) &&
1086 !elem_has_switch(fallback_elem
, playback
))
1087 fallback_elem
= NULL
;
1090 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
));
1093 if (elem
&& fallback_elem
) {
1095 /* Hmm, so we have both elements, but neither has both mute
1096 * and volume. Let's prefer the one with the volume */
1098 if (elem_has_volume(elem
, playback
))
1101 if (elem_has_volume(fallback_elem
, playback
)) {
1102 elem
= fallback_elem
;
1107 if (!elem
&& fallback_elem
)
1108 elem
= fallback_elem
;
1113 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid
));
1118 int pa_alsa_find_mixer_and_elem(
1121 snd_mixer_elem_t
**_e
,
1122 const char *control_name
,
1123 const pa_alsa_profile_info
*profile
) {
1127 snd_mixer_elem_t
*e
;
1128 pa_bool_t found
= FALSE
;
1135 if (control_name
&& *control_name
== 0) {
1136 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1140 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1141 pa_log("Error opening mixer: %s", pa_alsa_strerror(err
));
1145 /* First, try by name */
1146 if ((dev
= snd_pcm_name(pcm
)))
1147 if (pa_alsa_prepare_mixer(m
, dev
) >= 0)
1150 /* Then, try by card index */
1152 snd_pcm_info_t
* info
;
1153 snd_pcm_info_alloca(&info
);
1155 if (snd_pcm_info(pcm
, info
) >= 0) {
1159 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1161 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1163 if (!dev
|| !pa_streq(dev
, md
))
1164 if (pa_alsa_prepare_mixer(m
, md
) >= 0)
1177 switch (snd_pcm_stream(pcm
)) {
1179 case SND_PCM_STREAM_PLAYBACK
:
1181 e
= pa_alsa_find_elem(m
, control_name
, NULL
, TRUE
);
1183 e
= pa_alsa_find_elem(m
, profile
->playback_control_name
, profile
->playback_control_fallback
, TRUE
);
1185 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1188 case SND_PCM_STREAM_CAPTURE
:
1190 e
= pa_alsa_find_elem(m
, control_name
, NULL
, FALSE
);
1192 e
= pa_alsa_find_elem(m
, profile
->record_control_name
, profile
->record_control_fallback
, FALSE
);
1194 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1198 pa_assert_not_reached();
1214 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1215 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1217 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1218 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1219 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1221 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1222 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1223 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1225 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1227 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1228 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1230 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1231 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1233 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1234 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1235 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1236 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1237 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1238 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1239 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1240 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1241 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1242 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1243 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1244 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1245 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1246 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1247 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1248 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1249 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1250 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1251 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1252 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1253 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1254 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1255 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1256 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1257 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1258 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1259 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1260 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1261 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1262 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1263 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1264 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1266 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1268 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1269 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1270 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1272 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1273 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1274 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1278 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
) {
1280 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1281 pa_bool_t mono_used
= FALSE
;
1284 pa_assert(channel_map
);
1285 pa_assert(mixer_map
);
1287 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1289 if (channel_map
->channels
> 1 &&
1290 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1291 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1292 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1296 for (i
= 0; i
< channel_map
->channels
; i
++) {
1297 snd_mixer_selem_channel_id_t id
;
1300 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1301 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1303 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1304 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
]));
1308 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1309 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1313 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1314 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1316 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1321 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1325 alsa_channel_used
[id
] = TRUE
;
1329 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1334 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
1340 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1342 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1343 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1346 snd_output_buffer_string(out
, &s
);
1347 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
1350 pa_assert_se(snd_output_close(out
) == 0);
1353 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1356 snd_pcm_status_t
*status
;
1360 snd_pcm_status_alloca(&status
);
1362 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1364 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1366 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1367 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1370 snd_output_buffer_string(out
, &s
);
1371 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1374 pa_assert_se(snd_output_close(out
) == 0);
1377 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1381 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1385 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1389 pa_xfree(alsa_file
);
1392 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1394 void pa_alsa_redirect_errors_inc(void) {
1395 /* This is not really thread safe, but we do our best */
1397 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1398 snd_lib_error_set_handler(alsa_error_handler
);
1401 void pa_alsa_redirect_errors_dec(void) {
1404 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1407 snd_lib_error_set_handler(NULL
);
1410 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1414 if (pa_device_init_description(p
))
1417 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1418 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1422 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1423 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1430 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1431 char *cn
, *lcn
, *dn
;
1434 pa_assert(card
>= 0);
1436 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1438 if (snd_card_get_name(card
, &cn
) >= 0) {
1439 pa_proplist_sets(p
, "alsa.card_name", cn
);
1443 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1444 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1448 if ((dn
= pa_alsa_get_driver_name(card
))) {
1449 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1454 pa_udev_get_info(c
, p
, card
);
1458 pa_hal_get_info(c
, p
, card
);
1462 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1464 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1465 [SND_PCM_CLASS_GENERIC
] = "generic",
1466 [SND_PCM_CLASS_MULTI
] = "multi",
1467 [SND_PCM_CLASS_MODEM
] = "modem",
1468 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1470 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1471 [SND_PCM_CLASS_GENERIC
] = "sound",
1472 [SND_PCM_CLASS_MULTI
] = NULL
,
1473 [SND_PCM_CLASS_MODEM
] = "modem",
1474 [SND_PCM_CLASS_DIGITIZER
] = NULL
1476 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1477 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1478 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1481 snd_pcm_class_t
class;
1482 snd_pcm_subclass_t subclass
;
1483 const char *n
, *id
, *sdn
;
1487 pa_assert(pcm_info
);
1489 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1491 class = snd_pcm_info_get_class(pcm_info
);
1492 if (class <= SND_PCM_CLASS_LAST
) {
1493 if (class_table
[class])
1494 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1495 if (alsa_class_table
[class])
1496 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1499 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1500 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1501 if (alsa_subclass_table
[subclass
])
1502 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1504 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1505 pa_proplist_sets(p
, "alsa.name", n
);
1507 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1508 pa_proplist_sets(p
, "alsa.id", id
);
1510 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1511 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1512 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1514 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1516 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1517 pa_alsa_init_proplist_card(c
, p
, card
);
1520 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
, snd_mixer_elem_t
*elem
) {
1521 snd_pcm_hw_params_t
*hwparams
;
1522 snd_pcm_info_t
*info
;
1525 snd_pcm_hw_params_alloca(&hwparams
);
1526 snd_pcm_info_alloca(&info
);
1528 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1529 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
1532 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1533 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1537 pa_proplist_sets(p
, "alsa.mixer_element", snd_mixer_selem_get_name(elem
));
1539 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1540 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
1542 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1545 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1546 snd_pcm_state_t state
;
1551 if (revents
& POLLERR
)
1552 pa_log_debug("Got POLLERR from ALSA");
1553 if (revents
& POLLNVAL
)
1554 pa_log_warn("Got POLLNVAL from ALSA");
1555 if (revents
& POLLHUP
)
1556 pa_log_warn("Got POLLHUP from ALSA");
1557 if (revents
& POLLPRI
)
1558 pa_log_warn("Got POLLPRI from ALSA");
1559 if (revents
& POLLIN
)
1560 pa_log_debug("Got POLLIN from ALSA");
1561 if (revents
& POLLOUT
)
1562 pa_log_debug("Got POLLOUT from ALSA");
1564 state
= snd_pcm_state(pcm
);
1565 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1567 /* Try to recover from this error */
1571 case SND_PCM_STATE_XRUN
:
1572 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1573 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1578 case SND_PCM_STATE_SUSPENDED
:
1579 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1580 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1589 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1590 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1599 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1601 struct pollfd
*pollfd
;
1602 pa_rtpoll_item
*item
;
1606 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1607 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1611 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1612 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1614 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1615 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1616 pa_rtpoll_item_free(item
);
1623 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1624 snd_pcm_sframes_t n
;
1628 pa_assert(hwbuf_size
> 0);
1631 /* Some ALSA driver expose weird bugs, let's inform the user about
1632 * what is going on */
1634 n
= snd_pcm_avail(pcm
);
1639 k
= (size_t) n
* pa_frame_size(ss
);
1641 if (k
>= hwbuf_size
* 5 ||
1642 k
>= pa_bytes_per_second(ss
)*10) {
1645 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1646 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1647 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1649 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1652 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1655 /* Mhmm, let's try not to fail completely */
1656 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1662 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1669 pa_assert(hwbuf_size
> 0);
1672 /* Some ALSA driver expose weird bugs, let's inform the user about
1673 * what is going on */
1675 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1678 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1680 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1682 if (abs_k
>= hwbuf_size
* 5 ||
1683 abs_k
>= pa_bytes_per_second(ss
)*10) {
1686 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1687 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1688 "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(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1694 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1697 /* Mhmm, let's try not to fail completely */
1699 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1701 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1707 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
) {
1709 snd_pcm_uframes_t before
;
1716 pa_assert(hwbuf_size
> 0);
1721 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1726 k
= (size_t) *frames
* pa_frame_size(ss
);
1728 if (*frames
> before
||
1729 k
>= hwbuf_size
* 3 ||
1730 k
>= pa_bytes_per_second(ss
)*10)
1733 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1734 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1735 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1737 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1740 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1746 char *pa_alsa_get_driver_name(int card
) {
1749 pa_assert(card
>= 0);
1751 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1758 n
= pa_xstrdup(pa_path_get_filename(m
));
1764 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1766 snd_pcm_info_t
* info
;
1767 snd_pcm_info_alloca(&info
);
1771 if (snd_pcm_info(pcm
, info
) < 0)
1774 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1777 return pa_alsa_get_driver_name(card
);
1780 char *pa_alsa_get_reserve_name(const char *device
) {
1786 if ((t
= strchr(device
, ':')))
1789 if ((i
= snd_card_get_index(device
)) < 0) {
1792 if (pa_atoi(device
, &k
) < 0)
1798 return pa_sprintf_malloc("Audio%i", i
);
1801 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1802 snd_pcm_info_t
* info
;
1803 snd_pcm_info_alloca(&info
);
1807 if (snd_pcm_info(pcm
, info
) < 0)
1810 return snd_pcm_info_get_card(info
) >= 0;
1813 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1814 snd_pcm_info_t
* info
;
1815 snd_pcm_info_alloca(&info
);
1819 if (snd_pcm_info(pcm
, info
) < 0)
1822 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1825 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1827 const char* pa_alsa_strerror(int errnum
) {
1828 const char *original
= NULL
;
1829 char *translated
, *t
;
1832 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1837 original
= snd_strerror(errnum
);
1840 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1844 if (!(translated
= pa_locale_to_utf8(original
))) {
1845 pa_log_warn("Unable to convert error string to locale, filtering.");
1846 translated
= pa_utf8_filter(original
);
1849 PA_STATIC_TLS_SET(cstrerror
, translated
);