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);
195 void pa_alsa_fdlist_free(struct pa_alsa_fdlist
*fdl
) {
200 fdl
->m
->defer_free(fdl
->defer
);
206 for (i
= 0; i
< fdl
->num_fds
; i
++)
207 fdl
->m
->io_free(fdl
->ios
[i
]);
214 pa_xfree(fdl
->work_fds
);
219 int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist
*fdl
, snd_mixer_t
*mixer_handle
, pa_mainloop_api
* m
) {
221 pa_assert(mixer_handle
);
225 fdl
->mixer
= mixer_handle
;
227 fdl
->defer
= m
->defer_new(m
, defer_cb
, fdl
);
232 static int set_format(snd_pcm_t
*pcm_handle
, snd_pcm_hw_params_t
*hwparams
, pa_sample_format_t
*f
) {
234 static const snd_pcm_format_t format_trans
[] = {
235 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
236 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
237 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
238 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
239 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
240 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
241 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
242 [PA_SAMPLE_S32LE
] = SND_PCM_FORMAT_S32_LE
,
243 [PA_SAMPLE_S32BE
] = SND_PCM_FORMAT_S32_BE
,
244 [PA_SAMPLE_S24LE
] = SND_PCM_FORMAT_S24_3LE
,
245 [PA_SAMPLE_S24BE
] = SND_PCM_FORMAT_S24_3BE
,
246 [PA_SAMPLE_S24_32LE
] = SND_PCM_FORMAT_S24_LE
,
247 [PA_SAMPLE_S24_32BE
] = SND_PCM_FORMAT_S24_BE
,
250 static const pa_sample_format_t try_order
[] = {
269 pa_assert(pcm_handle
);
272 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
275 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
276 snd_pcm_format_description(format_trans
[*f
]),
277 pa_alsa_strerror(ret
));
280 if (*f
== PA_SAMPLE_FLOAT32BE
)
281 *f
= PA_SAMPLE_FLOAT32LE
;
282 else if (*f
== PA_SAMPLE_FLOAT32LE
)
283 *f
= PA_SAMPLE_FLOAT32BE
;
284 else if (*f
== PA_SAMPLE_S24BE
)
285 *f
= PA_SAMPLE_S24LE
;
286 else if (*f
== PA_SAMPLE_S24LE
)
287 *f
= PA_SAMPLE_S24BE
;
288 else if (*f
== PA_SAMPLE_S24_32BE
)
289 *f
= PA_SAMPLE_S24_32LE
;
290 else if (*f
== PA_SAMPLE_S24_32LE
)
291 *f
= PA_SAMPLE_S24_32BE
;
292 else if (*f
== PA_SAMPLE_S16BE
)
293 *f
= PA_SAMPLE_S16LE
;
294 else if (*f
== PA_SAMPLE_S16LE
)
295 *f
= PA_SAMPLE_S16BE
;
296 else if (*f
== PA_SAMPLE_S32BE
)
297 *f
= PA_SAMPLE_S32LE
;
298 else if (*f
== PA_SAMPLE_S32LE
)
299 *f
= PA_SAMPLE_S32BE
;
303 if ((ret
= snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[*f
])) >= 0)
306 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
307 snd_pcm_format_description(format_trans
[*f
]),
308 pa_alsa_strerror(ret
));
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)
318 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
319 snd_pcm_format_description(format_trans
[*f
]),
320 pa_alsa_strerror(ret
));
326 /* Set the hardware parameters of the given ALSA device. Returns the
327 * selected fragment settings in *period and *period_size */
328 int pa_alsa_set_hw_params(
329 snd_pcm_t
*pcm_handle
,
332 snd_pcm_uframes_t
*period_size
,
333 snd_pcm_uframes_t tsched_size
,
335 pa_bool_t
*use_tsched
,
336 pa_bool_t require_exact_channel_number
) {
339 snd_pcm_uframes_t _period_size
= period_size
? *period_size
: 0;
340 unsigned int _periods
= periods
? *periods
: 0;
341 unsigned int r
= ss
->rate
;
342 unsigned int c
= ss
->channels
;
343 pa_sample_format_t f
= ss
->format
;
344 snd_pcm_hw_params_t
*hwparams
;
345 pa_bool_t _use_mmap
= use_mmap
&& *use_mmap
;
346 pa_bool_t _use_tsched
= use_tsched
&& *use_tsched
;
349 pa_assert(pcm_handle
);
352 snd_pcm_hw_params_alloca(&hwparams
);
354 if ((ret
= snd_pcm_hw_params_any(pcm_handle
, hwparams
)) < 0) {
355 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret
));
359 if ((ret
= snd_pcm_hw_params_set_rate_resample(pcm_handle
, hwparams
, 0)) < 0) {
360 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret
));
366 if (snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_MMAP_INTERLEAVED
) < 0) {
368 /* mmap() didn't work, fall back to interleaved */
370 if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0) {
371 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret
));
378 } else if ((ret
= snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
)) < 0) {
379 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret
));
386 if ((ret
= set_format(pcm_handle
, hwparams
, &f
)) < 0)
389 if ((ret
= snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &r
, NULL
)) < 0) {
390 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret
));
394 if (require_exact_channel_number
) {
395 if ((ret
= snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, c
)) < 0) {
396 pa_log_debug("snd_pcm_hw_params_set_channels() failed: %s", pa_alsa_strerror(ret
));
400 if ((ret
= snd_pcm_hw_params_set_channels_near(pcm_handle
, hwparams
, &c
)) < 0) {
401 pa_log_debug("snd_pcm_hw_params_set_channels_near() failed: %s", pa_alsa_strerror(ret
));
406 if ((ret
= snd_pcm_hw_params_set_periods_integer(pcm_handle
, hwparams
)) < 0) {
407 pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret
));
411 if (_period_size
&& tsched_size
&& _periods
) {
413 /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
414 _period_size
= (snd_pcm_uframes_t
) (((uint64_t) _period_size
* r
) / ss
->rate
);
415 tsched_size
= (snd_pcm_uframes_t
) (((uint64_t) tsched_size
* r
) / ss
->rate
);
418 snd_pcm_uframes_t buffer_size
;
420 pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams
, &buffer_size
) == 0);
421 pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size
* 1000 / r
);
423 _period_size
= tsched_size
;
427 if (_period_size
> 0 && _periods
> 0) {
428 snd_pcm_uframes_t buffer_size
;
430 buffer_size
= _periods
* _period_size
;
432 if ((ret
= snd_pcm_hw_params_set_buffer_size_near(pcm_handle
, hwparams
, &buffer_size
)) < 0)
433 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret
));
438 /* First we pass 0 as direction to get exactly what we
439 * asked for. That this is necessary is presumably a bug
440 * in ALSA. All in all this is mostly a hint to ALSA, so
441 * we don't care if this fails. */
444 if (snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
) < 0) {
446 if (snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
) < 0) {
448 if ((ret
= snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, &_periods
, &dir
)) < 0)
449 pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret
));
455 if ((ret
= snd_pcm_hw_params(pcm_handle
, hwparams
)) < 0)
459 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle
), ss
->rate
, r
);
461 if (ss
->channels
!= c
)
462 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle
), ss
->channels
, c
);
465 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
));
467 if ((ret
= snd_pcm_prepare(pcm_handle
)) < 0)
470 if ((ret
= snd_pcm_hw_params_get_period_size(hwparams
, &_period_size
, &dir
)) < 0 ||
471 (ret
= snd_pcm_hw_params_get_periods(hwparams
, &_periods
, &dir
)) < 0)
474 /* If the sample rate deviates too much, we need to resample */
475 if (r
< ss
->rate
*.95 || r
> ss
->rate
*1.05)
477 ss
->channels
= (uint8_t) c
;
480 pa_assert(_periods
> 0);
481 pa_assert(_period_size
> 0);
487 *period_size
= _period_size
;
490 *use_mmap
= _use_mmap
;
493 *use_tsched
= _use_tsched
;
497 snd_pcm_nonblock(pcm_handle
, 1);
504 int pa_alsa_set_sw_params(snd_pcm_t
*pcm
, snd_pcm_uframes_t avail_min
) {
505 snd_pcm_sw_params_t
*swparams
;
506 snd_pcm_uframes_t boundary
;
511 snd_pcm_sw_params_alloca(&swparams
);
513 if ((err
= snd_pcm_sw_params_current(pcm
, swparams
) < 0)) {
514 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err
));
518 if ((err
= snd_pcm_sw_params_set_period_event(pcm
, swparams
, 0)) < 0) {
519 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err
));
523 if ((err
= snd_pcm_sw_params_set_tstamp_mode(pcm
, swparams
, SND_PCM_TSTAMP_ENABLE
)) < 0) {
524 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err
));
528 if ((err
= snd_pcm_sw_params_get_boundary(swparams
, &boundary
)) < 0) {
529 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err
));
533 if ((err
= snd_pcm_sw_params_set_stop_threshold(pcm
, swparams
, boundary
)) < 0) {
534 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err
));
538 if ((err
= snd_pcm_sw_params_set_start_threshold(pcm
, swparams
, (snd_pcm_uframes_t
) -1)) < 0) {
539 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err
));
543 if ((err
= snd_pcm_sw_params_set_avail_min(pcm
, swparams
, avail_min
)) < 0) {
544 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err
));
548 if ((err
= snd_pcm_sw_params(pcm
, swparams
)) < 0) {
549 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err
));
556 static const struct pa_alsa_profile_info device_table
[] = {
557 {{ 1, { PA_CHANNEL_POSITION_MONO
}},
565 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
573 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
575 N_("Digital Stereo (IEC958)"),
581 {{ 2, { PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
}},
583 N_("Digital Stereo (HDMI)"),
589 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
590 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
592 N_("Analog Surround 4.0"),
593 "analog-surround-40",
598 {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
599 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
}},
601 N_("Digital Surround 4.0 (IEC958/AC3)"),
602 "iec958-ac3-surround-40",
607 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
608 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
609 PA_CHANNEL_POSITION_LFE
}},
611 N_("Analog Surround 4.1"),
612 "analog-surround-41",
617 {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
618 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
619 PA_CHANNEL_POSITION_CENTER
}},
621 N_("Analog Surround 5.0"),
622 "analog-surround-50",
627 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
628 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
629 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
}},
631 N_("Analog Surround 5.1"),
632 "analog-surround-51",
637 {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
638 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
639 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
}},
641 N_("Digital Surround 5.1 (IEC958/AC3)"),
642 "iec958-ac3-surround-51",
647 {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
648 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
649 PA_CHANNEL_POSITION_CENTER
, PA_CHANNEL_POSITION_LFE
,
650 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
}},
652 N_("Analog Surround 7.1"),
653 "analog-surround-71",
658 {{ 0, { 0 }}, NULL
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
}
661 static snd_pcm_t
*open_by_device_string_with_fallback(
663 const char *prefix_fallback
,
670 snd_pcm_uframes_t
*period_size
,
671 snd_pcm_uframes_t tsched_size
,
673 pa_bool_t
*use_tsched
,
674 pa_bool_t require_exact_channel_number
) {
676 snd_pcm_t
*pcm_handle
;
679 d
= pa_sprintf_malloc("%s:%s", prefix
, dev_id
);
681 pcm_handle
= pa_alsa_open_by_device_string(
692 require_exact_channel_number
);
695 if (!pcm_handle
&& prefix_fallback
) {
697 d
= pa_sprintf_malloc("%s:%s", prefix_fallback
, dev_id
);
699 pcm_handle
= pa_alsa_open_by_device_string(
710 require_exact_channel_number
);
717 snd_pcm_t
*pa_alsa_open_by_device_id_auto(
724 snd_pcm_uframes_t
*period_size
,
725 snd_pcm_uframes_t tsched_size
,
727 pa_bool_t
*use_tsched
,
728 const pa_alsa_profile_info
**profile
) {
733 snd_pcm_t
*pcm_handle
;
740 pa_assert(period_size
);
742 /* First we try to find a device string with a superset of the
743 * requested channel map and open it without the plug: prefix. We
744 * iterate through our device table from top to bottom and take
745 * the first that matches. If we didn't find a working device that
746 * way, we iterate backwards, and check all devices that do not
747 * provide a superset of the requested channel map.*/
752 if ((direction
> 0) == pa_channel_map_superset(&device_table
[i
].map
, map
)) {
753 pa_sample_spec try_ss
;
755 pa_log_debug("Checking for %s (%s)", device_table
[i
].name
, device_table
[i
].alsa_name
);
757 try_ss
.channels
= device_table
[i
].map
.channels
;
758 try_ss
.rate
= ss
->rate
;
759 try_ss
.format
= ss
->format
;
761 pcm_handle
= open_by_device_string_with_fallback(
762 device_table
[i
].alsa_name
,
763 device_table
[i
].alsa_name_fallback
,
779 *map
= device_table
[i
].map
;
780 pa_assert(map
->channels
== ss
->channels
);
783 *profile
= &device_table
[i
];
791 if (!device_table
[i
+1].alsa_name
) {
792 /* OK, so we are at the end of our list. Let's turn
796 /* We are not at the end of the list, so let's simply
797 * try the next entry */
804 if (device_table
[i
+1].alsa_name
&&
805 device_table
[i
].map
.channels
== device_table
[i
+1].map
.channels
) {
807 /* OK, the next entry has the same number of channels,
812 /* Hmm, so the next entry does not have the same
813 * number of channels, so let's go backwards until we
814 * find the next entry with a different number of
817 for (i
--; i
>= 0; i
--)
818 if (device_table
[i
].map
.channels
!= device_table
[i
+1].map
.channels
)
821 /* Hmm, there is no entry with a different number of
822 * entries, then we're done */
826 /* OK, now lets find go back as long as we have the same number of channels */
828 if (device_table
[i
].map
.channels
!= device_table
[i
-1].map
.channels
)
834 /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
836 d
= pa_sprintf_malloc("hw:%s", dev_id
);
837 pa_log_debug("Trying %s as last resort...", d
);
838 pcm_handle
= pa_alsa_open_by_device_string(d
, dev
, ss
, map
, mode
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, FALSE
);
841 if (pcm_handle
&& profile
)
847 snd_pcm_t
*pa_alsa_open_by_device_id_profile(
854 snd_pcm_uframes_t
*period_size
,
855 snd_pcm_uframes_t tsched_size
,
857 pa_bool_t
*use_tsched
,
858 const pa_alsa_profile_info
*profile
) {
860 snd_pcm_t
*pcm_handle
;
861 pa_sample_spec try_ss
;
868 pa_assert(period_size
);
871 try_ss
.channels
= profile
->map
.channels
;
872 try_ss
.rate
= ss
->rate
;
873 try_ss
.format
= ss
->format
;
875 pcm_handle
= open_by_device_string_with_fallback(
877 profile
->alsa_name_fallback
,
895 pa_assert(map
->channels
== ss
->channels
);
900 snd_pcm_t
*pa_alsa_open_by_device_string(
907 snd_pcm_uframes_t
*period_size
,
908 snd_pcm_uframes_t tsched_size
,
910 pa_bool_t
*use_tsched
,
911 pa_bool_t require_exact_channel_number
) {
915 snd_pcm_t
*pcm_handle
;
916 pa_bool_t reformat
= FALSE
;
922 d
= pa_xstrdup(device
);
925 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d
, reformat
? "without" : "with");
927 /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
928 * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
929 * we enable nonblock mode afterwards via
930 * snd_pcm_nonblock(). Also see
931 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
933 if ((err
= snd_pcm_open(&pcm_handle
, d
, mode
,
934 /*SND_PCM_NONBLOCK|*/
935 SND_PCM_NO_AUTO_RESAMPLE
|
936 SND_PCM_NO_AUTO_CHANNELS
|
937 (reformat
? 0 : SND_PCM_NO_AUTO_FORMAT
))) < 0) {
938 pa_log_info("Error opening PCM device %s: %s", d
, pa_alsa_strerror(err
));
942 pa_log_debug("Managed to open %s", d
);
944 if ((err
= pa_alsa_set_hw_params(pcm_handle
, ss
, nfrags
, period_size
, tsched_size
, use_mmap
, use_tsched
, require_exact_channel_number
)) < 0) {
949 snd_pcm_close(pcm_handle
);
953 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
955 if (!pa_startswith(d
, "plug:") && !pa_startswith(d
, "plughw:")) {
958 t
= pa_sprintf_malloc("plug:%s", d
);
964 snd_pcm_close(pcm_handle
);
968 pa_log_info("Failed to set hardware parameters on %s: %s", d
, pa_alsa_strerror(err
));
969 snd_pcm_close(pcm_handle
);
979 if (ss
->channels
!= map
->channels
)
980 pa_channel_map_init_extend(map
, ss
->channels
, PA_CHANNEL_MAP_ALSA
);
991 int pa_alsa_probe_profiles(
993 const pa_sample_spec
*ss
,
994 void (*cb
)(const pa_alsa_profile_info
*sink
, const pa_alsa_profile_info
*source
, void *userdata
),
997 const pa_alsa_profile_info
*i
;
1003 /* We try each combination of playback/capture. We also try to
1004 * open only for capture resp. only for sink. Don't get confused
1005 * by the trailing entry in device_table we use for this! */
1007 for (i
= device_table
; i
< device_table
+ PA_ELEMENTSOF(device_table
); i
++) {
1008 const pa_alsa_profile_info
*j
;
1009 snd_pcm_t
*pcm_i
= NULL
;
1012 pa_sample_spec try_ss
;
1013 pa_channel_map try_map
;
1015 pa_log_debug("Checking for playback on %s (%s)", i
->name
, i
->alsa_name
);
1018 try_ss
.channels
= i
->map
.channels
;
1021 pcm_i
= open_by_device_string_with_fallback(
1023 i
->alsa_name_fallback
,
1027 SND_PCM_STREAM_PLAYBACK
,
1028 NULL
, NULL
, 0, NULL
, NULL
,
1035 for (j
= device_table
; j
< device_table
+ PA_ELEMENTSOF(device_table
); j
++) {
1036 snd_pcm_t
*pcm_j
= NULL
;
1039 pa_sample_spec try_ss
;
1040 pa_channel_map try_map
;
1042 pa_log_debug("Checking for capture on %s (%s)", j
->name
, j
->alsa_name
);
1045 try_ss
.channels
= j
->map
.channels
;
1048 pcm_j
= open_by_device_string_with_fallback(
1050 j
->alsa_name_fallback
,
1054 SND_PCM_STREAM_CAPTURE
,
1055 NULL
, NULL
, 0, NULL
, NULL
,
1063 snd_pcm_close(pcm_j
);
1065 if (i
->alsa_name
|| j
->alsa_name
)
1066 cb(i
->alsa_name
? i
: NULL
,
1067 j
->alsa_name
? j
: NULL
, userdata
);
1071 snd_pcm_close(pcm_i
);
1077 int pa_alsa_prepare_mixer(snd_mixer_t
*mixer
, const char *dev
) {
1083 if ((err
= snd_mixer_attach(mixer
, dev
)) < 0) {
1084 pa_log_info("Unable to attach to mixer %s: %s", dev
, pa_alsa_strerror(err
));
1088 if ((err
= snd_mixer_selem_register(mixer
, NULL
, NULL
)) < 0) {
1089 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err
));
1093 if ((err
= snd_mixer_load(mixer
)) < 0) {
1094 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err
));
1098 pa_log_info("Successfully attached to mixer '%s'", dev
);
1103 static pa_bool_t
elem_has_volume(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1106 if (playback
&& snd_mixer_selem_has_playback_volume(elem
))
1109 if (!playback
&& snd_mixer_selem_has_capture_volume(elem
))
1115 static pa_bool_t
elem_has_switch(snd_mixer_elem_t
*elem
, pa_bool_t playback
) {
1118 if (playback
&& snd_mixer_selem_has_playback_switch(elem
))
1121 if (!playback
&& snd_mixer_selem_has_capture_switch(elem
))
1127 snd_mixer_elem_t
*pa_alsa_find_elem(snd_mixer_t
*mixer
, const char *name
, const char *fallback
, pa_bool_t playback
) {
1128 snd_mixer_elem_t
*elem
= NULL
, *fallback_elem
= NULL
;
1129 snd_mixer_selem_id_t
*sid
= NULL
;
1131 snd_mixer_selem_id_alloca(&sid
);
1136 snd_mixer_selem_id_set_name(sid
, name
);
1137 snd_mixer_selem_id_set_index(sid
, 0);
1139 if ((elem
= snd_mixer_find_selem(mixer
, sid
))) {
1141 if (elem_has_volume(elem
, playback
) &&
1142 elem_has_switch(elem
, playback
))
1145 if (!elem_has_volume(elem
, playback
) &&
1146 !elem_has_switch(elem
, playback
))
1150 pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid
));
1153 snd_mixer_selem_id_set_name(sid
, fallback
);
1154 snd_mixer_selem_id_set_index(sid
, 0);
1156 if ((fallback_elem
= snd_mixer_find_selem(mixer
, sid
))) {
1158 if (elem_has_volume(fallback_elem
, playback
) &&
1159 elem_has_switch(fallback_elem
, playback
)) {
1160 elem
= fallback_elem
;
1164 if (!elem_has_volume(fallback_elem
, playback
) &&
1165 !elem_has_switch(fallback_elem
, playback
))
1166 fallback_elem
= NULL
;
1169 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
));
1172 if (elem
&& fallback_elem
) {
1174 /* Hmm, so we have both elements, but neither has both mute
1175 * and volume. Let's prefer the one with the volume */
1177 if (elem_has_volume(elem
, playback
))
1180 if (elem_has_volume(fallback_elem
, playback
)) {
1181 elem
= fallback_elem
;
1186 if (!elem
&& fallback_elem
)
1187 elem
= fallback_elem
;
1192 pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid
));
1197 int pa_alsa_find_mixer_and_elem(
1201 snd_mixer_elem_t
**_e
,
1202 const char *control_name
,
1203 const pa_alsa_profile_info
*profile
) {
1207 snd_mixer_elem_t
*e
;
1208 pa_bool_t found
= FALSE
;
1215 if (control_name
&& *control_name
== 0) {
1216 pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1220 if ((err
= snd_mixer_open(&m
, 0)) < 0) {
1221 pa_log("Error opening mixer: %s", pa_alsa_strerror(err
));
1225 /* First, try by name */
1226 if ((dev
= snd_pcm_name(pcm
)))
1227 if (pa_alsa_prepare_mixer(m
, dev
) >= 0) {
1231 *ctl_device
= pa_xstrdup(dev
);
1234 /* Then, try by card index */
1236 snd_pcm_info_t
* info
;
1237 snd_pcm_info_alloca(&info
);
1239 if (snd_pcm_info(pcm
, info
) >= 0) {
1243 if ((card_idx
= snd_pcm_info_get_card(info
)) >= 0) {
1245 md
= pa_sprintf_malloc("hw:%i", card_idx
);
1247 if (!dev
|| !pa_streq(dev
, md
))
1248 if (pa_alsa_prepare_mixer(m
, md
) >= 0) {
1267 switch (snd_pcm_stream(pcm
)) {
1269 case SND_PCM_STREAM_PLAYBACK
:
1271 e
= pa_alsa_find_elem(m
, control_name
, NULL
, TRUE
);
1273 e
= pa_alsa_find_elem(m
, profile
->playback_control_name
, profile
->playback_control_fallback
, TRUE
);
1275 e
= pa_alsa_find_elem(m
, "Master", "PCM", TRUE
);
1278 case SND_PCM_STREAM_CAPTURE
:
1280 e
= pa_alsa_find_elem(m
, control_name
, NULL
, FALSE
);
1282 e
= pa_alsa_find_elem(m
, profile
->record_control_name
, profile
->record_control_fallback
, FALSE
);
1284 e
= pa_alsa_find_elem(m
, "Capture", "Mic", FALSE
);
1288 pa_assert_not_reached();
1293 pa_xfree(*ctl_device
);
1307 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1308 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1310 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1311 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1312 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1314 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1315 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1316 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1318 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1320 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1321 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1323 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1324 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1326 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1327 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1328 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1329 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1330 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1331 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1332 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1333 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1334 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1335 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1336 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1337 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1338 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1339 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1340 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1341 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1342 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1343 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1344 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1345 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1346 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1347 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1348 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1349 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1350 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1351 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1352 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1353 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1354 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1355 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1356 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1357 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1359 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1361 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1362 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1363 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1365 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1366 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1367 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1371 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
) {
1373 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1374 pa_bool_t mono_used
= FALSE
;
1377 pa_assert(channel_map
);
1378 pa_assert(mixer_map
);
1380 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1382 if (channel_map
->channels
> 1 &&
1383 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1384 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1385 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1389 for (i
= 0; i
< channel_map
->channels
; i
++) {
1390 snd_mixer_selem_channel_id_t id
;
1393 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1394 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1396 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1397 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
]));
1401 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1402 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1406 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1407 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1409 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1414 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1418 alsa_channel_used
[id
] = TRUE
;
1422 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1427 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
1433 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1435 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1436 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1439 snd_output_buffer_string(out
, &s
);
1440 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
1443 pa_assert_se(snd_output_close(out
) == 0);
1446 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1449 snd_pcm_status_t
*status
;
1453 snd_pcm_status_alloca(&status
);
1455 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1457 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1459 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1460 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1463 snd_output_buffer_string(out
, &s
);
1464 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1467 pa_assert_se(snd_output_close(out
) == 0);
1470 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1474 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1478 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1482 pa_xfree(alsa_file
);
1485 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1487 void pa_alsa_redirect_errors_inc(void) {
1488 /* This is not really thread safe, but we do our best */
1490 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1491 snd_lib_error_set_handler(alsa_error_handler
);
1494 void pa_alsa_redirect_errors_dec(void) {
1497 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1500 snd_lib_error_set_handler(NULL
);
1503 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1507 if (pa_device_init_description(p
))
1510 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1511 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1515 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1516 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1523 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1524 char *cn
, *lcn
, *dn
;
1527 pa_assert(card
>= 0);
1529 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1531 if (snd_card_get_name(card
, &cn
) >= 0) {
1532 pa_proplist_sets(p
, "alsa.card_name", cn
);
1536 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1537 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1541 if ((dn
= pa_alsa_get_driver_name(card
))) {
1542 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1547 pa_udev_get_info(c
, p
, card
);
1551 pa_hal_get_info(c
, p
, card
);
1555 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1557 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1558 [SND_PCM_CLASS_GENERIC
] = "generic",
1559 [SND_PCM_CLASS_MULTI
] = "multi",
1560 [SND_PCM_CLASS_MODEM
] = "modem",
1561 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1563 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1564 [SND_PCM_CLASS_GENERIC
] = "sound",
1565 [SND_PCM_CLASS_MULTI
] = NULL
,
1566 [SND_PCM_CLASS_MODEM
] = "modem",
1567 [SND_PCM_CLASS_DIGITIZER
] = NULL
1569 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1570 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1571 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1574 snd_pcm_class_t
class;
1575 snd_pcm_subclass_t subclass
;
1576 const char *n
, *id
, *sdn
;
1580 pa_assert(pcm_info
);
1582 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1584 class = snd_pcm_info_get_class(pcm_info
);
1585 if (class <= SND_PCM_CLASS_LAST
) {
1586 if (class_table
[class])
1587 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1588 if (alsa_class_table
[class])
1589 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1592 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1593 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1594 if (alsa_subclass_table
[subclass
])
1595 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1597 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1598 pa_proplist_sets(p
, "alsa.name", n
);
1600 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1601 pa_proplist_sets(p
, "alsa.id", id
);
1603 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1604 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1605 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1607 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1609 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1610 pa_alsa_init_proplist_card(c
, p
, card
);
1613 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
, snd_mixer_elem_t
*elem
) {
1614 snd_pcm_hw_params_t
*hwparams
;
1615 snd_pcm_info_t
*info
;
1618 snd_pcm_hw_params_alloca(&hwparams
);
1619 snd_pcm_info_alloca(&info
);
1621 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1622 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
1625 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1626 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1630 pa_proplist_sets(p
, "alsa.mixer_element", snd_mixer_selem_get_name(elem
));
1632 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1633 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
1635 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1638 void pa_alsa_init_proplist_ctl(pa_proplist
*p
, const char *name
) {
1641 snd_ctl_card_info_t
*info
;
1646 snd_ctl_card_info_alloca(&info
);
1648 if ((err
= snd_ctl_open(&ctl
, name
, 0)) < 0) {
1649 pa_log_warn("Error opening low-level control device '%s'", name
);
1653 if ((err
= snd_ctl_card_info(ctl
, info
)) < 0) {
1654 pa_log_warn("Control device %s card info: %s", name
, snd_strerror(err
));
1659 if ((t
= snd_ctl_card_info_get_mixername(info
)))
1660 pa_proplist_sets(p
, "alsa.mixer_name", t
);
1662 if ((t
= snd_ctl_card_info_get_components(info
)))
1663 pa_proplist_sets(p
, "alsa.components", t
);
1668 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1669 snd_pcm_state_t state
;
1674 if (revents
& POLLERR
)
1675 pa_log_debug("Got POLLERR from ALSA");
1676 if (revents
& POLLNVAL
)
1677 pa_log_warn("Got POLLNVAL from ALSA");
1678 if (revents
& POLLHUP
)
1679 pa_log_warn("Got POLLHUP from ALSA");
1680 if (revents
& POLLPRI
)
1681 pa_log_warn("Got POLLPRI from ALSA");
1682 if (revents
& POLLIN
)
1683 pa_log_debug("Got POLLIN from ALSA");
1684 if (revents
& POLLOUT
)
1685 pa_log_debug("Got POLLOUT from ALSA");
1687 state
= snd_pcm_state(pcm
);
1688 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1690 /* Try to recover from this error */
1694 case SND_PCM_STATE_XRUN
:
1695 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1696 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1701 case SND_PCM_STATE_SUSPENDED
:
1702 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1703 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1712 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1713 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1722 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1724 struct pollfd
*pollfd
;
1725 pa_rtpoll_item
*item
;
1729 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1730 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1734 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1735 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1737 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1738 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1739 pa_rtpoll_item_free(item
);
1746 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1747 snd_pcm_sframes_t n
;
1751 pa_assert(hwbuf_size
> 0);
1754 /* Some ALSA driver expose weird bugs, let's inform the user about
1755 * what is going on */
1757 n
= snd_pcm_avail(pcm
);
1762 k
= (size_t) n
* pa_frame_size(ss
);
1764 if (k
>= hwbuf_size
* 5 ||
1765 k
>= pa_bytes_per_second(ss
)*10) {
1768 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1769 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1770 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1772 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1775 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1778 /* Mhmm, let's try not to fail completely */
1779 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1785 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1792 pa_assert(hwbuf_size
> 0);
1795 /* Some ALSA driver expose weird bugs, let's inform the user about
1796 * what is going on */
1798 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1801 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1803 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1805 if (abs_k
>= hwbuf_size
* 5 ||
1806 abs_k
>= pa_bytes_per_second(ss
)*10) {
1809 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1810 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1811 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1814 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1817 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1820 /* Mhmm, let's try not to fail completely */
1822 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1824 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1830 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
) {
1832 snd_pcm_uframes_t before
;
1839 pa_assert(hwbuf_size
> 0);
1844 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1849 k
= (size_t) *frames
* pa_frame_size(ss
);
1851 if (*frames
> before
||
1852 k
>= hwbuf_size
* 3 ||
1853 k
>= pa_bytes_per_second(ss
)*10)
1856 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1857 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1858 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1860 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1863 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1869 char *pa_alsa_get_driver_name(int card
) {
1872 pa_assert(card
>= 0);
1874 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1881 n
= pa_xstrdup(pa_path_get_filename(m
));
1887 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1889 snd_pcm_info_t
* info
;
1890 snd_pcm_info_alloca(&info
);
1894 if (snd_pcm_info(pcm
, info
) < 0)
1897 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1900 return pa_alsa_get_driver_name(card
);
1903 char *pa_alsa_get_reserve_name(const char *device
) {
1909 if ((t
= strchr(device
, ':')))
1912 if ((i
= snd_card_get_index(device
)) < 0) {
1915 if (pa_atoi(device
, &k
) < 0)
1921 return pa_sprintf_malloc("Audio%i", i
);
1924 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1925 snd_pcm_info_t
* info
;
1926 snd_pcm_info_alloca(&info
);
1930 if (snd_pcm_info(pcm
, info
) < 0)
1933 return snd_pcm_info_get_card(info
) >= 0;
1936 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1937 snd_pcm_info_t
* info
;
1938 snd_pcm_info_alloca(&info
);
1942 if (snd_pcm_info(pcm
, info
) < 0)
1945 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1948 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1950 const char* pa_alsa_strerror(int errnum
) {
1951 const char *original
= NULL
;
1952 char *translated
, *t
;
1955 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1958 original
= snd_strerror(errnum
);
1961 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1965 if (!(translated
= pa_locale_to_utf8(original
))) {
1966 pa_log_warn("Unable to convert error string to locale, filtering.");
1967 translated
= pa_utf8_filter(original
);
1970 PA_STATIC_TLS_SET(cstrerror
, translated
);