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, see <http://www.gnu.org/licenses/>.
25
#include <sys/types.h>
26
#include <asoundlib.h>
28
#include <pulse/sample.h>
29
#include <pulse/xmalloc.h>
30
#include <pulse/timeval.h>
31
#include <pulse/util.h>
32
#include <pulse/utf8.h>
34
#include <pulsecore/i18n.h>
35
#include <pulsecore/log.h>
36
#include <pulsecore/macro.h>
37
#include <pulsecore/core-util.h>
38
#include <pulsecore/atomic.h>
39
#include <pulsecore/core-error.h>
40
#include <pulsecore/thread.h>
41
#include <pulsecore/conf-parser.h>
42
#include <pulsecore/core-rtclock.h>
44
#include "alsa-util.h"
45
#include "alsa-mixer.h"
48
#include "udev-util.h"
51
static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
53
static const snd_pcm_format_t format_trans[] = {
54
[PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
55
[PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
56
[PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
57
[PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
58
[PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
59
[PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
60
[PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
61
[PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
62
[PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
63
[PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
64
[PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
65
[PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
66
[PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
69
static const pa_sample_format_t try_order[] = {
88
pa_assert(pcm_handle);
92
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
95
pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
96
snd_pcm_format_description(format_trans[*f]),
97
pa_alsa_strerror(ret));
99
if (*f == PA_SAMPLE_FLOAT32BE)
100
*f = PA_SAMPLE_FLOAT32LE;
101
else if (*f == PA_SAMPLE_FLOAT32LE)
102
*f = PA_SAMPLE_FLOAT32BE;
103
else if (*f == PA_SAMPLE_S24BE)
104
*f = PA_SAMPLE_S24LE;
105
else if (*f == PA_SAMPLE_S24LE)
106
*f = PA_SAMPLE_S24BE;
107
else if (*f == PA_SAMPLE_S24_32BE)
108
*f = PA_SAMPLE_S24_32LE;
109
else if (*f == PA_SAMPLE_S24_32LE)
110
*f = PA_SAMPLE_S24_32BE;
111
else if (*f == PA_SAMPLE_S16BE)
112
*f = PA_SAMPLE_S16LE;
113
else if (*f == PA_SAMPLE_S16LE)
114
*f = PA_SAMPLE_S16BE;
115
else if (*f == PA_SAMPLE_S32BE)
116
*f = PA_SAMPLE_S32LE;
117
else if (*f == PA_SAMPLE_S32LE)
118
*f = PA_SAMPLE_S32BE;
122
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
125
pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
126
snd_pcm_format_description(format_trans[*f]),
127
pa_alsa_strerror(ret));
131
for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
134
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
137
pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
138
snd_pcm_format_description(format_trans[*f]),
139
pa_alsa_strerror(ret));
145
static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
149
pa_assert(pcm_handle);
154
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
157
if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
160
if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
161
pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
170
static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
173
pa_assert(pcm_handle);
176
if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
177
pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
184
/* Set the hardware parameters of the given ALSA device. Returns the
185
* selected fragment settings in *buffer_size and *period_size. Determine
186
* whether mmap and tsched mode can be enabled. */
187
int pa_alsa_set_hw_params(
188
snd_pcm_t *pcm_handle,
190
snd_pcm_uframes_t *period_size,
191
snd_pcm_uframes_t *buffer_size,
192
snd_pcm_uframes_t tsched_size,
195
bool require_exact_channel_number) {
198
snd_pcm_hw_params_t *hwparams, *hwparams_copy;
200
snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
201
snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
202
bool _use_mmap = use_mmap && *use_mmap;
203
bool _use_tsched = use_tsched && *use_tsched;
204
pa_sample_spec _ss = *ss;
206
pa_assert(pcm_handle);
209
snd_pcm_hw_params_alloca(&hwparams);
210
snd_pcm_hw_params_alloca(&hwparams_copy);
212
if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
213
pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
217
if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
218
pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
224
if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
226
/* mmap() didn't work, fall back to interleaved */
228
if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
229
pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
236
} else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
237
pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
244
if (!pa_alsa_pcm_is_hw(pcm_handle))
247
/* The PCM pointer is only updated with period granularity */
248
if (snd_pcm_hw_params_is_batch(hwparams)) {
249
pa_log_info("Disabling tsched mode since BATCH flag is set");
253
#if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
256
/* try to disable period wakeups if hardware can do so */
257
if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
259
if ((ret = snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, false)) < 0)
260
/* don't bail, keep going with default mode with period wakeups */
261
pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret));
263
pa_log_info("Trying to disable ALSA period wakeups, using timers only");
265
pa_log_info("Cannot disable ALSA period wakeups");
269
if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
272
if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
273
pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
277
/* We ignore very small sampling rate deviations */
278
if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
281
if (require_exact_channel_number) {
282
if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
283
pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
287
unsigned int c = _ss.channels;
289
if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
290
pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
297
if (_use_tsched && tsched_size > 0) {
298
_buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
299
_period_size = _buffer_size;
301
_period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
302
_buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
305
if (_buffer_size > 0 || _period_size > 0) {
306
snd_pcm_uframes_t max_frames = 0;
308
if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
309
pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
311
pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
313
/* Some ALSA drivers really don't like if we set the buffer
314
* size first and the number of periods second (which would
315
* make a lot more sense to me). So, try a few combinations
316
* before we give up. */
318
if (_buffer_size > 0 && _period_size > 0) {
319
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
321
/* First try: set buffer size first, followed by period size */
322
if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
323
set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
324
snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
325
pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
329
snd_pcm_hw_params_copy(hwparams_copy, hwparams);
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;
435
int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
436
snd_pcm_sw_params_t *swparams;
437
snd_pcm_uframes_t boundary;
442
snd_pcm_sw_params_alloca(&swparams);
444
if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
445
pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
449
if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
450
pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
454
if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
455
pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
459
if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
460
pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
464
if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
465
pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
469
if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
470
pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
474
if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
475
pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
479
if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
480
pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
487
snd_pcm_t *pa_alsa_open_by_device_id_auto(
493
snd_pcm_uframes_t *period_size,
494
snd_pcm_uframes_t *buffer_size,
495
snd_pcm_uframes_t tsched_size,
498
pa_alsa_profile_set *ps,
499
pa_alsa_mapping **mapping) {
502
snd_pcm_t *pcm_handle;
512
/* First we try to find a device string with a superset of the
513
* requested channel map. We iterate through our device table from
514
* top to bottom and take the first that matches. If we didn't
515
* find a working device that way, we iterate backwards, and check
516
* all devices that do not provide a superset of the requested
519
PA_HASHMAP_FOREACH(m, ps->mappings, state) {
520
if (!pa_channel_map_superset(&m->channel_map, map))
523
pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
525
pcm_handle = pa_alsa_open_by_device_id_mapping(
546
PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
547
if (pa_channel_map_superset(&m->channel_map, map))
550
pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
552
pcm_handle = pa_alsa_open_by_device_id_mapping(
573
/* OK, we didn't find any good device, so let's try the raw hw: stuff */
574
d = pa_sprintf_malloc("hw:%s", dev_id);
575
pa_log_debug("Trying %s as last resort...", d);
576
pcm_handle = pa_alsa_open_by_device_string(
590
if (pcm_handle && mapping)
596
snd_pcm_t *pa_alsa_open_by_device_id_mapping(
602
snd_pcm_uframes_t *period_size,
603
snd_pcm_uframes_t *buffer_size,
604
snd_pcm_uframes_t tsched_size,
607
pa_alsa_mapping *m) {
609
snd_pcm_t *pcm_handle;
610
pa_sample_spec try_ss;
611
pa_channel_map try_map;
619
try_ss.channels = m->channel_map.channels;
620
try_ss.rate = ss->rate;
621
try_ss.format = ss->format;
622
try_map = m->channel_map;
624
pcm_handle = pa_alsa_open_by_template(
636
pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
643
pa_assert(map->channels == ss->channels);
648
snd_pcm_t *pa_alsa_open_by_device_string(
654
snd_pcm_uframes_t *period_size,
655
snd_pcm_uframes_t *buffer_size,
656
snd_pcm_uframes_t tsched_size,
659
bool require_exact_channel_number) {
663
snd_pcm_t *pcm_handle;
664
bool reformat = false;
670
d = pa_xstrdup(device);
673
pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
675
if ((err = snd_pcm_open(&pcm_handle, d, mode,
677
SND_PCM_NO_AUTO_RESAMPLE|
678
SND_PCM_NO_AUTO_CHANNELS|
679
(reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
680
pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
684
pa_log_debug("Managed to open %s", d);
686
if ((err = pa_alsa_set_hw_params(
694
require_exact_channel_number)) < 0) {
699
snd_pcm_close(pcm_handle);
703
/* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
704
if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
707
t = pa_sprintf_malloc("plug:%s", d);
713
snd_pcm_close(pcm_handle);
717
pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
718
snd_pcm_close(pcm_handle);
728
if (ss->channels != map->channels)
729
pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
740
snd_pcm_t *pa_alsa_open_by_template(
747
snd_pcm_uframes_t *period_size,
748
snd_pcm_uframes_t *buffer_size,
749
snd_pcm_uframes_t tsched_size,
752
bool require_exact_channel_number) {
754
snd_pcm_t *pcm_handle;
757
for (i = template; *i; i++) {
760
d = pa_replace(*i, "%f", dev_id);
762
pcm_handle = pa_alsa_open_by_device_string(
773
require_exact_channel_number);
784
void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
790
pa_assert_se(snd_output_buffer_open(&out) == 0);
792
if ((err = snd_pcm_dump(pcm, out)) < 0)
793
pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
796
snd_output_buffer_string(out, &s);
797
pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
800
pa_assert_se(snd_output_close(out) == 0);
803
void pa_alsa_dump_status(snd_pcm_t *pcm) {
806
snd_pcm_status_t *status;
811
snd_pcm_status_alloca(&status);
813
if ((err = snd_output_buffer_open(&out)) < 0) {
814
pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
818
if ((err = snd_pcm_status(pcm, status)) < 0) {
819
pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
823
if ((err = snd_pcm_status_dump(status, out)) < 0) {
824
pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err));
828
snd_output_buffer_string(out, &s);
829
pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s));
833
snd_output_close(out);
836
static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
840
alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
844
pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
851
static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
853
void pa_alsa_refcnt_inc(void) {
854
/* This is not really thread safe, but we do our best */
856
if (pa_atomic_inc(&n_error_handler_installed) == 0)
857
snd_lib_error_set_handler(alsa_error_handler);
860
void pa_alsa_refcnt_dec(void) {
863
pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
866
snd_lib_error_set_handler(NULL);
867
snd_config_update_free_global();
871
bool pa_alsa_init_description(pa_proplist *p, pa_card *card) {
875
if (pa_device_init_description(p, card))
878
if (!(d = pa_proplist_gets(p, "alsa.card_name")))
879
d = pa_proplist_gets(p, "alsa.name");
884
k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
887
pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
889
pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
894
void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
898
pa_assert(card >= 0);
900
pa_proplist_setf(p, "alsa.card", "%i", card);
902
if (snd_card_get_name(card, &cn) >= 0) {
903
pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
907
if (snd_card_get_longname(card, &lcn) >= 0) {
908
pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
912
if ((dn = pa_alsa_get_driver_name(card))) {
913
pa_proplist_sets(p, "alsa.driver_name", dn);
918
pa_udev_get_info(card, p);
922
void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
924
static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
925
[SND_PCM_CLASS_GENERIC] = "generic",
926
[SND_PCM_CLASS_MULTI] = "multi",
927
[SND_PCM_CLASS_MODEM] = "modem",
928
[SND_PCM_CLASS_DIGITIZER] = "digitizer"
930
static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
931
[SND_PCM_CLASS_GENERIC] = "sound",
932
[SND_PCM_CLASS_MULTI] = NULL,
933
[SND_PCM_CLASS_MODEM] = "modem",
934
[SND_PCM_CLASS_DIGITIZER] = NULL
936
static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
937
[SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
938
[SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
941
snd_pcm_class_t class;
942
snd_pcm_subclass_t subclass;
943
const char *n, *id, *sdn;
949
pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
951
if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
952
if (class_table[class])
953
pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
954
if (alsa_class_table[class])
955
pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
958
if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
959
if (alsa_subclass_table[subclass])
960
pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
962
if ((n = snd_pcm_info_get_name(pcm_info))) {
963
char *t = pa_xstrdup(n);
964
pa_proplist_sets(p, "alsa.name", pa_strip(t));
968
if ((id = snd_pcm_info_get_id(pcm_info)))
969
pa_proplist_sets(p, "alsa.id", id);
971
pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
972
if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
973
pa_proplist_sets(p, "alsa.subdevice_name", sdn);
975
pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
977
if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
978
pa_alsa_init_proplist_card(c, p, card);
981
void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
982
snd_pcm_hw_params_t *hwparams;
983
snd_pcm_info_t *info;
986
snd_pcm_hw_params_alloca(&hwparams);
987
snd_pcm_info_alloca(&info);
989
if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
990
pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
993
if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
994
pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
997
if ((err = snd_pcm_info(pcm, info)) < 0)
998
pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1000
pa_alsa_init_proplist_pcm_info(c, p, info);
1003
void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1006
snd_ctl_card_info_t *info;
1011
snd_ctl_card_info_alloca(&info);
1013
if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1014
pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1018
if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1019
pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1024
if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1025
pa_proplist_sets(p, "alsa.mixer_name", t);
1027
if ((t = snd_ctl_card_info_get_components(info)) && *t)
1028
pa_proplist_sets(p, "alsa.components", t);
1033
int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1034
snd_pcm_state_t state;
1039
if (revents & POLLERR)
1040
pa_log_debug("Got POLLERR from ALSA");
1041
if (revents & POLLNVAL)
1042
pa_log_warn("Got POLLNVAL from ALSA");
1043
if (revents & POLLHUP)
1044
pa_log_warn("Got POLLHUP from ALSA");
1045
if (revents & POLLPRI)
1046
pa_log_warn("Got POLLPRI from ALSA");
1047
if (revents & POLLIN)
1048
pa_log_debug("Got POLLIN from ALSA");
1049
if (revents & POLLOUT)
1050
pa_log_debug("Got POLLOUT from ALSA");
1052
state = snd_pcm_state(pcm);
1053
pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1055
/* Try to recover from this error */
1059
case SND_PCM_STATE_XRUN:
1060
if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1061
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1066
case SND_PCM_STATE_SUSPENDED:
1067
if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1068
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1077
if ((err = snd_pcm_prepare(pcm)) < 0) {
1078
pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1087
pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1089
struct pollfd *pollfd;
1090
pa_rtpoll_item *item;
1094
if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1095
pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1099
item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1100
pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1102
if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1103
pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1104
pa_rtpoll_item_free(item);
1111
snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1112
snd_pcm_sframes_t n;
1116
pa_assert(hwbuf_size > 0);
1119
/* Some ALSA driver expose weird bugs, let's inform the user about
1120
* what is going on */
1122
n = snd_pcm_avail(pcm);
1127
k = (size_t) n * pa_frame_size(ss);
1129
if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1130
k >= pa_bytes_per_second(ss)*10)) {
1133
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1134
pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1135
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1137
(unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1140
pa_alsa_dump(PA_LOG_ERROR, pcm);
1143
/* Mhmm, let's try not to fail completely */
1144
n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1150
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,
1155
snd_pcm_sframes_t avail = 0;
1159
pa_assert(hwbuf_size > 0);
1162
/* Some ALSA driver expose weird bugs, let's inform the user about
1163
* what is going on. We're going to get both the avail and delay values so
1164
* that we can compare and check them for capture.
1165
* This is done with snd_pcm_status() which provides
1166
* avail, delay and timestamp values in a single kernel call to improve
1167
* timer-based scheduling */
1169
if ((err = snd_pcm_status(pcm, status)) < 0)
1172
avail = snd_pcm_status_get_avail(status);
1173
*delay = snd_pcm_status_get_delay(status);
1175
k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1177
abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1179
if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1180
abs_k >= pa_bytes_per_second(ss)*10)) {
1183
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1184
pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1185
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1188
(unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1191
pa_alsa_dump(PA_LOG_ERROR, pcm);
1194
/* Mhmm, let's try not to fail completely */
1196
*delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1198
*delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1202
abs_k = (size_t) avail * pa_frame_size(ss);
1204
if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1205
abs_k >= pa_bytes_per_second(ss)*10)) {
1208
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1209
pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1210
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1212
(unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1215
pa_alsa_dump(PA_LOG_ERROR, pcm);
1218
/* Mhmm, let's try not to fail completely */
1219
avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1222
if (PA_UNLIKELY(*delay < avail)) {
1224
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1225
pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1226
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1227
(unsigned long) *delay,
1228
(unsigned long) avail,
1231
pa_alsa_dump(PA_LOG_ERROR, pcm);
1242
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) {
1244
snd_pcm_uframes_t before;
1251
pa_assert(hwbuf_size > 0);
1256
r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1261
k = (size_t) *frames * pa_frame_size(ss);
1263
if (PA_UNLIKELY(*frames > before ||
1264
k >= hwbuf_size * 3 ||
1265
k >= pa_bytes_per_second(ss)*10))
1267
char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1268
pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1269
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1271
(unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1274
pa_alsa_dump(PA_LOG_ERROR, pcm);
1280
char *pa_alsa_get_driver_name(int card) {
1283
pa_assert(card >= 0);
1285
t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1292
n = pa_xstrdup(pa_path_get_filename(m));
1298
char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1300
snd_pcm_info_t* info;
1301
snd_pcm_info_alloca(&info);
1305
if (snd_pcm_info(pcm, info) < 0)
1308
if ((card = snd_pcm_info_get_card(info)) < 0)
1311
return pa_alsa_get_driver_name(card);
1314
char *pa_alsa_get_reserve_name(const char *device) {
1320
if ((t = strchr(device, ':')))
1323
if ((i = snd_card_get_index(device)) < 0) {
1326
if (pa_atoi(device, &k) < 0)
1332
return pa_sprintf_malloc("Audio%i", i);
1335
unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1336
static unsigned int all_rates[] = { 8000, 11025, 12000,
1337
16000, 22050, 24000,
1338
32000, 44100, 48000,
1339
64000, 88200, 96000,
1340
128000, 176400, 192000,
1342
bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
1343
snd_pcm_hw_params_t *hwparams;
1344
unsigned int i, j, n, *rates = NULL;
1347
snd_pcm_hw_params_alloca(&hwparams);
1349
if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1350
pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1354
for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1355
if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1356
supported[i] = true;
1362
rates = pa_xnew(unsigned int, n + 1);
1364
for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1366
rates[j++] = all_rates[i];
1371
rates = pa_xnew(unsigned int, 2);
1373
rates[0] = fallback_rate;
1374
if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1375
pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1386
bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1387
snd_pcm_info_t* info;
1388
snd_pcm_info_alloca(&info);
1392
if (snd_pcm_info(pcm, info) < 0)
1395
return snd_pcm_info_get_card(info) >= 0;
1398
bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1399
snd_pcm_info_t* info;
1400
snd_pcm_info_alloca(&info);
1404
if (snd_pcm_info(pcm, info) < 0)
1407
return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1410
PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1412
const char* pa_alsa_strerror(int errnum) {
1413
const char *original = NULL;
1414
char *translated, *t;
1417
if ((t = PA_STATIC_TLS_GET(cstrerror)))
1420
original = snd_strerror(errnum);
1423
pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1427
if (!(translated = pa_locale_to_utf8(original))) {
1428
pa_log_warn("Unable to convert error string to locale, filtering.");
1429
translated = pa_utf8_filter(original);
1432
PA_STATIC_TLS_SET(cstrerror, translated);
1437
bool pa_alsa_may_tsched(bool want) {
1442
if (!pa_rtclock_hrtimer()) {
1443
/* We cannot depend on being woken up in time when the timers
1444
are inaccurate, so let's fallback to classic IO based playback
1446
pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1449
if (pa_running_in_vm()) {
1450
/* We cannot depend on being woken up when we ask for in a VM,
1451
* so let's fallback to classic IO based playback then. */
1452
pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1459
#define SND_MIXER_ELEM_PULSEAUDIO (SND_MIXER_ELEM_LAST + 10)
1461
snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer, const char *name, unsigned int device) {
1462
snd_mixer_elem_t *elem;
1464
for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
1465
snd_hctl_elem_t *helem;
1466
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
1468
helem = snd_mixer_elem_get_private(elem);
1469
if (!pa_streq(snd_hctl_elem_get_name(helem), name))
1471
if (snd_hctl_elem_get_device(helem) != device)
1478
static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
1480
/* Dummy compare function */
1481
return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1);
1484
static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
1485
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
1488
const char *name = snd_hctl_elem_get_name(helem);
1489
if (mask & SND_CTL_EVENT_MASK_ADD) {
1490
snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
1491
if (iface == SND_CTL_ELEM_IFACE_CARD || iface == SND_CTL_ELEM_IFACE_PCM) {
1492
snd_mixer_elem_t *new_melem;
1494
/* Put the hctl pointer as our private data - it will be useful for callbacks */
1495
if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, helem, NULL)) < 0) {
1496
pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
1500
if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
1501
pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err));
1502
snd_mixer_elem_free(melem);
1506
if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
1507
pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
1512
else if (mask & SND_CTL_EVENT_MASK_VALUE) {
1513
snd_mixer_elem_value(melem); /* Calls the element callback */
1517
pa_log_info("Got an unknown mixer class event for %s: mask 0x%x\n", name, mask);
1522
static int prepare_mixer(snd_mixer_t *mixer, const char *dev) {
1524
snd_mixer_class_t *class;
1529
if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1530
pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1534
if (snd_mixer_class_malloc(&class)) {
1535
pa_log_info("Failed to allocate mixer class for %s", dev);
1538
snd_mixer_class_set_event(class, mixer_class_event);
1539
snd_mixer_class_set_compare(class, mixer_class_compare);
1540
if ((err = snd_mixer_class_register(class, mixer)) < 0) {
1541
pa_log_info("Unable register mixer class for %s: %s", dev, pa_alsa_strerror(err));
1542
snd_mixer_class_free(class);
1545
/* From here on, the mixer class is deallocated by alsa on snd_mixer_close/free. */
1547
if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1548
pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1552
if ((err = snd_mixer_load(mixer)) < 0) {
1553
pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1557
pa_log_info("Successfully attached to mixer '%s'", dev);
1561
snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device) {
1565
snd_pcm_info_t* info;
1566
snd_pcm_info_alloca(&info);
1568
if ((err = snd_mixer_open(&m, 0)) < 0) {
1569
pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1573
/* Then, try by card index */
1574
md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1575
if (prepare_mixer(m, md) >= 0) {
1591
snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device) {
1595
snd_pcm_info_t* info;
1596
snd_pcm_info_alloca(&info);
1600
if ((err = snd_mixer_open(&m, 0)) < 0) {
1601
pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1605
/* First, try by name */
1606
if ((dev = snd_pcm_name(pcm)))
1607
if (prepare_mixer(m, dev) >= 0) {
1609
*ctl_device = pa_xstrdup(dev);
1614
/* Then, try by card index */
1615
if (snd_pcm_info(pcm, info) >= 0) {
1619
if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1621
md = pa_sprintf_malloc("hw:%i", card_idx);
1623
if (!dev || !pa_streq(dev, md))
1624
if (prepare_mixer(m, md) >= 0) {
1642
int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) {
1644
/* The ELD format is specific to HDA Intel sound cards and defined in the
1645
HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1647
snd_ctl_elem_info_t *info;
1648
snd_ctl_elem_value_t *value;
1650
unsigned int eldsize, mnl;
1651
unsigned int device;
1653
pa_assert(eld != NULL);
1654
pa_assert(elem != NULL);
1656
/* Does it have any contents? */
1657
snd_ctl_elem_info_alloca(&info);
1658
snd_ctl_elem_value_alloca(&value);
1659
if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1660
(err = snd_hctl_elem_read(elem, value)) < 0) {
1661
pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1665
device = snd_hctl_elem_get_device(elem);
1666
eldsize = snd_ctl_elem_info_get_count(info);
1667
elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1668
if (elddata == NULL || eldsize == 0) {
1669
pa_log_debug("ELD info empty (for device=%d)", device);
1672
if (eldsize < 20 || eldsize > 256) {
1673
pa_log_debug("ELD info has wrong size (for device=%d)", device);
1677
/* Try to fetch monitor name */
1678
mnl = elddata[4] & 0x1f;
1679
if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
1680
pa_log_debug("No monitor name in ELD info (for device=%d)", device);
1683
memcpy(eld->monitor_name, &elddata[20], mnl);
1684
eld->monitor_name[mnl] = '\0';
1686
pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);