2 This file is part of PulseAudio.
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/types.h>
29 #include <asoundlib.h>
31 #include <pulse/sample.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/i18n.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/atomic.h>
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/once.h>
44 #include "alsa-util.h"
51 #include "udev-util.h"
54 struct pa_alsa_fdlist
{
57 /* This is a temporary buffer used to avoid lots of mallocs */
58 struct pollfd
*work_fds
;
63 pa_defer_event
*defer
;
68 void (*cb
)(void *userdata
);
72 static void io_cb(pa_mainloop_api
*a
, pa_io_event
* e
, int fd
, pa_io_event_flags_t events
, void *userdata
) {
74 struct pa_alsa_fdlist
*fdl
= userdata
;
77 unsigned short revents
;
81 pa_assert(fdl
->mixer
);
83 pa_assert(fdl
->work_fds
);
90 memcpy(fdl
->work_fds
, fdl
->fds
, sizeof(struct pollfd
) * fdl
->num_fds
);
92 for (i
= 0; i
< fdl
->num_fds
; i
++) {
93 if (e
== fdl
->ios
[i
]) {
94 if (events
& PA_IO_EVENT_INPUT
)
95 fdl
->work_fds
[i
].revents
|= POLLIN
;
96 if (events
& PA_IO_EVENT_OUTPUT
)
97 fdl
->work_fds
[i
].revents
|= POLLOUT
;
98 if (events
& PA_IO_EVENT_ERROR
)
99 fdl
->work_fds
[i
].revents
|= POLLERR
;
100 if (events
& PA_IO_EVENT_HANGUP
)
101 fdl
->work_fds
[i
].revents
|= POLLHUP
;
106 pa_assert(i
!= fdl
->num_fds
);
108 if ((err
= snd_mixer_poll_descriptors_revents(fdl
->mixer
, fdl
->work_fds
, fdl
->num_fds
, &revents
)) < 0) {
109 pa_log_error("Unable to get poll revent: %s", snd_strerror(err
));
113 a
->defer_enable(fdl
->defer
, 1);
116 snd_mixer_handle_events(fdl
->mixer
);
119 static void defer_cb(pa_mainloop_api
*a
, pa_defer_event
* e
, void *userdata
) {
120 struct pa_alsa_fdlist
*fdl
= userdata
;
127 pa_assert(fdl
->mixer
);
129 a
->defer_enable(fdl
->defer
, 0);
131 if ((n
= snd_mixer_poll_descriptors_count(fdl
->mixer
)) < 0) {
132 pa_log("snd_mixer_poll_descriptors_count() failed: %s", snd_strerror(n
));
135 num_fds
= (unsigned) n
;
137 if (num_fds
!= fdl
->num_fds
) {
141 pa_xfree(fdl
->work_fds
);
142 fdl
->fds
= pa_xnew0(struct pollfd
, num_fds
);
143 fdl
->work_fds
= pa_xnew(struct pollfd
, num_fds
);
146 memset(fdl
->work_fds
, 0, sizeof(struct pollfd
) * num_fds
);
148 if ((err
= snd_mixer_poll_descriptors(fdl
->mixer
, fdl
->work_fds
, num_fds
)) < 0) {
149 pa_log_error("Unable to get poll descriptors: %s", snd_strerror(err
));
155 if (memcmp(fdl
->fds
, fdl
->work_fds
, sizeof(struct pollfd
) * num_fds
) == 0)
159 for (i
= 0; i
< fdl
->num_fds
; i
++)
160 a
->io_free(fdl
->ios
[i
]);
162 if (num_fds
!= fdl
->num_fds
) {
169 fdl
->ios
= pa_xnew(pa_io_event
*, num_fds
);
172 temp
= fdl
->work_fds
;
173 fdl
->work_fds
= fdl
->fds
;
176 fdl
->num_fds
= num_fds
;
178 for (i
= 0;i
< num_fds
;i
++)
179 fdl
->ios
[i
] = a
->io_new(a
, fdl
->fds
[i
].fd
,
180 ((fdl
->fds
[i
].events
& POLLIN
) ? PA_IO_EVENT_INPUT
: 0) |
181 ((fdl
->fds
[i
].events
& POLLOUT
) ? PA_IO_EVENT_OUTPUT
: 0),
185 struct pa_alsa_fdlist
*pa_alsa_fdlist_new(void) {
186 struct pa_alsa_fdlist
*fdl
;
188 fdl
= pa_xnew0(struct pa_alsa_fdlist
, 1);
192 fdl
->work_fds
= NULL
;
202 void pa_alsa_fdlist_free(struct pa_alsa_fdlist
*fdl
) {
207 fdl
->m
->defer_free(fdl
->defer
);
213 for (i
= 0; i
< fdl
->num_fds
; i
++)
214 fdl
->m
->io_free(fdl
->ios
[i
]);
221 pa_xfree(fdl
->work_fds
);
226 int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist
*fdl
, snd_mixer_t
*mixer_handle
, pa_mainloop_api
* m
) {
228 pa_assert(mixer_handle
);
232 fdl
->mixer
= mixer_handle
;
234 fdl
->defer
= m
->defer_new(m
, defer_cb
, fdl
);
239 static int set_format(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, pa_sample_format_t
*f
) {
241 static const snd_pcm_format_t format_trans
[] = {
242 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
243 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
244 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
245 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
246 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
247 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
248 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
249 [PA_SAMPLE_S32LE
] = SND_PCM_FORMAT_S32_LE
,
250 [PA_SAMPLE_S32BE
] = SND_PCM_FORMAT_S32_BE
,
251 [PA_SAMPLE_S24LE
] = SND_PCM_FORMAT_S24_3LE
,
252 [PA_SAMPLE_S24BE
] = SND_PCM_FORMAT_S24_3BE
,
253 [PA_SAMPLE_S24_32LE
] = SND_PCM_FORMAT_S24_LE
,
254 [PA_SAMPLE_S24_32BE
] = SND_PCM_FORMAT_S24_BE
,
257 static const pa_sample_format_t try_order
[] = {
276 pa_assert(pcm_handle
);
279 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
282 if (*f
== PA_SAMPLE_FLOAT32BE
)
283 *f
= PA_SAMPLE_FLOAT32LE
;
284 else if (*f
== PA_SAMPLE_FLOAT32LE
)
285 *f
= PA_SAMPLE_FLOAT32BE
;
286 else if (*f
== PA_SAMPLE_S24BE
)
287 *f
= PA_SAMPLE_S24LE
;
288 else if (*f
== PA_SAMPLE_S24LE
)
289 *f
= PA_SAMPLE_S24BE
;
290 else if (*f
== PA_SAMPLE_S24_32BE
)
291 *f
= PA_SAMPLE_S24_32LE
;
292 else if (*f
== PA_SAMPLE_S24_32LE
)
293 *f
= PA_SAMPLE_S24_32BE
;
294 else if (*f
== PA_SAMPLE_S16BE
)
295 *f
= PA_SAMPLE_S16LE
;
296 else if (*f
== PA_SAMPLE_S16LE
)
297 *f
= PA_SAMPLE_S16BE
;
298 else if (*f
== PA_SAMPLE_S32BE
)
299 *f
= PA_SAMPLE_S32LE
;
300 else if (*f
== PA_SAMPLE_S32LE
)
301 *f
= PA_SAMPLE_S32BE
;
305 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
310 for (i
= 0; try_order
[i
] != PA_SAMPLE_INVALID
; i
++) {
313 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
320 /* Set the hardware parameters of the given ALSA device. Returns the
321 * selected fragment settings in *period and *period_size */
322 int pa_alsa_set_hw_params(
323 snd_pcm_t
*pcm_handle
,
326 snd_pcm_uframes_t
*period_size
,
327 snd_pcm_uframes_t tsched_size
,
329 pa_bool_t
*use_tsched
,
330 pa_bool_t require_exact_channel_number
) {
333 snd_pcm_uframes_t _period_size
= period_size
? *period_size
: 0;
334 unsigned int _periods
= periods
? *periods
: 0;
335 snd_pcm_uframes_t buffer_size
;
336 unsigned int r
= ss
->rate
;
337 unsigned int c
= ss
->channels
;
338 pa_sample_format_t f
= ss
->format
;
339 snd_pcm_hw_params_t
*hwparams
;
340 pa_bool_t _use_mmap
= use_mmap
&& *use_mmap
;
341 pa_bool_t _use_tsched
= use_tsched
&& *use_tsched
;
344 pa_assert(pcm_handle
);
347 snd_pcm_hw_params_alloca(&hwparams
);
349 if ((ret
= snd_pcm_hw_params_any(pcm_handle
, hwparams
)) < 0)
352 if ((ret
= snd_pcm_hw_params_set_rate_resample(pcm_handle
, hwparams
, 0)) < 0)
357 if (snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) < 0) {
359 /* mmap() didn't work, fall back to interleaved */
361 if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
367 } else if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0)
373 if ((ret
= set_format(pcm_handle
, hwparams
, &f
)) < 0)
376 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &r
, NULL
)) < 0)
379 if (require_exact_channel_number
) {
380 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, c
)) < 0)
383 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0)
387 if ((ret
= snd_pcm_hw_params_set_periods_integer(pcm_handle
, hwparams
)) < 0)
390 if (_period_size
&& tsched_size
&& _periods
) {
391 /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
392 _period_size
= (snd_pcm_uframes_t
) (((uint64_t) _period_size
* r
) / ss
->rate
);
393 tsched_size
= (snd_pcm_uframes_t
) (((uint64_t) tsched_size
* r
) / ss
->rate
);
396 _period_size
= tsched_size
;
399 pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams
, &buffer_size
) == 0);
400 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size
* 1000 / r
);
403 buffer_size
= _periods
* _period_size
;
407 /* First we pass 0 as direction to get exactly what we asked
408 * for. That this is necessary is presumably a bug in ALSA */
411 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0) {
413 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0) {
415 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0)
421 if (_period_size
> 0)
422 if ((ret
= snd_pcm_hw_params_set_buffer_size_near(pcm_handle
, hwparams
, &buffer_size
)) < 0)
426 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0)
430 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, r
);
432 if (ss
->channels
!= c
)
433 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, c
);
436 pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle
), pa_sample_format_to_string(ss
->format
), pa_sample_format_to_string(f
));
438 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0)
441 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
442 (ret
= snd_pcm_hw_params_get_periods(hwparams
, &_periods
, &dir
)) < 0)
445 /* If the sample rate deviates too much, we need to resample */
446 if (r
< ss
->rate
*.95 || r
> ss
->rate
*1.05)
448 ss
->channels
= (uint8_t) c
;
451 pa_assert(_periods
> 0);
452 pa_assert(_period_size
> 0);
458 *period_size
= _period_size
;
461 *use_mmap
= _use_mmap
;
464 *use_tsched
= _use_tsched
;
468 snd_pcm_nonblock(pcm_handle
, 1);
475 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
) {
476 snd_pcm_sw_params_t
*swparams
;
477 snd_pcm_uframes_t boundary
;
482 snd_pcm_sw_params_alloca(&swparams
);
484 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
485 pa_log_warn("Unable to determine current swparams: %s\n", snd_strerror(err
));
489 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 0)) < 0) {
490 pa_log_warn("Unable to disable period event: %s\n", snd_strerror(err
));
494 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
495 pa_log_warn("Unable to enable time stamping: %s\n", snd_strerror(err
));
499 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
500 pa_log_warn("Unable to get boundary: %s\n", snd_strerror(err
));
504 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
505 pa_log_warn("Unable to set stop threshold: %s\n", snd_strerror(err
));
509 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
510 pa_log_warn("Unable to set start threshold: %s\n", snd_strerror(err
));
514 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
515 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err
));
519 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
520 pa_log_warn("Unable to set sw params: %s\n", snd_strerror(err
));
527 static const struct pa_alsa_profile_info device_table
[] = {
528 {{ 1, { PA_CHANNEL_POSITION_MONO
}},
536 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
544 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
546 N_("Digital Stereo (IEC958)"),
552 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
554 N_("Digital Stereo (HDMI)"),
560 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
561 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
563 N_("Analog Surround 4.0"),
564 "analog-surround-40",
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_("Digital Surround 4.0 (IEC958/AC3)"),
573 "iec958-ac3-surround-40",
578 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
579 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
580 PA_CHANNEL_POSITION_LFE
}},
582 N_("Analog Surround 4.1"),
583 "analog-surround-41",
588 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
589 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
590 PA_CHANNEL_POSITION_CENTER
}},
592 N_("Analog Surround 5.0"),
593 "analog-surround-50",
598 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
599 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
600 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
}},
602 N_("Analog Surround 5.1"),
603 "analog-surround-51",
608 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
609 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
610 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
}},
612 N_("Digital Surround 5.1 (IEC958/AC3)"),
613 "iec958-ac3-surround-51",
618 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
619 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
620 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
,
621 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
}},
623 N_("Analog Surround 7.1"),
624 "analog-surround-71",
629 {{ 0, { 0 }}, NULL
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
}
632 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
639 snd_pcm_uframes_t
*period_size
,
640 snd_pcm_uframes_t tsched_size
,
642 pa_bool_t
*use_tsched
,
643 const pa_alsa_profile_info
**profile
) {
648 snd_pcm_t
*pcm_handle
;
655 pa_assert(period_size
);
657 /* First we try to find a device string with a superset of the
658 * requested channel map and open it without the plug: prefix. We
659 * iterate through our device table from top to bottom and take
660 * the first that matches. If we didn't find a working device that
661 * way, we iterate backwards, and check all devices that do not
662 * provide a superset of the requested channel map.*/
667 if ((direction
> 0) == pa_channel_map_superset(&device_table
[i
].map
, map
)) {
668 pa_sample_spec try_ss
;
670 pa_log_debug("Checking for %s (%s)", device_table
[i
].name
, device_table
[i
].alsa_name
);
672 d
= pa_sprintf_malloc("%s:%s", device_table
[i
].alsa_name
, dev_id
);
674 try_ss
.channels
= device_table
[i
].map
.channels
;
675 try_ss
.rate
= ss
->rate
;
676 try_ss
.format
= ss
->format
;
678 pcm_handle
= pa_alsa_open_by_device_string(
696 *map
= device_table
[i
].map
;
697 pa_assert(map
->channels
== ss
->channels
);
700 *profile
= &device_table
[i
];
707 if (!device_table
[i
+1].alsa_name
) {
708 /* OK, so we are at the end of our list. Let's turn
712 /* We are not at the end of the list, so let's simply
713 * try the next entry */
720 if (device_table
[i
+1].alsa_name
&&
721 device_table
[i
].map
.channels
== device_table
[i
+1].map
.channels
) {
723 /* OK, the next entry has the same number of channels,
728 /* Hmm, so the next entry does not have the same
729 * number of channels, so let's go backwards until we
730 * find the next entry with a different number of
733 for (i
--; i
>= 0; i
--)
734 if (device_table
[i
].map
.channels
!= device_table
[i
+1].map
.channels
)
737 /* Hmm, there is no entry with a different number of
738 * entries, then we're done */
742 /* OK, now lets find go back as long as we have the same number of channels */
744 if (device_table
[i
].map
.channels
!= device_table
[i
-1].map
.channels
)
750 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
752 d
= pa_sprintf_malloc("hw:%s", dev_id
);
753 pa_log_debug("Trying %s as last resort...", d
);
754 pcm_handle
= pa_alsa_open_by_device_string(d
, dev
, ss
, map
, mode
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, FALSE
);
757 if (pcm_handle
&& profile
)
763 snd_pcm_t
*pa_alsa_open_by_device_id_profile(
770 snd_pcm_uframes_t
*period_size
,
771 snd_pcm_uframes_t tsched_size
,
773 pa_bool_t
*use_tsched
,
774 const pa_alsa_profile_info
*profile
) {
777 snd_pcm_t
*pcm_handle
;
778 pa_sample_spec try_ss
;
785 pa_assert(period_size
);
788 d
= pa_sprintf_malloc("%s:%s", profile
->alsa_name
, dev_id
);
790 try_ss
.channels
= profile
->map
.channels
;
791 try_ss
.rate
= ss
->rate
;
792 try_ss
.format
= ss
->format
;
794 pcm_handle
= pa_alsa_open_by_device_string(
814 pa_assert(map
->channels
== ss
->channels
);
819 snd_pcm_t
*pa_alsa_open_by_device_string(
826 snd_pcm_uframes_t
*period_size
,
827 snd_pcm_uframes_t tsched_size
,
829 pa_bool_t
*use_tsched
,
830 pa_bool_t require_exact_channel_number
) {
834 snd_pcm_t
*pcm_handle
;
835 pa_bool_t reformat
= FALSE
;
841 d
= pa_xstrdup(device
);
844 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
846 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
847 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
848 * we enable nonblock mode afterwards via
849 * snd_pcm_nonblock(). Also see
850 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
852 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
853 /*SND_PCM_NONBLOCK|*/
854 SND_PCM_NO_AUTO_RESAMPLE
|
855 SND_PCM_NO_AUTO_CHANNELS
|
856 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
857 pa_log_info("Error opening PCM device %s: %s", d
, snd_strerror(err
));
861 if ((err
= pa_alsa_set_hw_params(pcm_handle
, ss
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, require_exact_channel_number
)) < 0) {
866 snd_pcm_close(pcm_handle
);
870 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
872 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
875 t
= pa_sprintf_malloc("plug:%s", d
);
881 snd_pcm_close(pcm_handle
);
885 pa_log_info("Failed to set hardware parameters on %s: %s", d
, snd_strerror(err
));
886 snd_pcm_close(pcm_handle
);
896 if (ss
->channels
!= map
->channels
)
897 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
908 int pa_alsa_probe_profiles(
910 const pa_sample_spec
*ss
,
911 void (*cb
)(const pa_alsa_profile_info
*sink
, const pa_alsa_profile_info
*source
, void *userdata
),
914 const pa_alsa_profile_info
*i
;
920 /* We try each combination of playback/capture. We also try to
921 * open only for capture resp. only for sink. Don't get confused
922 * by the trailing entry in device_table we use for this! */
924 for (i
= device_table
; i
< device_table
+ PA_ELEMENTSOF(device_table
); i
++) {
925 const pa_alsa_profile_info
*j
;
926 snd_pcm_t
*pcm_i
= NULL
;
930 pa_sample_spec try_ss
;
931 pa_channel_map try_map
;
933 pa_log_debug("Checking for playback on %s (%s)", i
->name
, i
->alsa_name
);
934 id
= pa_sprintf_malloc("%s:%s", i
->alsa_name
, dev_id
);
937 try_ss
.channels
= i
->map
.channels
;
940 pcm_i
= pa_alsa_open_by_device_string(
943 SND_PCM_STREAM_PLAYBACK
,
944 NULL
, NULL
, 0, NULL
, NULL
,
953 for (j
= device_table
; j
< device_table
+ PA_ELEMENTSOF(device_table
); j
++) {
954 snd_pcm_t
*pcm_j
= NULL
;
958 pa_sample_spec try_ss
;
959 pa_channel_map try_map
;
961 pa_log_debug("Checking for capture on %s (%s)", j
->name
, j
->alsa_name
);
962 jd
= pa_sprintf_malloc("%s:%s", j
->alsa_name
, dev_id
);
965 try_ss
.channels
= j
->map
.channels
;
968 pcm_j
= pa_alsa_open_by_device_string(
971 SND_PCM_STREAM_CAPTURE
,
972 NULL
, NULL
, 0, NULL
, NULL
,
982 snd_pcm_close(pcm_j
);
984 if (i
->alsa_name
|| j
->alsa_name
)
985 cb(i
->alsa_name
? i
: NULL
,
986 j
->alsa_name
? j
: NULL
, userdata
);
990 snd_pcm_close(pcm_i
);
996 int pa_alsa_prepare_mixer(snd_mixer_t
*mixer
, const char *dev
) {
1002 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
1003 pa_log_info("Unable to attach to mixer %s: %s", dev
, snd_strerror(err
));
1007 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
1008 pa_log_warn("Unable to register mixer: %s", snd_strerror(err
));
1012 if ((err
= snd_mixer_load(mixer
)) < 0) {
1013 pa_log_warn("Unable to load mixer: %s", snd_strerror(err
));
1017 pa_log_info("Successfully attached to mixer '%s'", dev
);
1022 static pa_bool_t
elem_has_volume(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1025 if (playback
&& snd_mixer_selem_has_playback_volume(elem
))
1028 if (!playback
&& snd_mixer_selem_has_capture_volume(elem
))
1034 static pa_bool_t
elem_has_switch(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1037 if (playback
&& snd_mixer_selem_has_playback_switch(elem
))
1040 if (!playback
&& snd_mixer_selem_has_capture_switch(elem
))
1046 snd_mixer_elem_t
*pa_alsa_find_elem(snd_mixer_t
*mixer
, const char *name
, const char *fallback
, pa_bool_t playback
) {
1047 snd_mixer_elem_t
*elem
= NULL
, *fallback_elem
= NULL
;
1048 snd_mixer_selem_id_t
*sid
= NULL
;
1050 snd_mixer_selem_id_alloca(&sid
);
1055 snd_mixer_selem_id_set_name(sid
, name
);
1056 snd_mixer_selem_id_set_index(sid
, 0);
1058 if ((elem
= snd_mixer_find_selem(mixer
, sid
))) {
1060 if (elem_has_volume(elem
, playback
) &&
1061 elem_has_switch(elem
, playback
))
1064 if (!elem_has_volume(elem
, playback
) &&
1065 !elem_has_switch(elem
, playback
))
1069 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1072 snd_mixer_selem_id_set_name(sid
, fallback
);
1073 snd_mixer_selem_id_set_index(sid
, 0);
1075 if ((fallback_elem
= snd_mixer_find_selem(mixer
, sid
))) {
1077 if (elem_has_volume(fallback_elem
, playback
) &&
1078 elem_has_switch(fallback_elem
, playback
)) {
1079 elem
= fallback_elem
;
1083 if (!elem_has_volume(fallback_elem
, playback
) &&
1084 !elem_has_switch(fallback_elem
, playback
))
1085 fallback_elem
= NULL
;
1088 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
));
1091 if (elem
&& fallback_elem
) {
1093 /* Hmm, so we have both elements, but neither has both mute
1094 * and volume. Let's prefer the one with the volume */
1096 if (elem_has_volume(elem
, playback
))
1099 if (elem_has_volume(fallback_elem
, playback
)) {
1100 elem
= fallback_elem
;
1105 if (!elem
&& fallback_elem
)
1106 elem
= fallback_elem
;
1111 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid
));
1116 int pa_alsa_find_mixer_and_elem(
1119 snd_mixer_elem_t
**_e
,
1120 const char *control_name
,
1121 const pa_alsa_profile_info
*profile
) {
1125 snd_mixer_elem_t
*e
;
1126 pa_bool_t found
= FALSE
;
1133 if (control_name
&& *control_name
== 0) {
1134 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1138 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1139 pa_log("Error opening mixer: %s", snd_strerror(err
));
1143 /* First, try by name */
1144 if ((dev
= snd_pcm_name(pcm
)))
1145 if (pa_alsa_prepare_mixer(m
, dev
) >= 0)
1148 /* Then, try by card index */
1150 snd_pcm_info_t
* info
;
1151 snd_pcm_info_alloca(&info
);
1153 if (snd_pcm_info(pcm
, info
) >= 0) {
1157 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1159 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1161 if (!dev
|| !pa_streq(dev
, md
))
1162 if (pa_alsa_prepare_mixer(m
, md
) >= 0)
1175 switch (snd_pcm_stream(pcm
)) {
1177 case SND_PCM_STREAM_PLAYBACK
:
1179 e
= pa_alsa_find_elem(m
, control_name
, NULL
, TRUE
);
1181 e
= pa_alsa_find_elem(m
, profile
->playback_control_name
, profile
->playback_control_fallback
, TRUE
);
1183 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1186 case SND_PCM_STREAM_CAPTURE
:
1188 e
= pa_alsa_find_elem(m
, control_name
, NULL
, FALSE
);
1190 e
= pa_alsa_find_elem(m
, profile
->record_control_name
, profile
->record_control_fallback
, FALSE
);
1192 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1196 pa_assert_not_reached();
1212 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1213 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1215 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1216 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1217 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1219 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1220 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1221 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1223 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1225 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1226 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1228 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1229 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1231 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1232 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1233 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1234 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1235 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1236 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1237 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1238 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1239 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1240 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1241 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1242 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1243 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1244 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1245 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1246 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1247 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1248 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1249 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1250 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1251 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1252 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1253 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1254 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1255 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1256 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1257 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1258 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1259 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1260 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1261 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1262 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1264 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1266 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1267 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1268 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1270 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1271 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1272 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1276 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
) {
1278 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1279 pa_bool_t mono_used
= FALSE
;
1282 pa_assert(channel_map
);
1283 pa_assert(mixer_map
);
1285 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1287 if (channel_map
->channels
> 1 &&
1288 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1289 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1290 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1294 for (i
= 0; i
< channel_map
->channels
; i
++) {
1295 snd_mixer_selem_channel_id_t id
;
1298 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1299 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1301 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1302 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
]));
1306 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1307 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1311 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1312 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1314 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1319 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1323 alsa_channel_used
[id
] = TRUE
;
1327 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1332 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
1338 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1340 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1341 pa_logl(level
, "snd_pcm_dump(): %s", snd_strerror(err
));
1344 snd_output_buffer_string(out
, &s
);
1345 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
1348 pa_assert_se(snd_output_close(out
) == 0);
1351 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1354 snd_pcm_status_t
*status
;
1358 snd_pcm_status_alloca(&status
);
1360 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1362 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1364 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1365 pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err
));
1368 snd_output_buffer_string(out
, &s
);
1369 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1372 pa_assert_se(snd_output_close(out
) == 0);
1375 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1379 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1383 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1387 pa_xfree(alsa_file
);
1390 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1392 void pa_alsa_redirect_errors_inc(void) {
1393 /* This is not really thread safe, but we do our best */
1395 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1396 snd_lib_error_set_handler(alsa_error_handler
);
1399 void pa_alsa_redirect_errors_dec(void) {
1402 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1405 snd_lib_error_set_handler(NULL
);
1408 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1412 if (pa_device_init_description(p
))
1415 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1416 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1420 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1421 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1428 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1429 char *cn
, *lcn
, *dn
;
1432 pa_assert(card
>= 0);
1434 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1436 if (snd_card_get_name(card
, &cn
) >= 0) {
1437 pa_proplist_sets(p
, "alsa.card_name", cn
);
1441 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1442 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1446 if ((dn
= pa_alsa_get_driver_name(card
))) {
1447 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1452 pa_udev_get_info(c
, p
, card
);
1456 pa_hal_get_info(c
, p
, card
);
1460 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1462 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1463 [SND_PCM_CLASS_GENERIC
] = "generic",
1464 [SND_PCM_CLASS_MULTI
] = "multi",
1465 [SND_PCM_CLASS_MODEM
] = "modem",
1466 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1468 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1469 [SND_PCM_CLASS_GENERIC
] = "sound",
1470 [SND_PCM_CLASS_MULTI
] = NULL
,
1471 [SND_PCM_CLASS_MODEM
] = "modem",
1472 [SND_PCM_CLASS_DIGITIZER
] = NULL
1474 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1475 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1476 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1479 snd_pcm_class_t
class;
1480 snd_pcm_subclass_t subclass
;
1481 const char *n
, *id
, *sdn
;
1485 pa_assert(pcm_info
);
1487 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1489 class = snd_pcm_info_get_class(pcm_info
);
1490 if (class <= SND_PCM_CLASS_LAST
) {
1491 if (class_table
[class])
1492 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1493 if (alsa_class_table
[class])
1494 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1497 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1498 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1499 if (alsa_subclass_table
[subclass
])
1500 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1502 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1503 pa_proplist_sets(p
, "alsa.name", n
);
1505 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1506 pa_proplist_sets(p
, "alsa.id", id
);
1508 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1509 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1510 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1512 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1514 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1515 pa_alsa_init_proplist_card(c
, p
, card
);
1518 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
, snd_mixer_elem_t
*elem
) {
1519 snd_pcm_hw_params_t
*hwparams
;
1520 snd_pcm_info_t
*info
;
1523 snd_pcm_hw_params_alloca(&hwparams
);
1524 snd_pcm_info_alloca(&info
);
1526 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1527 pa_log_warn("Error fetching hardware parameter info: %s", snd_strerror(err
));
1530 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1531 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1535 pa_proplist_sets(p
, "alsa.mixer_element", snd_mixer_selem_get_name(elem
));
1537 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1538 pa_log_warn("Error fetching PCM info: %s", snd_strerror(err
));
1540 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1543 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1544 snd_pcm_state_t state
;
1549 if (revents
& POLLERR
)
1550 pa_log_debug("Got POLLERR from ALSA");
1551 if (revents
& POLLNVAL
)
1552 pa_log_warn("Got POLLNVAL from ALSA");
1553 if (revents
& POLLHUP
)
1554 pa_log_warn("Got POLLHUP from ALSA");
1555 if (revents
& POLLPRI
)
1556 pa_log_warn("Got POLLPRI from ALSA");
1557 if (revents
& POLLIN
)
1558 pa_log_debug("Got POLLIN from ALSA");
1559 if (revents
& POLLOUT
)
1560 pa_log_debug("Got POLLOUT from ALSA");
1562 state
= snd_pcm_state(pcm
);
1563 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1565 /* Try to recover from this error */
1569 case SND_PCM_STATE_XRUN
:
1570 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1571 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err
));
1576 case SND_PCM_STATE_SUSPENDED
:
1577 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1578 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err
));
1587 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1588 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err
));
1597 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1599 struct pollfd
*pollfd
;
1600 pa_rtpoll_item
*item
;
1604 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1605 pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n
));
1609 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1610 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1612 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1613 pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err
));
1614 pa_rtpoll_item_free(item
);
1621 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1622 snd_pcm_sframes_t n
;
1626 pa_assert(hwbuf_size
> 0);
1629 /* Some ALSA driver expose weird bugs, let's inform the user about
1630 * what is going on */
1632 n
= snd_pcm_avail(pcm
);
1637 k
= (size_t) n
* pa_frame_size(ss
);
1639 if (k
>= hwbuf_size
* 5 ||
1640 k
>= pa_bytes_per_second(ss
)*10) {
1643 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1644 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1645 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1647 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1650 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1653 /* Mhmm, let's try not to fail completely */
1654 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1660 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1667 pa_assert(hwbuf_size
> 0);
1670 /* Some ALSA driver expose weird bugs, let's inform the user about
1671 * what is going on */
1673 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1676 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1678 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1680 if (abs_k
>= hwbuf_size
* 5 ||
1681 abs_k
>= pa_bytes_per_second(ss
)*10) {
1684 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1685 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1686 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1689 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1692 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1695 /* Mhmm, let's try not to fail completely */
1697 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1699 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1705 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
) {
1707 snd_pcm_uframes_t before
;
1714 pa_assert(hwbuf_size
> 0);
1719 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1724 k
= (size_t) *frames
* pa_frame_size(ss
);
1726 if (*frames
> before
||
1727 k
>= hwbuf_size
* 3 ||
1728 k
>= pa_bytes_per_second(ss
)*10)
1731 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1732 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1733 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1735 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1738 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1744 char *pa_alsa_get_driver_name(int card
) {
1747 pa_assert(card
>= 0);
1749 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1756 n
= pa_xstrdup(pa_path_get_filename(m
));
1762 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1764 snd_pcm_info_t
* info
;
1765 snd_pcm_info_alloca(&info
);
1769 if (snd_pcm_info(pcm
, info
) < 0)
1772 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1775 return pa_alsa_get_driver_name(card
);
1778 char *pa_alsa_get_reserve_name(const char *device
) {
1784 if ((t
= strchr(device
, ':')))
1787 if ((i
= snd_card_get_index(device
)) < 0) {
1790 if (pa_atoi(device
, &k
) < 0)
1796 return pa_sprintf_malloc("Audio%i", i
);
1799 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1800 snd_pcm_info_t
* info
;
1801 snd_pcm_info_alloca(&info
);
1805 if (snd_pcm_info(pcm
, info
) < 0)
1808 return snd_pcm_info_get_card(info
) >= 0;
1811 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1812 snd_pcm_info_t
* info
;
1813 snd_pcm_info_alloca(&info
);
1817 if (snd_pcm_info(pcm
, info
) < 0)
1820 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;