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
);
1309 static const snd_mixer_selem_channel_id_t alsa_channel_ids
[PA_CHANNEL_POSITION_MAX
] = {
1310 [PA_CHANNEL_POSITION_MONO
] = SND_MIXER_SCHN_MONO
, /* The ALSA name is just an alias! */
1312 [PA_CHANNEL_POSITION_FRONT_CENTER
] = SND_MIXER_SCHN_FRONT_CENTER
,
1313 [PA_CHANNEL_POSITION_FRONT_LEFT
] = SND_MIXER_SCHN_FRONT_LEFT
,
1314 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = SND_MIXER_SCHN_FRONT_RIGHT
,
1316 [PA_CHANNEL_POSITION_REAR_CENTER
] = SND_MIXER_SCHN_REAR_CENTER
,
1317 [PA_CHANNEL_POSITION_REAR_LEFT
] = SND_MIXER_SCHN_REAR_LEFT
,
1318 [PA_CHANNEL_POSITION_REAR_RIGHT
] = SND_MIXER_SCHN_REAR_RIGHT
,
1320 [PA_CHANNEL_POSITION_LFE
] = SND_MIXER_SCHN_WOOFER
,
1322 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1323 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1325 [PA_CHANNEL_POSITION_SIDE_LEFT
] = SND_MIXER_SCHN_SIDE_LEFT
,
1326 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = SND_MIXER_SCHN_SIDE_RIGHT
,
1328 [PA_CHANNEL_POSITION_AUX0
] = SND_MIXER_SCHN_UNKNOWN
,
1329 [PA_CHANNEL_POSITION_AUX1
] = SND_MIXER_SCHN_UNKNOWN
,
1330 [PA_CHANNEL_POSITION_AUX2
] = SND_MIXER_SCHN_UNKNOWN
,
1331 [PA_CHANNEL_POSITION_AUX3
] = SND_MIXER_SCHN_UNKNOWN
,
1332 [PA_CHANNEL_POSITION_AUX4
] = SND_MIXER_SCHN_UNKNOWN
,
1333 [PA_CHANNEL_POSITION_AUX5
] = SND_MIXER_SCHN_UNKNOWN
,
1334 [PA_CHANNEL_POSITION_AUX6
] = SND_MIXER_SCHN_UNKNOWN
,
1335 [PA_CHANNEL_POSITION_AUX7
] = SND_MIXER_SCHN_UNKNOWN
,
1336 [PA_CHANNEL_POSITION_AUX8
] = SND_MIXER_SCHN_UNKNOWN
,
1337 [PA_CHANNEL_POSITION_AUX9
] = SND_MIXER_SCHN_UNKNOWN
,
1338 [PA_CHANNEL_POSITION_AUX10
] = SND_MIXER_SCHN_UNKNOWN
,
1339 [PA_CHANNEL_POSITION_AUX11
] = SND_MIXER_SCHN_UNKNOWN
,
1340 [PA_CHANNEL_POSITION_AUX12
] = SND_MIXER_SCHN_UNKNOWN
,
1341 [PA_CHANNEL_POSITION_AUX13
] = SND_MIXER_SCHN_UNKNOWN
,
1342 [PA_CHANNEL_POSITION_AUX14
] = SND_MIXER_SCHN_UNKNOWN
,
1343 [PA_CHANNEL_POSITION_AUX15
] = SND_MIXER_SCHN_UNKNOWN
,
1344 [PA_CHANNEL_POSITION_AUX16
] = SND_MIXER_SCHN_UNKNOWN
,
1345 [PA_CHANNEL_POSITION_AUX17
] = SND_MIXER_SCHN_UNKNOWN
,
1346 [PA_CHANNEL_POSITION_AUX18
] = SND_MIXER_SCHN_UNKNOWN
,
1347 [PA_CHANNEL_POSITION_AUX19
] = SND_MIXER_SCHN_UNKNOWN
,
1348 [PA_CHANNEL_POSITION_AUX20
] = SND_MIXER_SCHN_UNKNOWN
,
1349 [PA_CHANNEL_POSITION_AUX21
] = SND_MIXER_SCHN_UNKNOWN
,
1350 [PA_CHANNEL_POSITION_AUX22
] = SND_MIXER_SCHN_UNKNOWN
,
1351 [PA_CHANNEL_POSITION_AUX23
] = SND_MIXER_SCHN_UNKNOWN
,
1352 [PA_CHANNEL_POSITION_AUX24
] = SND_MIXER_SCHN_UNKNOWN
,
1353 [PA_CHANNEL_POSITION_AUX25
] = SND_MIXER_SCHN_UNKNOWN
,
1354 [PA_CHANNEL_POSITION_AUX26
] = SND_MIXER_SCHN_UNKNOWN
,
1355 [PA_CHANNEL_POSITION_AUX27
] = SND_MIXER_SCHN_UNKNOWN
,
1356 [PA_CHANNEL_POSITION_AUX28
] = SND_MIXER_SCHN_UNKNOWN
,
1357 [PA_CHANNEL_POSITION_AUX29
] = SND_MIXER_SCHN_UNKNOWN
,
1358 [PA_CHANNEL_POSITION_AUX30
] = SND_MIXER_SCHN_UNKNOWN
,
1359 [PA_CHANNEL_POSITION_AUX31
] = SND_MIXER_SCHN_UNKNOWN
,
1361 [PA_CHANNEL_POSITION_TOP_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1363 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1364 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1365 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
,
1367 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = SND_MIXER_SCHN_UNKNOWN
,
1368 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = SND_MIXER_SCHN_UNKNOWN
,
1369 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = SND_MIXER_SCHN_UNKNOWN
1373 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
) {
1375 pa_bool_t alsa_channel_used
[SND_MIXER_SCHN_LAST
];
1376 pa_bool_t mono_used
= FALSE
;
1379 pa_assert(channel_map
);
1380 pa_assert(mixer_map
);
1382 memset(&alsa_channel_used
, 0, sizeof(alsa_channel_used
));
1384 if (channel_map
->channels
> 1 &&
1385 ((playback
&& snd_mixer_selem_has_playback_volume_joined(elem
)) ||
1386 (!playback
&& snd_mixer_selem_has_capture_volume_joined(elem
)))) {
1387 pa_log_info("ALSA device lacks independant volume controls for each channel.");
1391 for (i
= 0; i
< channel_map
->channels
; i
++) {
1392 snd_mixer_selem_channel_id_t id
;
1395 is_mono
= channel_map
->map
[i
] == PA_CHANNEL_POSITION_MONO
;
1396 id
= alsa_channel_ids
[channel_map
->map
[i
]];
1398 if (!is_mono
&& id
== SND_MIXER_SCHN_UNKNOWN
) {
1399 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
]));
1403 if ((is_mono
&& mono_used
) || (!is_mono
&& alsa_channel_used
[id
])) {
1404 pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map
->map
[i
]));
1408 if ((playback
&& (!snd_mixer_selem_has_playback_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_playback_mono(elem
)))) ||
1409 (!playback
&& (!snd_mixer_selem_has_capture_channel(elem
, id
) || (is_mono
&& !snd_mixer_selem_is_capture_mono(elem
))))) {
1411 pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map
->map
[i
]));
1416 mixer_map
[i
] = SND_MIXER_SCHN_MONO
;
1420 alsa_channel_used
[id
] = TRUE
;
1424 pa_log_info("All %u channels can be mapped to mixer channels.", channel_map
->channels
);
1429 void pa_alsa_dump(pa_log_level_t level
, snd_pcm_t
*pcm
) {
1435 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1437 if ((err
= snd_pcm_dump(pcm
, out
)) < 0)
1438 pa_logl(level
, "snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1441 snd_output_buffer_string(out
, &s
);
1442 pa_logl(level
, "snd_pcm_dump():\n%s", pa_strnull(s
));
1445 pa_assert_se(snd_output_close(out
) == 0);
1448 void pa_alsa_dump_status(snd_pcm_t
*pcm
) {
1451 snd_pcm_status_t
*status
;
1455 snd_pcm_status_alloca(&status
);
1457 pa_assert_se(snd_output_buffer_open(&out
) == 0);
1459 pa_assert_se(snd_pcm_status(pcm
, status
) == 0);
1461 if ((err
= snd_pcm_status_dump(status
, out
)) < 0)
1462 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err
));
1465 snd_output_buffer_string(out
, &s
);
1466 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s
));
1469 pa_assert_se(snd_output_close(out
) == 0);
1472 static void alsa_error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
,...) {
1476 alsa_file
= pa_sprintf_malloc("(alsa-lib)%s", file
);
1480 pa_log_levelv_meta(PA_LOG_INFO
, alsa_file
, line
, function
, fmt
, ap
);
1484 pa_xfree(alsa_file
);
1487 static pa_atomic_t n_error_handler_installed
= PA_ATOMIC_INIT(0);
1489 void pa_alsa_redirect_errors_inc(void) {
1490 /* This is not really thread safe, but we do our best */
1492 if (pa_atomic_inc(&n_error_handler_installed
) == 0)
1493 snd_lib_error_set_handler(alsa_error_handler
);
1496 void pa_alsa_redirect_errors_dec(void) {
1499 pa_assert_se((r
= pa_atomic_dec(&n_error_handler_installed
)) >= 1);
1502 snd_lib_error_set_handler(NULL
);
1505 pa_bool_t
pa_alsa_init_description(pa_proplist
*p
) {
1509 if (pa_device_init_description(p
))
1512 if ((s
= pa_proplist_gets(p
, "alsa.card_name"))) {
1513 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1517 if ((s
= pa_proplist_gets(p
, "alsa.name"))) {
1518 pa_proplist_sets(p
, PA_PROP_DEVICE_DESCRIPTION
, s
);
1525 void pa_alsa_init_proplist_card(pa_core
*c
, pa_proplist
*p
, int card
) {
1526 char *cn
, *lcn
, *dn
;
1529 pa_assert(card
>= 0);
1531 pa_proplist_setf(p
, "alsa.card", "%i", card
);
1533 if (snd_card_get_name(card
, &cn
) >= 0) {
1534 pa_proplist_sets(p
, "alsa.card_name", cn
);
1538 if (snd_card_get_longname(card
, &lcn
) >= 0) {
1539 pa_proplist_sets(p
, "alsa.long_card_name", lcn
);
1543 if ((dn
= pa_alsa_get_driver_name(card
))) {
1544 pa_proplist_sets(p
, "alsa.driver_name", dn
);
1549 pa_udev_get_info(c
, p
, card
);
1553 pa_hal_get_info(c
, p
, card
);
1557 void pa_alsa_init_proplist_pcm_info(pa_core
*c
, pa_proplist
*p
, snd_pcm_info_t
*pcm_info
) {
1559 static const char * const alsa_class_table
[SND_PCM_CLASS_LAST
+1] = {
1560 [SND_PCM_CLASS_GENERIC
] = "generic",
1561 [SND_PCM_CLASS_MULTI
] = "multi",
1562 [SND_PCM_CLASS_MODEM
] = "modem",
1563 [SND_PCM_CLASS_DIGITIZER
] = "digitizer"
1565 static const char * const class_table
[SND_PCM_CLASS_LAST
+1] = {
1566 [SND_PCM_CLASS_GENERIC
] = "sound",
1567 [SND_PCM_CLASS_MULTI
] = NULL
,
1568 [SND_PCM_CLASS_MODEM
] = "modem",
1569 [SND_PCM_CLASS_DIGITIZER
] = NULL
1571 static const char * const alsa_subclass_table
[SND_PCM_SUBCLASS_LAST
+1] = {
1572 [SND_PCM_SUBCLASS_GENERIC_MIX
] = "generic-mix",
1573 [SND_PCM_SUBCLASS_MULTI_MIX
] = "multi-mix"
1576 snd_pcm_class_t
class;
1577 snd_pcm_subclass_t subclass
;
1578 const char *n
, *id
, *sdn
;
1582 pa_assert(pcm_info
);
1584 pa_proplist_sets(p
, PA_PROP_DEVICE_API
, "alsa");
1586 class = snd_pcm_info_get_class(pcm_info
);
1587 if (class <= SND_PCM_CLASS_LAST
) {
1588 if (class_table
[class])
1589 pa_proplist_sets(p
, PA_PROP_DEVICE_CLASS
, class_table
[class]);
1590 if (alsa_class_table
[class])
1591 pa_proplist_sets(p
, "alsa.class", alsa_class_table
[class]);
1594 subclass
= snd_pcm_info_get_subclass(pcm_info
);
1595 if (subclass
<= SND_PCM_SUBCLASS_LAST
)
1596 if (alsa_subclass_table
[subclass
])
1597 pa_proplist_sets(p
, "alsa.subclass", alsa_subclass_table
[subclass
]);
1599 if ((n
= snd_pcm_info_get_name(pcm_info
)))
1600 pa_proplist_sets(p
, "alsa.name", n
);
1602 if ((id
= snd_pcm_info_get_id(pcm_info
)))
1603 pa_proplist_sets(p
, "alsa.id", id
);
1605 pa_proplist_setf(p
, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info
));
1606 if ((sdn
= snd_pcm_info_get_subdevice_name(pcm_info
)))
1607 pa_proplist_sets(p
, "alsa.subdevice_name", sdn
);
1609 pa_proplist_setf(p
, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info
));
1611 if ((card
= snd_pcm_info_get_card(pcm_info
)) >= 0)
1612 pa_alsa_init_proplist_card(c
, p
, card
);
1615 void pa_alsa_init_proplist_pcm(pa_core
*c
, pa_proplist
*p
, snd_pcm_t
*pcm
, snd_mixer_elem_t
*elem
) {
1616 snd_pcm_hw_params_t
*hwparams
;
1617 snd_pcm_info_t
*info
;
1620 snd_pcm_hw_params_alloca(&hwparams
);
1621 snd_pcm_info_alloca(&info
);
1623 if ((err
= snd_pcm_hw_params_current(pcm
, hwparams
)) < 0)
1624 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err
));
1627 if ((bits
= snd_pcm_hw_params_get_sbits(hwparams
)) >= 0)
1628 pa_proplist_setf(p
, "alsa.resolution_bits", "%i", bits
);
1632 pa_proplist_sets(p
, "alsa.mixer_element", snd_mixer_selem_get_name(elem
));
1634 if ((err
= snd_pcm_info(pcm
, info
)) < 0)
1635 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err
));
1637 pa_alsa_init_proplist_pcm_info(c
, p
, info
);
1640 void pa_alsa_init_proplist_ctl(pa_proplist
*p
, const char *name
) {
1643 snd_ctl_card_info_t
*info
;
1648 snd_ctl_card_info_alloca(&info
);
1650 if ((err
= snd_ctl_open(&ctl
, name
, 0)) < 0) {
1651 pa_log_warn("Error opening low-level control device '%s'", name
);
1655 if ((err
= snd_ctl_card_info(ctl
, info
)) < 0) {
1656 pa_log_warn("Control device %s card info: %s", name
, snd_strerror(err
));
1661 if ((t
= snd_ctl_card_info_get_mixername(info
)))
1662 pa_proplist_sets(p
, "alsa.mixer_name", t
);
1664 if ((t
= snd_ctl_card_info_get_components(info
)))
1665 pa_proplist_sets(p
, "alsa.components", t
);
1670 int pa_alsa_recover_from_poll(snd_pcm_t
*pcm
, int revents
) {
1671 snd_pcm_state_t state
;
1676 if (revents
& POLLERR
)
1677 pa_log_debug("Got POLLERR from ALSA");
1678 if (revents
& POLLNVAL
)
1679 pa_log_warn("Got POLLNVAL from ALSA");
1680 if (revents
& POLLHUP
)
1681 pa_log_warn("Got POLLHUP from ALSA");
1682 if (revents
& POLLPRI
)
1683 pa_log_warn("Got POLLPRI from ALSA");
1684 if (revents
& POLLIN
)
1685 pa_log_debug("Got POLLIN from ALSA");
1686 if (revents
& POLLOUT
)
1687 pa_log_debug("Got POLLOUT from ALSA");
1689 state
= snd_pcm_state(pcm
);
1690 pa_log_debug("PCM state is %s", snd_pcm_state_name(state
));
1692 /* Try to recover from this error */
1696 case SND_PCM_STATE_XRUN
:
1697 if ((err
= snd_pcm_recover(pcm
, -EPIPE
, 1)) != 0) {
1698 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err
));
1703 case SND_PCM_STATE_SUSPENDED
:
1704 if ((err
= snd_pcm_recover(pcm
, -ESTRPIPE
, 1)) != 0) {
1705 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err
));
1714 if ((err
= snd_pcm_prepare(pcm
)) < 0) {
1715 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err
));
1724 pa_rtpoll_item
* pa_alsa_build_pollfd(snd_pcm_t
*pcm
, pa_rtpoll
*rtpoll
) {
1726 struct pollfd
*pollfd
;
1727 pa_rtpoll_item
*item
;
1731 if ((n
= snd_pcm_poll_descriptors_count(pcm
)) < 0) {
1732 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n
));
1736 item
= pa_rtpoll_item_new(rtpoll
, PA_RTPOLL_NEVER
, (unsigned) n
);
1737 pollfd
= pa_rtpoll_item_get_pollfd(item
, NULL
);
1739 if ((err
= snd_pcm_poll_descriptors(pcm
, pollfd
, (unsigned) n
)) < 0) {
1740 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err
));
1741 pa_rtpoll_item_free(item
);
1748 snd_pcm_sframes_t
pa_alsa_safe_avail(snd_pcm_t
*pcm
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1749 snd_pcm_sframes_t n
;
1753 pa_assert(hwbuf_size
> 0);
1756 /* Some ALSA driver expose weird bugs, let's inform the user about
1757 * what is going on */
1759 n
= snd_pcm_avail(pcm
);
1764 k
= (size_t) n
* pa_frame_size(ss
);
1766 if (k
>= hwbuf_size
* 5 ||
1767 k
>= pa_bytes_per_second(ss
)*10) {
1770 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1771 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1772 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1774 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1777 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1780 /* Mhmm, let's try not to fail completely */
1781 n
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1787 int pa_alsa_safe_delay(snd_pcm_t
*pcm
, snd_pcm_sframes_t
*delay
, size_t hwbuf_size
, const pa_sample_spec
*ss
) {
1794 pa_assert(hwbuf_size
> 0);
1797 /* Some ALSA driver expose weird bugs, let's inform the user about
1798 * what is going on */
1800 if ((r
= snd_pcm_delay(pcm
, delay
)) < 0)
1803 k
= (ssize_t
) *delay
* (ssize_t
) pa_frame_size(ss
);
1805 abs_k
= k
>= 0 ? (size_t) k
: (size_t) -k
;
1807 if (abs_k
>= hwbuf_size
* 5 ||
1808 abs_k
>= pa_bytes_per_second(ss
)*10) {
1811 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1812 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1813 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1816 (unsigned long) (pa_bytes_to_usec(abs_k
, ss
) / PA_USEC_PER_MSEC
),
1819 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1822 /* Mhmm, let's try not to fail completely */
1824 *delay
= -(snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1826 *delay
= (snd_pcm_sframes_t
) (hwbuf_size
/ pa_frame_size(ss
));
1832 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
) {
1834 snd_pcm_uframes_t before
;
1841 pa_assert(hwbuf_size
> 0);
1846 r
= snd_pcm_mmap_begin(pcm
, areas
, offset
, frames
);
1851 k
= (size_t) *frames
* pa_frame_size(ss
);
1853 if (*frames
> before
||
1854 k
>= hwbuf_size
* 3 ||
1855 k
>= pa_bytes_per_second(ss
)*10)
1858 char *dn
= pa_alsa_get_driver_name_by_pcm(pcm
);
1859 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1860 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1862 (unsigned long) (pa_bytes_to_usec(k
, ss
) / PA_USEC_PER_MSEC
),
1865 pa_alsa_dump(PA_LOG_ERROR
, pcm
);
1871 char *pa_alsa_get_driver_name(int card
) {
1874 pa_assert(card
>= 0);
1876 t
= pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card
);
1883 n
= pa_xstrdup(pa_path_get_filename(m
));
1889 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t
*pcm
) {
1891 snd_pcm_info_t
* info
;
1892 snd_pcm_info_alloca(&info
);
1896 if (snd_pcm_info(pcm
, info
) < 0)
1899 if ((card
= snd_pcm_info_get_card(info
)) < 0)
1902 return pa_alsa_get_driver_name(card
);
1905 char *pa_alsa_get_reserve_name(const char *device
) {
1911 if ((t
= strchr(device
, ':')))
1914 if ((i
= snd_card_get_index(device
)) < 0) {
1917 if (pa_atoi(device
, &k
) < 0)
1923 return pa_sprintf_malloc("Audio%i", i
);
1926 pa_bool_t
pa_alsa_pcm_is_hw(snd_pcm_t
*pcm
) {
1927 snd_pcm_info_t
* info
;
1928 snd_pcm_info_alloca(&info
);
1932 if (snd_pcm_info(pcm
, info
) < 0)
1935 return snd_pcm_info_get_card(info
) >= 0;
1938 pa_bool_t
pa_alsa_pcm_is_modem(snd_pcm_t
*pcm
) {
1939 snd_pcm_info_t
* info
;
1940 snd_pcm_info_alloca(&info
);
1944 if (snd_pcm_info(pcm
, info
) < 0)
1947 return snd_pcm_info_get_class(info
) == SND_PCM_CLASS_MODEM
;
1950 PA_STATIC_TLS_DECLARE(cstrerror
, pa_xfree
);
1952 const char* pa_alsa_strerror(int errnum
) {
1953 const char *original
= NULL
;
1954 char *translated
, *t
;
1957 if ((t
= PA_STATIC_TLS_GET(cstrerror
)))
1960 original
= snd_strerror(errnum
);
1963 pa_snprintf(errbuf
, sizeof(errbuf
), "Unknown error %i", errnum
);
1967 if (!(translated
= pa_locale_to_utf8(original
))) {
1968 pa_log_warn("Unable to convert error string to locale, filtering.");
1969 translated
= pa_utf8_filter(original
);
1972 PA_STATIC_TLS_SET(cstrerror
, translated
);