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>
28 #include <asoundlib.h>
30 #include <pulse/sample.h>
31 #include <pulse/xmalloc.h>
32 #include <pulse/timeval.h>
33 #include <pulse/util.h>
34 #include <pulse/utf8.h>
36 #include <pulsecore/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/thread.h>
43 #include <pulsecore/conf-parser.h>
44 #include <pulsecore/core-rtclock.h>
46 #include "alsa-util.h"
47 #include "alsa-mixer.h"
50 #include "udev-util.h"
53 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
55 static const snd_pcm_format_t format_trans[] = {
56 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
57 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
58 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
59 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
60 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
61 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
62 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
63 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
64 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
65 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
66 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
67 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
68 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
71 static const pa_sample_format_t try_order[] = {
90 pa_assert(pcm_handle);
94 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
97 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
98 snd_pcm_format_description(format_trans[*f]),
99 pa_alsa_strerror(ret));
101 if (*f == PA_SAMPLE_FLOAT32BE)
102 *f = PA_SAMPLE_FLOAT32LE;
103 else if (*f == PA_SAMPLE_FLOAT32LE)
104 *f = PA_SAMPLE_FLOAT32BE;
105 else if (*f == PA_SAMPLE_S24BE)
106 *f = PA_SAMPLE_S24LE;
107 else if (*f == PA_SAMPLE_S24LE)
108 *f = PA_SAMPLE_S24BE;
109 else if (*f == PA_SAMPLE_S24_32BE)
110 *f = PA_SAMPLE_S24_32LE;
111 else if (*f == PA_SAMPLE_S24_32LE)
112 *f = PA_SAMPLE_S24_32BE;
113 else if (*f == PA_SAMPLE_S16BE)
114 *f = PA_SAMPLE_S16LE;
115 else if (*f == PA_SAMPLE_S16LE)
116 *f = PA_SAMPLE_S16BE;
117 else if (*f == PA_SAMPLE_S32BE)
118 *f = PA_SAMPLE_S32LE;
119 else if (*f == PA_SAMPLE_S32LE)
120 *f = PA_SAMPLE_S32BE;
124 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
127 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
128 snd_pcm_format_description(format_trans[*f]),
129 pa_alsa_strerror(ret));
133 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
136 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
139 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
140 snd_pcm_format_description(format_trans[*f]),
141 pa_alsa_strerror(ret));
147 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
151 pa_assert(pcm_handle);
156 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
159 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
162 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
163 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
172 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
175 pa_assert(pcm_handle);
178 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
179 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
186 /* Set the hardware parameters of the given ALSA device. Returns the
187 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
188 int pa_alsa_set_hw_params(
189 snd_pcm_t *pcm_handle,
191 snd_pcm_uframes_t *period_size,
192 snd_pcm_uframes_t *buffer_size,
193 snd_pcm_uframes_t tsched_size,
196 bool require_exact_channel_number) {
199 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
201 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
202 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
203 bool _use_mmap = use_mmap && *use_mmap;
204 bool _use_tsched = use_tsched && *use_tsched;
205 pa_sample_spec _ss = *ss;
207 pa_assert(pcm_handle);
210 snd_pcm_hw_params_alloca(&hwparams);
211 snd_pcm_hw_params_alloca(&hwparams_copy);
213 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
214 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
218 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
219 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
225 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
227 /* mmap() didn't work, fall back to interleaved */
229 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
230 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
237 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
238 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
245 if (!pa_alsa_pcm_is_hw(pcm_handle))
248 /* The PCM pointer is only updated with period granularity */
249 if (snd_pcm_hw_params_is_batch(hwparams)) {
250 pa_log_info("Disabling tsched mode since BATCH flag is set");
254 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
257 /* try to disable period wakeups if hardware can do so */
258 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
260 if ((ret = snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, false)) < 0)
261 /* don't bail, keep going with default mode with period wakeups */
262 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret));
264 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
266 pa_log_info("cannot disable ALSA period wakeups");
270 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
273 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
274 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
278 /* We ignore very small sampling rate deviations */
279 if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
282 if (require_exact_channel_number) {
283 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
284 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
288 unsigned int c = _ss.channels;
290 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
291 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
298 if (_use_tsched && tsched_size > 0) {
299 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
300 _period_size = _buffer_size;
302 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
303 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
306 if (_buffer_size > 0 || _period_size > 0) {
307 snd_pcm_uframes_t max_frames = 0;
309 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
310 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
312 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
314 /* Some ALSA drivers really don't like if we set the buffer
315 * size first and the number of periods second (which would
316 * make a lot more sense to me). So, try a few combinations
317 * before we give up. */
319 if (_buffer_size > 0 && _period_size > 0) {
320 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
322 /* First try: set buffer size first, followed by period size */
323 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
324 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
325 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
326 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
330 /* Second try: set period size first, followed by buffer size */
331 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
332 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
333 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
334 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);
339 if (_buffer_size > 0) {
340 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
342 /* Third try: set only buffer size */
343 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
344 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
345 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);
350 if (_period_size > 0) {
351 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
353 /* Fourth try: set only period size */
354 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
355 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
356 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);
362 pa_log_debug("Set neither period nor buffer size.");
364 /* Last chance, set nothing */
365 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
366 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
372 if (ss->rate != _ss.rate)
373 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
375 if (ss->channels != _ss.channels)
376 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
378 if (ss->format != _ss.format)
379 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(_ss.format));
381 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
382 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
386 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
387 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
391 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
392 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
393 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
397 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
399 unsigned int no_wakeup;
400 /* see if period wakeups were disabled */
401 snd_pcm_hw_params_get_period_wakeup(pcm_handle, hwparams, &no_wakeup);
403 pa_log_info("ALSA period wakeups disabled");
405 pa_log_info("ALSA period wakeups were not disabled");
410 ss->channels = _ss.channels;
411 ss->format = _ss.format;
413 pa_assert(_period_size > 0);
414 pa_assert(_buffer_size > 0);
417 *buffer_size = _buffer_size;
420 *period_size = _period_size;
423 *use_mmap = _use_mmap;
426 *use_tsched = _use_tsched;
436 // FIXME : Fix added for VT avsync issue + Reducing voip HW buff size
437 #define VOIP_WIDE_BAND 16000
438 #define VOIP_WB_AVAIL_MIN 160
439 #define VOIP_NB_AVAIL_MIN 80
443 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event, int start_threshold,int sampling_rate) {
445 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
447 snd_pcm_sw_params_t *swparams;
448 snd_pcm_uframes_t boundary;
454 if (start_threshold > 0) {
455 avail_min = start_threshold;
458 if (pa_alsa_pcm_is_voip(pcm)) {
459 // FIXME : Fix added for VT avsync issue + Reducing voip HW buff size
460 avail_min = (sampling_rate == VOIP_WIDE_BAND) ? VOIP_WB_AVAIL_MIN :VOIP_NB_AVAIL_MIN;
463 snd_pcm_sw_params_alloca(&swparams);
465 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
466 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
470 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
471 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
475 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
476 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
480 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
481 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
486 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
487 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
491 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (start_threshold > 0)? (snd_pcm_uframes_t)start_threshold : avail_min)) < 0) {
492 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
496 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
497 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
501 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
502 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
507 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
508 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
512 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
513 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
520 snd_pcm_t *pa_alsa_open_by_device_id_auto(
529 snd_pcm_uframes_t *period_size,
530 snd_pcm_uframes_t *buffer_size,
531 snd_pcm_uframes_t tsched_size,
534 pa_alsa_profile_set *ps,
535 pa_alsa_mapping **mapping) {
538 snd_pcm_t *pcm_handle;
548 /* First we try to find a device string with a superset of the
549 * requested channel map. We iterate through our device table from
550 * top to bottom and take the first that matches. If we didn't
551 * find a working device that way, we iterate backwards, and check
552 * all devices that do not provide a superset of the requested
555 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
556 if (!pa_channel_map_superset(&m->channel_map, map))
559 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
561 pcm_handle = pa_alsa_open_by_device_id_mapping(
585 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
586 if (pa_channel_map_superset(&m->channel_map, map))
589 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
591 pcm_handle = pa_alsa_open_by_device_id_mapping(
615 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
616 d = pa_sprintf_malloc("hw:%s", dev_id);
617 pa_log_debug("Trying %s as last resort...", d);
618 pcm_handle = pa_alsa_open_by_device_string(
635 if (pcm_handle && mapping)
641 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
650 snd_pcm_uframes_t *period_size,
651 snd_pcm_uframes_t *buffer_size,
652 snd_pcm_uframes_t tsched_size,
655 pa_alsa_mapping *m) {
657 snd_pcm_t *pcm_handle;
658 pa_sample_spec try_ss;
659 pa_channel_map try_map;
667 try_ss.channels = m->channel_map.channels;
668 try_ss.rate = ss->rate;
669 try_ss.format = ss->format;
670 try_map = m->channel_map;
672 pcm_handle = pa_alsa_open_by_template(
687 pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
694 pa_assert(map->channels == ss->channels);
699 snd_pcm_t *pa_alsa_open_by_device_string(
708 snd_pcm_uframes_t *period_size,
709 snd_pcm_uframes_t *buffer_size,
710 snd_pcm_uframes_t tsched_size,
713 bool require_exact_channel_number) {
717 snd_pcm_t *pcm_handle;
718 bool reformat = false;
724 d = pa_xstrdup(device);
727 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
729 if ((err = snd_pcm_open(&pcm_handle, d, mode,
731 SND_PCM_NO_AUTO_RESAMPLE|
732 SND_PCM_NO_AUTO_CHANNELS|
733 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
734 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
738 pa_log_debug("Managed to open %s", d);
740 if ((err = pa_alsa_set_hw_params(
748 require_exact_channel_number)) < 0) {
752 snd_pcm_close(pcm_handle);
756 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
757 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
760 t = pa_sprintf_malloc("plug:%s", d);
765 snd_pcm_close(pcm_handle);
769 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
770 snd_pcm_close(pcm_handle);
780 if (ss->channels != map->channels)
781 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
792 snd_pcm_t *pa_alsa_open_by_template(
802 snd_pcm_uframes_t *period_size,
803 snd_pcm_uframes_t *buffer_size,
804 snd_pcm_uframes_t tsched_size,
807 bool require_exact_channel_number) {
809 snd_pcm_t *pcm_handle;
812 for (i = template; *i; i++) {
815 d = pa_replace(*i, "%f", dev_id);
817 pcm_handle = pa_alsa_open_by_device_string(
831 require_exact_channel_number);
842 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
848 pa_assert_se(snd_output_buffer_open(&out) == 0);
850 if ((err = snd_pcm_dump(pcm, out)) < 0)
851 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
854 snd_output_buffer_string(out, &s);
855 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
858 pa_assert_se(snd_output_close(out) == 0);
861 void pa_alsa_dump_status(snd_pcm_t *pcm) {
864 snd_pcm_status_t *status;
869 snd_pcm_status_alloca(&status);
871 if ((err = snd_output_buffer_open(&out)) < 0) {
872 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
876 if ((err = snd_pcm_status(pcm, status)) < 0) {
877 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
881 if ((err = snd_pcm_status_dump(status, out)) < 0) {
882 pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err));
886 snd_output_buffer_string(out, &s);
887 pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s));
891 snd_output_close(out);
894 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
898 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
902 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
909 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
911 void pa_alsa_refcnt_inc(void) {
912 /* This is not really thread safe, but we do our best */
914 if (pa_atomic_inc(&n_error_handler_installed) == 0)
915 snd_lib_error_set_handler(alsa_error_handler);
918 void pa_alsa_refcnt_dec(void) {
921 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
924 snd_lib_error_set_handler(NULL);
925 snd_config_update_free_global();
929 bool pa_alsa_init_description(pa_proplist *p) {
933 if (pa_device_init_description(p))
936 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
937 d = pa_proplist_gets(p, "alsa.name");
942 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
945 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
947 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
952 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
956 pa_assert(card >= 0);
958 pa_proplist_setf(p, "alsa.card", "%i", card);
960 if (snd_card_get_name(card, &cn) >= 0) {
961 pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
965 if (snd_card_get_longname(card, &lcn) >= 0) {
966 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
970 if ((dn = pa_alsa_get_driver_name(card))) {
971 pa_proplist_sets(p, "alsa.driver_name", dn);
976 pa_udev_get_info(card, p);
980 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
982 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
983 [SND_PCM_CLASS_GENERIC] = "generic",
984 [SND_PCM_CLASS_MULTI] = "multi",
985 [SND_PCM_CLASS_MODEM] = "modem",
986 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
988 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
989 [SND_PCM_CLASS_GENERIC] = "sound",
990 [SND_PCM_CLASS_MULTI] = NULL,
991 [SND_PCM_CLASS_MODEM] = "modem",
992 [SND_PCM_CLASS_DIGITIZER] = NULL
994 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
995 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
996 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
999 snd_pcm_class_t class;
1000 snd_pcm_subclass_t subclass;
1001 const char *n, *id, *sdn;
1005 pa_assert(pcm_info);
1007 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
1009 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
1010 if (class_table[class])
1011 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
1012 if (alsa_class_table[class])
1013 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
1016 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
1017 if (alsa_subclass_table[subclass])
1018 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
1020 if ((n = snd_pcm_info_get_name(pcm_info))) {
1021 char *t = pa_xstrdup(n);
1022 pa_proplist_sets(p, "alsa.name", pa_strip(t));
1026 if ((id = snd_pcm_info_get_id(pcm_info)))
1027 pa_proplist_sets(p, "alsa.id", id);
1029 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
1030 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
1031 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
1033 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
1035 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
1036 pa_alsa_init_proplist_card(c, p, card);
1039 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
1040 snd_pcm_hw_params_t *hwparams;
1041 snd_pcm_info_t *info;
1044 snd_pcm_hw_params_alloca(&hwparams);
1045 snd_pcm_info_alloca(&info);
1047 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
1048 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
1051 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
1052 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
1055 if ((err = snd_pcm_info(pcm, info)) < 0)
1056 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1058 pa_alsa_init_proplist_pcm_info(c, p, info);
1061 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1064 snd_ctl_card_info_t *info;
1069 snd_ctl_card_info_alloca(&info);
1071 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1072 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1076 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1077 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1082 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1083 pa_proplist_sets(p, "alsa.mixer_name", t);
1085 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1086 pa_proplist_sets(p, "alsa.components", t);
1091 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1092 snd_pcm_state_t state;
1097 if (revents & POLLERR)
1098 pa_log_debug("Got POLLERR from ALSA");
1099 if (revents & POLLNVAL)
1100 pa_log_warn("Got POLLNVAL from ALSA");
1101 if (revents & POLLHUP)
1102 pa_log_warn("Got POLLHUP from ALSA");
1103 if (revents & POLLPRI)
1104 pa_log_warn("Got POLLPRI from ALSA");
1105 if (revents & POLLIN)
1106 pa_log_debug("Got POLLIN from ALSA");
1107 if (revents & POLLOUT)
1108 pa_log_debug("Got POLLOUT from ALSA");
1110 state = snd_pcm_state(pcm);
1111 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1113 /* Try to recover from this error */
1117 case SND_PCM_STATE_XRUN:
1118 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1119 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1124 case SND_PCM_STATE_SUSPENDED:
1125 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1126 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1135 if ((err = snd_pcm_prepare(pcm)) < 0) {
1136 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1145 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1147 struct pollfd *pollfd;
1148 pa_rtpoll_item *item;
1152 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1153 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1157 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1158 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1160 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1161 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1162 pa_rtpoll_item_free(item);
1169 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1170 snd_pcm_sframes_t n;
1174 pa_assert(hwbuf_size > 0);
1177 /* Some ALSA driver expose weird bugs, let's inform the user about
1178 * what is going on */
1180 n = snd_pcm_avail(pcm);
1185 k = (size_t) n * pa_frame_size(ss);
1187 if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1188 k >= pa_bytes_per_second(ss)*10)) {
1191 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1192 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1193 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1195 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1198 pa_alsa_dump(PA_LOG_ERROR, pcm);
1201 /* Mhmm, let's try not to fail completely */
1202 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1208 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_status_t *status, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss,
1213 snd_pcm_sframes_t avail = 0;
1217 pa_assert(hwbuf_size > 0);
1220 /* Some ALSA driver expose weird bugs, let's inform the user about
1221 * what is going on. We're going to get both the avail and delay values so
1222 * that we can compare and check them for capture.
1223 * This is done with snd_pcm_status() which provides
1224 * avail, delay and timestamp values in a single kernel call to improve
1225 * timer-based scheduling */
1227 if ((err = snd_pcm_status(pcm, status)) < 0)
1230 avail = snd_pcm_status_get_avail(status);
1231 *delay = snd_pcm_status_get_delay(status);
1233 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1235 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1237 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1238 abs_k >= pa_bytes_per_second(ss)*10)) {
1241 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1242 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1243 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1246 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1249 pa_alsa_dump(PA_LOG_ERROR, pcm);
1252 /* Mhmm, let's try not to fail completely */
1254 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1256 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1260 abs_k = (size_t) avail * pa_frame_size(ss);
1262 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1263 abs_k >= pa_bytes_per_second(ss)*10)) {
1266 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1267 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1268 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1270 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1273 pa_alsa_dump(PA_LOG_ERROR, pcm);
1276 /* Mhmm, let's try not to fail completely */
1277 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1280 if (PA_UNLIKELY(*delay < avail)) {
1282 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1283 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1284 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1285 (unsigned long) *delay,
1286 (unsigned long) avail,
1289 pa_alsa_dump(PA_LOG_ERROR, pcm);
1300 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) {
1302 snd_pcm_uframes_t before;
1309 pa_assert(hwbuf_size > 0);
1314 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1319 k = (size_t) *frames * pa_frame_size(ss);
1321 if (PA_UNLIKELY(*frames > before ||
1322 k >= hwbuf_size * 3 ||
1323 k >= pa_bytes_per_second(ss)*10))
1325 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1326 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1327 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1329 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1332 pa_alsa_dump(PA_LOG_ERROR, pcm);
1338 char *pa_alsa_get_driver_name(int card) {
1341 pa_assert(card >= 0);
1343 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1350 n = pa_xstrdup(pa_path_get_filename(m));
1356 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1358 snd_pcm_info_t* info;
1359 snd_pcm_info_alloca(&info);
1363 if (snd_pcm_info(pcm, info) < 0)
1366 if ((card = snd_pcm_info_get_card(info)) < 0)
1369 return pa_alsa_get_driver_name(card);
1372 char *pa_alsa_get_reserve_name(const char *device) {
1378 if ((t = strchr(device, ':')))
1381 if ((i = snd_card_get_index(device)) < 0) {
1384 if (pa_atoi(device, &k) < 0)
1390 return pa_sprintf_malloc("Audio%i", i);
1393 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1394 static unsigned int all_rates[] = { 8000, 11025, 12000,
1395 16000, 22050, 24000,
1396 32000, 44100, 48000,
1397 64000, 88200, 96000,
1398 128000, 176400, 192000,
1400 bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
1401 snd_pcm_hw_params_t *hwparams;
1402 unsigned int i, j, n, *rates = NULL;
1405 snd_pcm_hw_params_alloca(&hwparams);
1407 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1408 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1412 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1413 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1414 supported[i] = true;
1420 rates = pa_xnew(unsigned int, n + 1);
1422 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1424 rates[j++] = all_rates[i];
1429 rates = pa_xnew(unsigned int, 2);
1431 rates[0] = fallback_rate;
1432 if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1433 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1444 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1445 snd_pcm_info_t* info;
1446 snd_pcm_info_alloca(&info);
1450 if (snd_pcm_info(pcm, info) < 0)
1453 return snd_pcm_info_get_card(info) >= 0;
1456 bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1457 snd_pcm_info_t* info;
1458 snd_pcm_info_alloca(&info);
1462 if (snd_pcm_info(pcm, info) < 0)
1465 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1469 bool pa_alsa_pcm_is_voip(snd_pcm_t *pcm) {
1470 const char *id = NULL;
1471 snd_pcm_info_t* info;
1472 snd_pcm_info_alloca(&info);
1476 if (snd_pcm_info(pcm, info) < 0)
1479 if (!(id = snd_pcm_info_get_id(info)))
1482 if(!strncmp(id, "VoIP",4))
1489 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1491 const char* pa_alsa_strerror(int errnum) {
1492 const char *original = NULL;
1493 char *translated, *t;
1496 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1499 original = snd_strerror(errnum);
1502 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1506 if (!(translated = pa_locale_to_utf8(original))) {
1507 pa_log_warn("Unable to convert error string to locale, filtering.");
1508 translated = pa_utf8_filter(original);
1511 PA_STATIC_TLS_SET(cstrerror, translated);
1516 bool pa_alsa_may_tsched(bool want) {
1521 if (!pa_rtclock_hrtimer()) {
1522 /* We cannot depend on being woken up in time when the timers
1523 are inaccurate, so let's fallback to classic IO based playback
1525 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1528 if (pa_running_in_vm()) {
1529 /* We cannot depend on being woken up when we ask for in a VM,
1530 * so let's fallback to classic IO based playback then. */
1531 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1538 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
1539 snd_ctl_elem_id_t *id;
1541 snd_ctl_elem_id_alloca(&id);
1542 snd_ctl_elem_id_clear(id);
1543 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
1544 snd_ctl_elem_id_set_name(id, jack_name);
1546 return snd_hctl_find_elem(hctl, id);
1549 snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
1550 snd_ctl_elem_id_t *id;
1552 /* See if we can find the ELD control */
1553 snd_ctl_elem_id_alloca(&id);
1554 snd_ctl_elem_id_clear(id);
1555 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1556 snd_ctl_elem_id_set_name(id, "ELD");
1557 snd_ctl_elem_id_set_device(id, device);
1559 return snd_hctl_find_elem(hctl, id);
1562 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
1568 if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1569 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1573 /* Note: The hctl handle returned should not be freed.
1574 It is closed/freed by alsa-lib on snd_mixer_close/free */
1575 if (hctl && (err = snd_mixer_get_hctl(mixer, dev, hctl)) < 0) {
1576 pa_log_info("Unable to get hctl of mixer %s: %s", dev, pa_alsa_strerror(err));
1580 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1581 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1585 if ((err = snd_mixer_load(mixer)) < 0) {
1586 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1590 pa_log_info("Successfully attached to mixer '%s'", dev);
1594 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl) {
1598 snd_pcm_info_t* info;
1599 snd_pcm_info_alloca(&info);
1601 if ((err = snd_mixer_open(&m, 0)) < 0) {
1602 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1606 /* Then, try by card index */
1607 md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1608 if (prepare_mixer(m, md, hctl) >= 0) {
1624 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl) {
1628 snd_pcm_info_t* info;
1629 snd_pcm_info_alloca(&info);
1633 if ((err = snd_mixer_open(&m, 0)) < 0) {
1634 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1638 /* First, try by name */
1639 if ((dev = snd_pcm_name(pcm)))
1640 if (prepare_mixer(m, dev, hctl) >= 0) {
1642 *ctl_device = pa_xstrdup(dev);
1647 /* Then, try by card index */
1648 if (snd_pcm_info(pcm, info) >= 0) {
1652 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1654 md = pa_sprintf_malloc("hw:%i", card_idx);
1656 if (!dev || !pa_streq(dev, md))
1657 if (prepare_mixer(m, md, hctl) >= 0) {
1675 int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
1677 /* The ELD format is specific to HDA Intel sound cards and defined in the
1678 HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1680 snd_hctl_elem_t *elem;
1681 snd_ctl_elem_info_t *info;
1682 snd_ctl_elem_value_t *value;
1684 unsigned int eldsize, mnl;
1686 pa_assert(eld != NULL);
1688 /* See if we can find the ELD control */
1689 elem = pa_alsa_find_eld_ctl(hctl, device);
1691 pa_log_debug("No ELD info control found (for device=%d)", device);
1695 /* Does it have any contents? */
1696 snd_ctl_elem_info_alloca(&info);
1697 snd_ctl_elem_value_alloca(&value);
1698 if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1699 (err = snd_hctl_elem_read(elem, value)) < 0) {
1700 pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1704 eldsize = snd_ctl_elem_info_get_count(info);
1705 elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1706 if (elddata == NULL || eldsize == 0) {
1707 pa_log_debug("ELD info empty (for device=%d)", device);
1710 if (eldsize < 20 || eldsize > 256) {
1711 pa_log_debug("ELD info has wrong size (for device=%d)", device);
1715 /* Try to fetch monitor name */
1716 mnl = elddata[4] & 0x1f;
1717 if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
1718 pa_log_debug("No monitor name in ELD info (for device=%d)", device);
1721 memcpy(eld->monitor_name, &elddata[20], mnl);
1722 eld->monitor_name[mnl] = '\0';
1724 pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
1730 int pa_alsa_set_mixer_control(const char *ctl_name, int val)
1733 snd_ctl_elem_value_t *control;
1734 snd_ctl_elem_id_t *id;
1735 snd_ctl_elem_info_t *info;
1736 snd_ctl_elem_type_t type;
1738 char *card_name = NULL;
1739 int ret = 0, count = 0, i = 0;
1741 snd_card_get_name(0, &card_name);
1743 card_name = strdup("default");
1745 ret = snd_ctl_open(&handle, card_name, 0);
1747 pa_log_error("snd_ctl_open error, card: %s: %s", card_name, snd_strerror(ret));
1748 if (card_name != NULL) {
1754 if (card_name != NULL) {
1760 snd_ctl_elem_id_alloca(&id);
1761 snd_ctl_elem_info_alloca(&info);
1762 snd_ctl_elem_value_alloca(&control);
1764 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
1765 snd_ctl_elem_id_set_name(id, ctl_name);
1767 snd_ctl_elem_info_set_id(info, id);
1768 if(snd_ctl_elem_info(handle, info) < 0 ) {
1769 pa_log_error("Cannot find control element: %s", ctl_name);
1772 snd_ctl_elem_info_get_id(info, id);
1774 type = snd_ctl_elem_info_get_type(info);
1775 count = snd_ctl_elem_info_get_count(info);
1777 snd_ctl_elem_value_set_id(control, id);
1779 snd_ctl_elem_read(handle, control);
1781 pa_log_debug("type(%d), count(%d): ", type, count);
1784 case SND_CTL_ELEM_TYPE_BOOLEAN:
1785 for (i = 0; i < count; i++)
1786 snd_ctl_elem_value_set_boolean(control, i, val);
1788 case SND_CTL_ELEM_TYPE_INTEGER:
1789 for (i = 0; i < count; i++)
1790 snd_ctl_elem_value_set_integer(control, i,val);
1792 case SND_CTL_ELEM_TYPE_ENUMERATED:
1793 for (i = 0; i < count; i++)
1794 snd_ctl_elem_value_set_enumerated(control, i,val);
1798 pa_log_warn("unsupported control element type");
1802 snd_ctl_elem_write(handle, control);
1804 snd_ctl_close(handle);
1809 pa_log_error("Error");
1810 snd_ctl_close(handle);