1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2009 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <sys/types.h>
26 #include <alsa/asoundlib.h>
27
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>
33
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>
43 #include <pulsecore/strbuf.h>
44
45 #include "alsa-util.h"
46 #include "alsa-mixer.h"
47
48 #ifdef HAVE_UDEV
49 #include <modules/udev-util.h>
50 #endif
51
set_format(snd_pcm_t * pcm_handle,snd_pcm_hw_params_t * hwparams,pa_sample_format_t * f)52 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
53
54 static const snd_pcm_format_t format_trans[] = {
55 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
56 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
57 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
58 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
59 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
60 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
61 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
62 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
63 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
64 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
65 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
66 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
67 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
68 };
69
70 static const pa_sample_format_t try_order[] = {
71 PA_SAMPLE_FLOAT32NE,
72 PA_SAMPLE_FLOAT32RE,
73 PA_SAMPLE_S32NE,
74 PA_SAMPLE_S32RE,
75 PA_SAMPLE_S24_32NE,
76 PA_SAMPLE_S24_32RE,
77 PA_SAMPLE_S24NE,
78 PA_SAMPLE_S24RE,
79 PA_SAMPLE_S16NE,
80 PA_SAMPLE_S16RE,
81 PA_SAMPLE_ALAW,
82 PA_SAMPLE_ULAW,
83 PA_SAMPLE_U8
84 };
85
86 unsigned i;
87 int ret;
88
89 pa_assert(pcm_handle);
90 pa_assert(hwparams);
91 pa_assert(f);
92
93 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
94 return ret;
95
96 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
97 snd_pcm_format_description(format_trans[*f]),
98 pa_alsa_strerror(ret));
99
100 if (*f == PA_SAMPLE_FLOAT32BE)
101 *f = PA_SAMPLE_FLOAT32LE;
102 else if (*f == PA_SAMPLE_FLOAT32LE)
103 *f = PA_SAMPLE_FLOAT32BE;
104 else if (*f == PA_SAMPLE_S24BE)
105 *f = PA_SAMPLE_S24LE;
106 else if (*f == PA_SAMPLE_S24LE)
107 *f = PA_SAMPLE_S24BE;
108 else if (*f == PA_SAMPLE_S24_32BE)
109 *f = PA_SAMPLE_S24_32LE;
110 else if (*f == PA_SAMPLE_S24_32LE)
111 *f = PA_SAMPLE_S24_32BE;
112 else if (*f == PA_SAMPLE_S16BE)
113 *f = PA_SAMPLE_S16LE;
114 else if (*f == PA_SAMPLE_S16LE)
115 *f = PA_SAMPLE_S16BE;
116 else if (*f == PA_SAMPLE_S32BE)
117 *f = PA_SAMPLE_S32LE;
118 else if (*f == PA_SAMPLE_S32LE)
119 *f = PA_SAMPLE_S32BE;
120 else
121 goto try_auto;
122
123 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
124 return ret;
125
126 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
127 snd_pcm_format_description(format_trans[*f]),
128 pa_alsa_strerror(ret));
129
130 try_auto:
131
132 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
133 *f = try_order[i];
134
135 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
136 return ret;
137
138 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
139 snd_pcm_format_description(format_trans[*f]),
140 pa_alsa_strerror(ret));
141 }
142
143 return -1;
144 }
145
set_period_size(snd_pcm_t * pcm_handle,snd_pcm_hw_params_t * hwparams,snd_pcm_uframes_t size)146 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
147 snd_pcm_uframes_t s;
148 int d, ret;
149
150 pa_assert(pcm_handle);
151 pa_assert(hwparams);
152
153 s = size;
154 d = 0;
155 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
156 s = size;
157 d = -1;
158 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
159 s = size;
160 d = 1;
161 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
162 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
163 return ret;
164 }
165 }
166 }
167
168 return 0;
169 }
170
set_buffer_size(snd_pcm_t * pcm_handle,snd_pcm_hw_params_t * hwparams,snd_pcm_uframes_t size)171 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
172 int ret;
173
174 pa_assert(pcm_handle);
175 pa_assert(hwparams);
176
177 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
178 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
179 return ret;
180 }
181
182 return 0;
183 }
184
check_access(snd_pcm_t * pcm_handle,snd_pcm_hw_params_t * hwparams,bool use_mmap)185 static void check_access(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, bool use_mmap) {
186 if ((use_mmap && !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) ||
187 !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))
188 pa_log_error("Weird, PCM claims to support interleaved access, but snd_pcm_hw_params_set_access() failed.");
189
190 if ((use_mmap && !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) ||
191 !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_NONINTERLEAVED))
192 pa_log_debug("PCM seems to support non-interleaved access, but PA doesn't.");
193 else if (use_mmap && !snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_COMPLEX)) {
194 pa_log_debug("PCM seems to support mmapped complex access, but PA doesn't.");
195 }
196 }
197
198 /* Set the hardware parameters of the given ALSA device. Returns the
199 * selected fragment settings in *buffer_size and *period_size. Determine
200 * whether mmap and tsched mode can be enabled. */
pa_alsa_set_hw_params(snd_pcm_t * pcm_handle,pa_sample_spec * ss,snd_pcm_uframes_t * period_size,snd_pcm_uframes_t * buffer_size,snd_pcm_uframes_t tsched_size,bool * use_mmap,bool * use_tsched,bool require_exact_channel_number)201 int pa_alsa_set_hw_params(
202 snd_pcm_t *pcm_handle,
203 pa_sample_spec *ss,
204 snd_pcm_uframes_t *period_size,
205 snd_pcm_uframes_t *buffer_size,
206 snd_pcm_uframes_t tsched_size,
207 bool *use_mmap,
208 bool *use_tsched,
209 bool require_exact_channel_number) {
210
211 int ret = -1;
212 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
213 int dir;
214 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
215 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
216 bool _use_mmap = use_mmap && *use_mmap;
217 bool _use_tsched = use_tsched && *use_tsched;
218 pa_sample_spec _ss = *ss;
219
220 pa_assert(pcm_handle);
221 pa_assert(ss);
222
223 snd_pcm_hw_params_alloca(&hwparams);
224 snd_pcm_hw_params_alloca(&hwparams_copy);
225
226 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
227 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
228 goto finish;
229 }
230
231 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
232 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
233 goto finish;
234 }
235
236 if (_use_mmap) {
237
238 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
239
240 /* mmap() didn't work, fall back to interleaved */
241
242 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
243 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
244 check_access(pcm_handle, hwparams, true);
245 goto finish;
246 }
247
248 _use_mmap = false;
249 }
250
251 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
252 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
253 check_access(pcm_handle, hwparams, false);
254 goto finish;
255 }
256
257 if (!_use_mmap)
258 _use_tsched = false;
259
260 if (!pa_alsa_pcm_is_hw(pcm_handle))
261 _use_tsched = false;
262
263 /* The PCM pointer is only updated with period granularity */
264 if (snd_pcm_hw_params_is_batch(hwparams)) {
265 bool is_usb = false;
266 const char *id;
267 snd_pcm_info_t* pcm_info;
268 snd_pcm_info_alloca(&pcm_info);
269
270 if (snd_pcm_info(pcm_handle, pcm_info) == 0 &&
271 (id = snd_pcm_info_get_id(pcm_info))) {
272 /* This horrible hack makes sure we don't disable tsched on USB
273 * devices, which have a low enough transfer size for timer-based
274 * scheduling to work. This can go away when the ALSA API supprots
275 * querying the block transfer size. */
276 if (pa_streq(id, "USB Audio"))
277 is_usb = true;
278 }
279
280 if (!is_usb) {
281 pa_log_info("Disabling tsched mode since BATCH flag is set");
282 _use_tsched = false;
283 }
284 }
285
286 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
287 if (_use_tsched) {
288
289 /* try to disable period wakeups if hardware can do so */
290 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
291
292 if ((ret = snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, false)) < 0)
293 /* don't bail, keep going with default mode with period wakeups */
294 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret));
295 else
296 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
297 } else
298 pa_log_info("Cannot disable ALSA period wakeups");
299 }
300 #endif
301
302 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
303 goto finish;
304
305 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
306 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
307 goto finish;
308 }
309
310 /* We ignore very small sampling rate deviations */
311 if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
312 _ss.rate = ss->rate;
313
314 if (require_exact_channel_number) {
315 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
316 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
317 goto finish;
318 }
319 } else {
320 unsigned int c = _ss.channels;
321
322 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
323 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
324 goto finish;
325 }
326
327 _ss.channels = c;
328 }
329
330 if (_use_tsched && tsched_size > 0) {
331 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
332 _period_size = _buffer_size;
333 } else {
334 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
335 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
336 }
337
338 if (_buffer_size > 0 || _period_size > 0) {
339 snd_pcm_uframes_t max_frames = 0;
340
341 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
342 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
343 else
344 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
345
346 /* Some ALSA drivers really don't like if we set the buffer
347 * size first and the number of periods second (which would
348 * make a lot more sense to me). So, try a few combinations
349 * before we give up. */
350
351 if (_buffer_size > 0 && _period_size > 0) {
352 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
353
354 /* First try: set buffer size first, followed by period size */
355 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
356 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
357 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
358 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
359 goto success;
360 }
361
362 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
363 /* Second try: set period size first, followed by buffer size */
364 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
365 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
366 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
367 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);
368 goto success;
369 }
370 }
371
372 if (_buffer_size > 0) {
373 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
374
375 /* Third try: set only buffer size */
376 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
377 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
378 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);
379 goto success;
380 }
381 }
382
383 if (_period_size > 0) {
384 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
385
386 /* Fourth try: set only period size */
387 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
388 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
389 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);
390 goto success;
391 }
392 }
393 }
394
395 pa_log_debug("Set neither period nor buffer size.");
396
397 /* Last chance, set nothing */
398 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
399 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
400 goto finish;
401 }
402
403 success:
404
405 if (ss->rate != _ss.rate)
406 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
407
408 if (ss->channels != _ss.channels)
409 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
410
411 if (ss->format != _ss.format)
412 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));
413
414 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
415 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
416 goto finish;
417 }
418
419 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
420 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
421 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
422 goto finish;
423 }
424
425 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
426 if (_use_tsched) {
427 unsigned int no_wakeup;
428 /* see if period wakeups were disabled */
429 snd_pcm_hw_params_get_period_wakeup(pcm_handle, hwparams, &no_wakeup);
430 if (no_wakeup == 0)
431 pa_log_info("ALSA period wakeups disabled");
432 else
433 pa_log_info("ALSA period wakeups were not disabled");
434 }
435 #endif
436
437 ss->rate = _ss.rate;
438 ss->channels = _ss.channels;
439 ss->format = _ss.format;
440
441 pa_assert(_period_size > 0);
442 pa_assert(_buffer_size > 0);
443
444 if (buffer_size)
445 *buffer_size = _buffer_size;
446
447 if (period_size)
448 *period_size = _period_size;
449
450 if (use_mmap)
451 *use_mmap = _use_mmap;
452
453 if (use_tsched)
454 *use_tsched = _use_tsched;
455
456 ret = 0;
457
458 finish:
459
460 return ret;
461 }
462
pa_alsa_set_sw_params(snd_pcm_t * pcm,snd_pcm_uframes_t avail_min,bool period_event)463 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
464 snd_pcm_sw_params_t *swparams;
465 snd_pcm_uframes_t boundary;
466 int err;
467
468 pa_assert(pcm);
469
470 snd_pcm_sw_params_alloca(&swparams);
471
472 if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) {
473 pa_log_warn("Unable to determine current swparams: %s", pa_alsa_strerror(err));
474 return err;
475 }
476
477 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
478 pa_log_warn("Unable to disable period event: %s", pa_alsa_strerror(err));
479 return err;
480 }
481
482 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
483 pa_log_warn("Unable to enable time stamping: %s", pa_alsa_strerror(err));
484 return err;
485 }
486
487 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
488 pa_log_warn("Unable to get boundary: %s", pa_alsa_strerror(err));
489 return err;
490 }
491
492 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
493 pa_log_warn("Unable to set stop threshold: %s", pa_alsa_strerror(err));
494 return err;
495 }
496
497 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
498 pa_log_warn("Unable to set start threshold: %s", pa_alsa_strerror(err));
499 return err;
500 }
501
502 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
503 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
504 return err;
505 }
506
507 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
508 pa_log_warn("Unable to set sw params: %s", pa_alsa_strerror(err));
509 return err;
510 }
511
512 return 0;
513 }
514
pa_alsa_open_by_device_id_auto(const char * dev_id,char ** dev,pa_sample_spec * ss,pa_channel_map * map,int mode,snd_pcm_uframes_t * period_size,snd_pcm_uframes_t * buffer_size,snd_pcm_uframes_t tsched_size,bool * use_mmap,bool * use_tsched,pa_sample_format_t ** query_supported_formats,unsigned int ** query_supported_rates,pa_alsa_profile_set * ps,pa_alsa_mapping ** mapping)515 snd_pcm_t *pa_alsa_open_by_device_id_auto(
516 const char *dev_id,
517 char **dev,
518 pa_sample_spec *ss,
519 pa_channel_map* map,
520 int mode,
521 snd_pcm_uframes_t *period_size,
522 snd_pcm_uframes_t *buffer_size,
523 snd_pcm_uframes_t tsched_size,
524 bool *use_mmap,
525 bool *use_tsched,
526 pa_sample_format_t **query_supported_formats,
527 unsigned int **query_supported_rates,
528 pa_alsa_profile_set *ps,
529 pa_alsa_mapping **mapping) {
530
531 char *d;
532 snd_pcm_t *pcm_handle;
533 void *state;
534 pa_alsa_mapping *m;
535
536 pa_assert(dev_id);
537 pa_assert(dev);
538 pa_assert(ss);
539 pa_assert(map);
540 pa_assert(ps);
541
542 /* First we try to find a device string with a superset of the
543 * requested channel map. We iterate through our device table from
544 * top to bottom and take the first that matches. If we didn't
545 * find a working device that way, we iterate backwards, and check
546 * all devices that do not provide a superset of the requested
547 * channel map.*/
548
549 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
550 if (!pa_channel_map_superset(&m->channel_map, map))
551 continue;
552
553 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
554
555 pcm_handle = pa_alsa_open_by_device_id_mapping(
556 dev_id,
557 dev,
558 ss,
559 map,
560 mode,
561 period_size,
562 buffer_size,
563 tsched_size,
564 use_mmap,
565 use_tsched,
566 query_supported_formats,
567 query_supported_rates,
568 m);
569
570 if (pcm_handle) {
571 if (mapping)
572 *mapping = m;
573
574 return pcm_handle;
575 }
576 }
577
578 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
579 if (pa_channel_map_superset(&m->channel_map, map))
580 continue;
581
582 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
583
584 pcm_handle = pa_alsa_open_by_device_id_mapping(
585 dev_id,
586 dev,
587 ss,
588 map,
589 mode,
590 period_size,
591 buffer_size,
592 tsched_size,
593 use_mmap,
594 use_tsched,
595 query_supported_formats,
596 query_supported_rates,
597 m);
598
599 if (pcm_handle) {
600 if (mapping)
601 *mapping = m;
602
603 return pcm_handle;
604 }
605 }
606
607 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
608 d = pa_sprintf_malloc("hw:%s", dev_id);
609 pa_log_debug("Trying %s as last resort...", d);
610 pcm_handle = pa_alsa_open_by_device_string(
611 d,
612 dev,
613 ss,
614 map,
615 mode,
616 period_size,
617 buffer_size,
618 tsched_size,
619 use_mmap,
620 use_tsched,
621 query_supported_formats,
622 query_supported_rates,
623 false);
624 pa_xfree(d);
625
626 if (pcm_handle && mapping)
627 *mapping = NULL;
628
629 return pcm_handle;
630 }
631
pa_alsa_open_by_device_id_mapping(const char * dev_id,char ** dev,pa_sample_spec * ss,pa_channel_map * map,int mode,snd_pcm_uframes_t * period_size,snd_pcm_uframes_t * buffer_size,snd_pcm_uframes_t tsched_size,bool * use_mmap,bool * use_tsched,pa_sample_format_t ** query_supported_formats,unsigned int ** query_supported_rates,pa_alsa_mapping * m)632 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
633 const char *dev_id,
634 char **dev,
635 pa_sample_spec *ss,
636 pa_channel_map* map,
637 int mode,
638 snd_pcm_uframes_t *period_size,
639 snd_pcm_uframes_t *buffer_size,
640 snd_pcm_uframes_t tsched_size,
641 bool *use_mmap,
642 bool *use_tsched,
643 pa_sample_format_t **query_supported_formats,
644 unsigned int **query_supported_rates,
645 pa_alsa_mapping *m) {
646
647 snd_pcm_t *pcm_handle;
648 pa_sample_spec try_ss;
649 pa_channel_map try_map;
650
651 pa_assert(dev_id);
652 pa_assert(dev);
653 pa_assert(ss);
654 pa_assert(map);
655 pa_assert(m);
656
657 try_ss.channels = m->channel_map.channels;
658 try_ss.rate = ss->rate;
659 try_ss.format = ss->format;
660 try_map = m->channel_map;
661
662 pcm_handle = pa_alsa_open_by_template(
663 m->device_strings,
664 dev_id,
665 dev,
666 &try_ss,
667 &try_map,
668 mode,
669 period_size,
670 buffer_size,
671 tsched_size,
672 use_mmap,
673 use_tsched,
674 query_supported_formats,
675 query_supported_rates,
676 pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
677
678 if (!pcm_handle)
679 return NULL;
680
681 *ss = try_ss;
682 *map = try_map;
683 pa_assert(map->channels == ss->channels);
684
685 return pcm_handle;
686 }
687
pa_alsa_open_by_device_string(const char * device,char ** dev,pa_sample_spec * ss,pa_channel_map * map,int mode,snd_pcm_uframes_t * period_size,snd_pcm_uframes_t * buffer_size,snd_pcm_uframes_t tsched_size,bool * use_mmap,bool * use_tsched,pa_sample_format_t ** query_supported_formats,unsigned int ** query_supported_rates,bool require_exact_channel_number)688 snd_pcm_t *pa_alsa_open_by_device_string(
689 const char *device,
690 char **dev,
691 pa_sample_spec *ss,
692 pa_channel_map* map,
693 int mode,
694 snd_pcm_uframes_t *period_size,
695 snd_pcm_uframes_t *buffer_size,
696 snd_pcm_uframes_t tsched_size,
697 bool *use_mmap,
698 bool *use_tsched,
699 pa_sample_format_t **query_supported_formats,
700 unsigned int **query_supported_rates,
701 bool require_exact_channel_number) {
702
703 int err;
704 char *d;
705 snd_pcm_t *pcm_handle;
706 bool reformat = false;
707
708 pa_assert(device);
709 pa_assert(ss);
710 pa_assert(map);
711
712 d = pa_xstrdup(device);
713
714 for (;;) {
715 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
716
717 if ((err = snd_pcm_open(&pcm_handle, d, mode,
718 SND_PCM_NONBLOCK|
719 SND_PCM_NO_AUTO_RESAMPLE|
720 SND_PCM_NO_AUTO_CHANNELS|
721 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
722 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
723 goto fail;
724 }
725
726 pa_log_debug("Managed to open %s", d);
727
728 if (query_supported_formats)
729 *query_supported_formats = pa_alsa_get_supported_formats(pcm_handle, ss->format);
730
731 if (query_supported_rates)
732 *query_supported_rates = pa_alsa_get_supported_rates(pcm_handle, ss->rate);
733
734 if ((err = pa_alsa_set_hw_params(
735 pcm_handle,
736 ss,
737 period_size,
738 buffer_size,
739 tsched_size,
740 use_mmap,
741 use_tsched,
742 require_exact_channel_number)) < 0) {
743
744 if (!reformat) {
745 reformat = true;
746
747 snd_pcm_close(pcm_handle);
748 continue;
749 }
750
751 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
752 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
753 char *t;
754
755 t = pa_sprintf_malloc("plug:SLAVE='%s'", d);
756 pa_xfree(d);
757 d = t;
758
759 reformat = false;
760
761 snd_pcm_close(pcm_handle);
762 continue;
763 }
764
765 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
766 snd_pcm_close(pcm_handle);
767
768 goto fail;
769 }
770
771 if (ss->channels > PA_CHANNELS_MAX) {
772 pa_log("Device %s has %u channels, but PulseAudio supports only %u channels. Unable to use the device.",
773 d, ss->channels, PA_CHANNELS_MAX);
774 snd_pcm_close(pcm_handle);
775 goto fail;
776 }
777
778 if (dev)
779 *dev = d;
780 else
781 pa_xfree(d);
782
783 if (ss->channels != map->channels)
784 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
785
786 return pcm_handle;
787 }
788
789 fail:
790 pa_xfree(d);
791
792 return NULL;
793 }
794
pa_alsa_open_by_template(char ** template,const char * dev_id,char ** dev,pa_sample_spec * ss,pa_channel_map * map,int mode,snd_pcm_uframes_t * period_size,snd_pcm_uframes_t * buffer_size,snd_pcm_uframes_t tsched_size,bool * use_mmap,bool * use_tsched,pa_sample_format_t ** query_supported_formats,unsigned int ** query_supported_rates,bool require_exact_channel_number)795 snd_pcm_t *pa_alsa_open_by_template(
796 char **template,
797 const char *dev_id,
798 char **dev,
799 pa_sample_spec *ss,
800 pa_channel_map* map,
801 int mode,
802 snd_pcm_uframes_t *period_size,
803 snd_pcm_uframes_t *buffer_size,
804 snd_pcm_uframes_t tsched_size,
805 bool *use_mmap,
806 bool *use_tsched,
807 pa_sample_format_t **query_supported_formats,
808 unsigned int **query_supported_rates,
809 bool require_exact_channel_number) {
810
811 snd_pcm_t *pcm_handle;
812 char **i;
813
814 for (i = template; *i; i++) {
815 char *d;
816
817 d = pa_replace(*i, "%f", dev_id);
818
819 pcm_handle = pa_alsa_open_by_device_string(
820 d,
821 dev,
822 ss,
823 map,
824 mode,
825 period_size,
826 buffer_size,
827 tsched_size,
828 use_mmap,
829 use_tsched,
830 query_supported_formats,
831 query_supported_rates,
832 require_exact_channel_number);
833
834 pa_xfree(d);
835
836 if (pcm_handle)
837 return pcm_handle;
838 }
839
840 return NULL;
841 }
842
pa_alsa_dump(pa_log_level_t level,snd_pcm_t * pcm)843 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
844 int err;
845 snd_output_t *out;
846
847 pa_assert(pcm);
848
849 pa_assert_se(snd_output_buffer_open(&out) == 0);
850
851 if ((err = snd_pcm_dump(pcm, out)) < 0)
852 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
853 else {
854 char *s = NULL;
855 snd_output_buffer_string(out, &s);
856 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
857 }
858
859 pa_assert_se(snd_output_close(out) == 0);
860 }
861
pa_alsa_dump_status(snd_pcm_t * pcm)862 void pa_alsa_dump_status(snd_pcm_t *pcm) {
863 int err;
864 snd_output_t *out;
865 snd_pcm_status_t *status;
866 char *s = NULL;
867
868 pa_assert(pcm);
869
870 snd_pcm_status_alloca(&status);
871
872 if ((err = snd_output_buffer_open(&out)) < 0) {
873 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
874 return;
875 }
876
877 if ((err = snd_pcm_status(pcm, status)) < 0) {
878 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
879 goto finish;
880 }
881
882 if ((err = snd_pcm_status_dump(status, out)) < 0) {
883 pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err));
884 goto finish;
885 }
886
887 snd_output_buffer_string(out, &s);
888 pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s));
889
890 finish:
891
892 snd_output_close(out);
893 }
894
alsa_error_handler(const char * file,int line,const char * function,int err,const char * fmt,...)895 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
896 va_list ap;
897 char *alsa_file;
898
899 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
900
901 va_start(ap, fmt);
902
903 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
904
905 va_end(ap);
906
907 pa_xfree(alsa_file);
908 }
909
910 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
911
pa_alsa_refcnt_inc(void)912 void pa_alsa_refcnt_inc(void) {
913 /* This is not really thread safe, but we do our best */
914
915 if (pa_atomic_inc(&n_error_handler_installed) == 0)
916 snd_lib_error_set_handler(alsa_error_handler);
917 }
918
pa_alsa_refcnt_dec(void)919 void pa_alsa_refcnt_dec(void) {
920 int r;
921
922 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
923
924 if (r == 1) {
925 snd_lib_error_set_handler(NULL);
926 snd_config_update_free_global();
927 }
928 }
929
pa_alsa_init_description(pa_proplist * p,pa_card * card)930 bool pa_alsa_init_description(pa_proplist *p, pa_card *card) {
931 const char *d, *k;
932 pa_assert(p);
933
934 if (pa_device_init_description(p, card))
935 return true;
936
937 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
938 d = pa_proplist_gets(p, "alsa.name");
939
940 if (!d)
941 return false;
942
943 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
944
945 if (d && k)
946 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
947 else if (d)
948 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
949
950 return false;
951 }
952
pa_alsa_init_proplist_card(pa_core * c,pa_proplist * p,int card)953 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
954 char *cn, *lcn, *dn;
955
956 pa_assert(p);
957 pa_assert(card >= 0);
958
959 pa_proplist_setf(p, "alsa.card", "%i", card);
960
961 if (snd_card_get_name(card, &cn) >= 0) {
962 pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
963 free(cn);
964 }
965
966 if (snd_card_get_longname(card, &lcn) >= 0) {
967 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
968 free(lcn);
969 }
970
971 if ((dn = pa_alsa_get_driver_name(card))) {
972 pa_proplist_sets(p, "alsa.driver_name", dn);
973 pa_xfree(dn);
974 }
975
976 #ifdef HAVE_UDEV
977 pa_udev_get_info(card, p);
978 #endif
979 }
980
pa_alsa_init_proplist_pcm_info(pa_core * c,pa_proplist * p,snd_pcm_info_t * pcm_info)981 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
982
983 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
984 [SND_PCM_CLASS_GENERIC] = "generic",
985 [SND_PCM_CLASS_MULTI] = "multi",
986 [SND_PCM_CLASS_MODEM] = "modem",
987 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
988 };
989 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
990 [SND_PCM_CLASS_GENERIC] = "sound",
991 [SND_PCM_CLASS_MULTI] = NULL,
992 [SND_PCM_CLASS_MODEM] = "modem",
993 [SND_PCM_CLASS_DIGITIZER] = NULL
994 };
995 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
996 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
997 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
998 };
999
1000 snd_pcm_class_t class;
1001 snd_pcm_subclass_t subclass;
1002 const char *n, *id, *sdn;
1003 int card;
1004
1005 pa_assert(p);
1006 pa_assert(pcm_info);
1007
1008 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
1009
1010 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
1011 if (class_table[class])
1012 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
1013 if (alsa_class_table[class])
1014 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
1015 }
1016
1017 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
1018 if (alsa_subclass_table[subclass])
1019 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
1020
1021 if ((n = snd_pcm_info_get_name(pcm_info))) {
1022 char *t = pa_xstrdup(n);
1023 pa_proplist_sets(p, "alsa.name", pa_strip(t));
1024 pa_xfree(t);
1025 }
1026
1027 if ((id = snd_pcm_info_get_id(pcm_info)))
1028 pa_proplist_sets(p, "alsa.id", id);
1029
1030 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
1031 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
1032 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
1033
1034 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
1035
1036 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
1037 pa_alsa_init_proplist_card(c, p, card);
1038 }
1039
pa_alsa_init_proplist_pcm(pa_core * c,pa_proplist * p,snd_pcm_t * pcm)1040 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
1041 snd_pcm_hw_params_t *hwparams;
1042 snd_pcm_info_t *info;
1043 int bits, err;
1044
1045 snd_pcm_hw_params_alloca(&hwparams);
1046 snd_pcm_info_alloca(&info);
1047
1048 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
1049 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
1050 else {
1051
1052 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
1053 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
1054 }
1055
1056 if ((err = snd_pcm_info(pcm, info)) < 0)
1057 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1058 else
1059 pa_alsa_init_proplist_pcm_info(c, p, info);
1060 }
1061
pa_alsa_init_proplist_ctl(pa_proplist * p,const char * name)1062 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1063 int err;
1064 snd_ctl_t *ctl;
1065 snd_ctl_card_info_t *info;
1066 const char *t;
1067
1068 pa_assert(p);
1069
1070 snd_ctl_card_info_alloca(&info);
1071
1072 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1073 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1074 return;
1075 }
1076
1077 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1078 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1079 snd_ctl_close(ctl);
1080 return;
1081 }
1082
1083 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1084 pa_proplist_sets(p, "alsa.mixer_name", t);
1085
1086 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1087 pa_proplist_sets(p, "alsa.components", t);
1088
1089 snd_ctl_close(ctl);
1090 }
1091
pa_alsa_recover_from_poll(snd_pcm_t * pcm,int revents)1092 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1093 snd_pcm_state_t state;
1094 snd_pcm_hw_params_t *hwparams;
1095 int err;
1096
1097 pa_assert(pcm);
1098
1099 if (revents & POLLERR)
1100 pa_log_debug("Got POLLERR from ALSA");
1101 if (revents & POLLNVAL)
1102 pa_log_warn("Got POLLNVAL from ALSA");
1103 if (revents & POLLHUP)
1104 pa_log_warn("Got POLLHUP from ALSA");
1105 if (revents & POLLPRI)
1106 pa_log_warn("Got POLLPRI from ALSA");
1107 if (revents & POLLIN)
1108 pa_log_debug("Got POLLIN from ALSA");
1109 if (revents & POLLOUT)
1110 pa_log_debug("Got POLLOUT from ALSA");
1111
1112 state = snd_pcm_state(pcm);
1113 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1114
1115 /* Try to recover from this error */
1116
1117 switch (state) {
1118
1119 case SND_PCM_STATE_DISCONNECTED:
1120 /* Do not try to recover */
1121 pa_log_info("Device disconnected.");
1122 return -1;
1123
1124 case SND_PCM_STATE_XRUN:
1125 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1126 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1127 return -1;
1128 }
1129 break;
1130
1131 case SND_PCM_STATE_SUSPENDED:
1132 snd_pcm_hw_params_alloca(&hwparams);
1133
1134 if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1135 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(err));
1136 return -1;
1137 }
1138
1139 if (snd_pcm_hw_params_can_resume(hwparams)) {
1140 /* Retry resume 3 times before giving up, then fallback to restarting the stream. */
1141 for (int i = 0; i < 3; i++) {
1142 if ((err = snd_pcm_resume(pcm)) == 0)
1143 return 0;
1144 if (err != -EAGAIN)
1145 break;
1146 pa_msleep(25);
1147 }
1148 pa_log_warn("Could not recover alsa device from SUSPENDED state, trying to restart PCM");
1149 }
1150 /* Fall through */
1151
1152 default:
1153
1154 snd_pcm_drop(pcm);
1155 return 1;
1156 }
1157
1158 return 0;
1159 }
1160
pa_alsa_build_pollfd(snd_pcm_t * pcm,pa_rtpoll * rtpoll)1161 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1162 int n, err;
1163 struct pollfd *pollfd;
1164 pa_rtpoll_item *item;
1165
1166 pa_assert(pcm);
1167
1168 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1169 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1170 return NULL;
1171 }
1172
1173 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1174 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1175
1176 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1177 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1178 pa_rtpoll_item_free(item);
1179 return NULL;
1180 }
1181
1182 return item;
1183 }
1184
pa_alsa_safe_avail(snd_pcm_t * pcm,size_t hwbuf_size,const pa_sample_spec * ss)1185 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1186 snd_pcm_sframes_t n;
1187 size_t k;
1188
1189 pa_assert(pcm);
1190 pa_assert(hwbuf_size > 0);
1191 pa_assert(ss);
1192
1193 /* Some ALSA driver expose weird bugs, let's inform the user about
1194 * what is going on */
1195
1196 n = snd_pcm_avail(pcm);
1197
1198 if (n <= 0)
1199 return n;
1200
1201 k = (size_t) n * pa_frame_size(ss);
1202
1203 if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1204 k >= pa_bytes_per_second(ss)*10)) {
1205
1206 PA_ONCE_BEGIN {
1207 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1208 pa_log_debug(ngettext("snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
1209 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1210 "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1211 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1212 (unsigned long) k),
1213 (unsigned long) k,
1214 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1215 pa_strnull(dn));
1216 pa_xfree(dn);
1217 pa_alsa_dump(PA_LOG_DEBUG, pcm);
1218 } PA_ONCE_END;
1219
1220 /* Mhmm, let's try not to fail completely */
1221 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1222 }
1223
1224 return n;
1225 }
1226
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,bool capture)1227 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,
1228 bool capture) {
1229 ssize_t k;
1230 size_t abs_k;
1231 int err;
1232 snd_pcm_sframes_t avail = 0;
1233 #if (SND_LIB_VERSION >= ((1<<16)|(1<<8)|0)) /* API additions in 1.1.0 */
1234 snd_pcm_audio_tstamp_config_t tstamp_config;
1235 #endif
1236
1237 pa_assert(pcm);
1238 pa_assert(delay);
1239 pa_assert(hwbuf_size > 0);
1240 pa_assert(ss);
1241
1242 /* Some ALSA driver expose weird bugs, let's inform the user about
1243 * what is going on. We're going to get both the avail and delay values so
1244 * that we can compare and check them for capture.
1245 * This is done with snd_pcm_status() which provides
1246 * avail, delay and timestamp values in a single kernel call to improve
1247 * timer-based scheduling */
1248
1249 #if (SND_LIB_VERSION >= ((1<<16)|(1<<8)|0)) /* API additions in 1.1.0 */
1250
1251 /* The time stamp configuration needs to be set so that the
1252 * ALSA code will use the internal delay reported by the driver.
1253 * The time stamp configuration was introduced in alsa version 1.1.0. */
1254 tstamp_config.type_requested = 1; /* ALSA default time stamp type */
1255 tstamp_config.report_delay = 1;
1256 snd_pcm_status_set_audio_htstamp_config(status, &tstamp_config);
1257 #endif
1258
1259 if ((err = snd_pcm_status(pcm, status)) < 0)
1260 return err;
1261
1262 avail = snd_pcm_status_get_avail(status);
1263 *delay = snd_pcm_status_get_delay(status);
1264
1265 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1266
1267 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1268
1269 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1270 abs_k >= pa_bytes_per_second(ss)*10)) {
1271
1272 PA_ONCE_BEGIN {
1273 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1274 pa_log_debug(ngettext("snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s%lu ms).\n"
1275 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1276 "snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1277 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1278 (signed long) k),
1279 (signed long) k,
1280 k < 0 ? "-" : "",
1281 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1282 pa_strnull(dn));
1283 pa_xfree(dn);
1284 pa_alsa_dump(PA_LOG_DEBUG, pcm);
1285 } PA_ONCE_END;
1286
1287 /* Mhmm, let's try not to fail completely */
1288 if (k < 0)
1289 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1290 else
1291 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1292 }
1293
1294 if (capture) {
1295 abs_k = (size_t) avail * pa_frame_size(ss);
1296
1297 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1298 abs_k >= pa_bytes_per_second(ss)*10)) {
1299
1300 PA_ONCE_BEGIN {
1301 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1302 pa_log_debug(ngettext("snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
1303 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1304 "snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1305 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1306 (unsigned long) k),
1307 (unsigned long) k,
1308 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1309 pa_strnull(dn));
1310 pa_xfree(dn);
1311 pa_alsa_dump(PA_LOG_DEBUG, pcm);
1312 } PA_ONCE_END;
1313
1314 /* Mhmm, let's try not to fail completely */
1315 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1316 }
1317
1318 if (PA_UNLIKELY(*delay < avail)) {
1319 PA_ONCE_BEGIN {
1320 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1321 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1322 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1323 (unsigned long) *delay,
1324 (unsigned long) avail,
1325 pa_strnull(dn));
1326 pa_xfree(dn);
1327 pa_alsa_dump(PA_LOG_ERROR, pcm);
1328 } PA_ONCE_END;
1329
1330 /* try to fixup */
1331 *delay = avail;
1332 }
1333 }
1334
1335 return 0;
1336 }
1337
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)1338 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) {
1339 int r;
1340 snd_pcm_uframes_t before;
1341 size_t k;
1342
1343 pa_assert(pcm);
1344 pa_assert(areas);
1345 pa_assert(offset);
1346 pa_assert(frames);
1347 pa_assert(hwbuf_size > 0);
1348 pa_assert(ss);
1349
1350 before = *frames;
1351
1352 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1353
1354 if (r < 0)
1355 return r;
1356
1357 k = (size_t) *frames * pa_frame_size(ss);
1358
1359 if (PA_UNLIKELY(*frames > before ||
1360 k >= hwbuf_size * 3 ||
1361 k >= pa_bytes_per_second(ss)*10))
1362 PA_ONCE_BEGIN {
1363 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1364 pa_log_debug(ngettext("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
1365 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1366 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1367 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers.",
1368 (unsigned long) k),
1369 (unsigned long) k,
1370 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1371 pa_strnull(dn));
1372 pa_xfree(dn);
1373 pa_alsa_dump(PA_LOG_DEBUG, pcm);
1374 } PA_ONCE_END;
1375
1376 return r;
1377 }
1378
pa_alsa_get_driver_name(int card)1379 char *pa_alsa_get_driver_name(int card) {
1380 char *t, *m, *n;
1381
1382 pa_assert(card >= 0);
1383
1384 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1385 m = pa_readlink(t);
1386 pa_xfree(t);
1387
1388 if (!m)
1389 return NULL;
1390
1391 n = pa_xstrdup(pa_path_get_filename(m));
1392 pa_xfree(m);
1393
1394 return n;
1395 }
1396
pa_alsa_get_driver_name_by_pcm(snd_pcm_t * pcm)1397 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1398 int card;
1399 snd_pcm_info_t* info;
1400 snd_pcm_info_alloca(&info);
1401
1402 pa_assert(pcm);
1403
1404 if (snd_pcm_info(pcm, info) < 0)
1405 return NULL;
1406
1407 if ((card = snd_pcm_info_get_card(info)) < 0)
1408 return NULL;
1409
1410 return pa_alsa_get_driver_name(card);
1411 }
1412
pa_alsa_get_reserve_name(const char * device)1413 char *pa_alsa_get_reserve_name(const char *device) {
1414 const char *t;
1415 int i;
1416
1417 pa_assert(device);
1418
1419 if ((t = strchr(device, ':')))
1420 device = t+1;
1421
1422 if ((i = snd_card_get_index(device)) < 0) {
1423 int32_t k;
1424
1425 if (pa_atoi(device, &k) < 0)
1426 return NULL;
1427
1428 i = (int) k;
1429 }
1430
1431 return pa_sprintf_malloc("Audio%i", i);
1432 }
1433
dump_supported_rates(unsigned int * values)1434 static void dump_supported_rates(unsigned int* values)
1435 {
1436 pa_strbuf *buf;
1437 char *str;
1438 int i;
1439
1440 buf = pa_strbuf_new();
1441
1442 for (i = 0; values[i]; i++) {
1443 pa_strbuf_printf(buf, " %u", values[i]);
1444 }
1445
1446 str = pa_strbuf_to_string_free(buf);
1447 pa_log_debug("Supported rates:%s", str);
1448 pa_xfree(str);
1449 }
1450
pa_alsa_get_supported_rates(snd_pcm_t * pcm,unsigned int fallback_rate)1451 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1452 static unsigned int all_rates[] = { 8000, 11025, 12000,
1453 16000, 22050, 24000,
1454 32000, 44100, 48000,
1455 64000, 88200, 96000,
1456 128000, 176400, 192000,
1457 352800, 384000,
1458 705600, 768000 };
1459 bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
1460 snd_pcm_hw_params_t *hwparams;
1461 unsigned int i, j, n, *rates = NULL;
1462 int ret;
1463
1464 snd_pcm_hw_params_alloca(&hwparams);
1465
1466 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1467 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1468 return NULL;
1469 }
1470
1471 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1472 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1473 supported[i] = true;
1474 n++;
1475 }
1476 }
1477
1478 if (n > 0) {
1479 rates = pa_xnew(unsigned int, n + 1);
1480
1481 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1482 if (supported[i])
1483 rates[j++] = all_rates[i];
1484 }
1485
1486 rates[j] = 0;
1487 } else {
1488 rates = pa_xnew(unsigned int, 2);
1489
1490 rates[0] = fallback_rate;
1491 if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1492 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1493 pa_xfree(rates);
1494 return NULL;
1495 }
1496
1497 rates[1] = 0;
1498 }
1499
1500 dump_supported_rates(rates);
1501 return rates;
1502 }
1503
pa_alsa_get_supported_formats(snd_pcm_t * pcm,pa_sample_format_t fallback_format)1504 pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) {
1505 static const snd_pcm_format_t format_trans_to_pcm[] = {
1506 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
1507 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
1508 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
1509 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
1510 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
1511 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
1512 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
1513 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
1514 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
1515 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
1516 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
1517 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
1518 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
1519 };
1520 static const pa_sample_format_t all_formats[] = {
1521 PA_SAMPLE_U8,
1522 PA_SAMPLE_ALAW,
1523 PA_SAMPLE_ULAW,
1524 PA_SAMPLE_S16LE,
1525 PA_SAMPLE_S16BE,
1526 PA_SAMPLE_FLOAT32LE,
1527 PA_SAMPLE_FLOAT32BE,
1528 PA_SAMPLE_S32LE,
1529 PA_SAMPLE_S32BE,
1530 PA_SAMPLE_S24LE,
1531 PA_SAMPLE_S24BE,
1532 PA_SAMPLE_S24_32LE,
1533 PA_SAMPLE_S24_32BE,
1534 };
1535 bool supported[PA_ELEMENTSOF(all_formats)] = {
1536 false,
1537 };
1538 snd_pcm_hw_params_t *hwparams;
1539 unsigned int i, j, n;
1540 pa_sample_format_t *formats = NULL;
1541 int ret;
1542
1543 snd_pcm_hw_params_alloca(&hwparams);
1544
1545 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1546 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1547 return NULL;
1548 }
1549
1550 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_formats); i++) {
1551 if (snd_pcm_hw_params_test_format(pcm, hwparams, format_trans_to_pcm[all_formats[i]]) == 0) {
1552 supported[i] = true;
1553 n++;
1554 }
1555 }
1556
1557 if (n > 0) {
1558 formats = pa_xnew(pa_sample_format_t, n + 1);
1559
1560 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_formats); i++) {
1561 if (supported[i])
1562 formats[j++] = all_formats[i];
1563 }
1564
1565 formats[j] = PA_SAMPLE_MAX;
1566 } else {
1567 formats = pa_xnew(pa_sample_format_t, 2);
1568
1569 formats[0] = fallback_format;
1570 if ((ret = snd_pcm_hw_params_set_format(pcm, hwparams, format_trans_to_pcm[formats[0]])) < 0) {
1571 pa_log_debug("snd_pcm_hw_params_set_format() failed: %s", pa_alsa_strerror(ret));
1572 pa_xfree(formats);
1573 return NULL;
1574 }
1575
1576 formats[1] = PA_SAMPLE_MAX;
1577 }
1578
1579 return formats;
1580 }
1581
pa_alsa_pcm_is_hw(snd_pcm_t * pcm)1582 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1583 snd_pcm_info_t* info;
1584 snd_pcm_info_alloca(&info);
1585
1586 pa_assert(pcm);
1587
1588 if (snd_pcm_info(pcm, info) < 0)
1589 return false;
1590
1591 return snd_pcm_info_get_card(info) >= 0;
1592 }
1593
pa_alsa_pcm_is_modem(snd_pcm_t * pcm)1594 bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1595 snd_pcm_info_t* info;
1596 snd_pcm_info_alloca(&info);
1597
1598 pa_assert(pcm);
1599
1600 if (snd_pcm_info(pcm, info) < 0)
1601 return false;
1602
1603 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1604 }
1605
1606 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1607
pa_alsa_strerror(int errnum)1608 const char* pa_alsa_strerror(int errnum) {
1609 const char *original = NULL;
1610 char *translated, *t;
1611 char errbuf[128];
1612
1613 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1614 pa_xfree(t);
1615
1616 original = snd_strerror(errnum);
1617
1618 if (!original) {
1619 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1620 original = errbuf;
1621 }
1622
1623 if (!(translated = pa_locale_to_utf8(original))) {
1624 pa_log_warn("Unable to convert error string to locale, filtering.");
1625 translated = pa_utf8_filter(original);
1626 }
1627
1628 PA_STATIC_TLS_SET(cstrerror, translated);
1629
1630 return translated;
1631 }
1632
pa_alsa_may_tsched(bool want)1633 bool pa_alsa_may_tsched(bool want) {
1634
1635 if (!want)
1636 return false;
1637
1638 if (!pa_rtclock_hrtimer()) {
1639 /* We cannot depend on being woken up in time when the timers
1640 are inaccurate, so let's fallback to classic IO based playback
1641 then. */
1642 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1643 return false; }
1644
1645 if (pa_running_in_vm()) {
1646 /* We cannot depend on being woken up when we ask for in a VM,
1647 * so let's fallback to classic IO based playback then. */
1648 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1649 return false;
1650 }
1651
1652 return true;
1653 }
1654
1655 #define SND_MIXER_ELEM_PULSEAUDIO (SND_MIXER_ELEM_LAST + 10)
1656
pa_alsa_mixer_find(snd_mixer_t * mixer,snd_ctl_elem_iface_t iface,const char * name,unsigned int index,unsigned int device,unsigned int subdevice)1657 static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
1658 snd_ctl_elem_iface_t iface,
1659 const char *name,
1660 unsigned int index,
1661 unsigned int device,
1662 unsigned int subdevice) {
1663 snd_mixer_elem_t *elem;
1664
1665 for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) {
1666 snd_hctl_elem_t **_helem, *helem;
1667 if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_PULSEAUDIO)
1668 continue;
1669 _helem = snd_mixer_elem_get_private(elem);
1670 helem = *_helem;
1671 if (snd_hctl_elem_get_interface(helem) != iface)
1672 continue;
1673 if (!pa_streq(snd_hctl_elem_get_name(helem), name))
1674 continue;
1675 if (snd_hctl_elem_get_index(helem) != index)
1676 continue;
1677 if (snd_hctl_elem_get_device(helem) != device)
1678 continue;
1679 if (snd_hctl_elem_get_subdevice(helem) != subdevice)
1680 continue;
1681 return elem;
1682 }
1683 return NULL;
1684 }
1685
pa_alsa_mixer_find_card(snd_mixer_t * mixer,struct pa_alsa_mixer_id * alsa_id,unsigned int device)1686 snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) {
1687 return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device, 0);
1688 }
1689
pa_alsa_mixer_find_pcm(snd_mixer_t * mixer,const char * name,unsigned int device)1690 snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {
1691 return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_PCM, name, 0, device, 0);
1692 }
1693
mixer_class_compare(const snd_mixer_elem_t * c1,const snd_mixer_elem_t * c2)1694 static int mixer_class_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
1695 {
1696 /* Dummy compare function */
1697 return c1 == c2 ? 0 : (c1 > c2 ? 1 : -1);
1698 }
1699
mixer_melem_free(snd_mixer_elem_t * elem)1700 static void mixer_melem_free(snd_mixer_elem_t *elem)
1701 {
1702 snd_hctl_elem_t **_helem;
1703 _helem = snd_mixer_elem_get_private(elem);
1704 pa_xfree(_helem);
1705 }
1706
mixer_class_event(snd_mixer_class_t * class,unsigned int mask,snd_hctl_elem_t * helem,snd_mixer_elem_t * melem)1707 static int mixer_class_event(snd_mixer_class_t *class, unsigned int mask,
1708 snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
1709 {
1710 int err;
1711 const char *name = snd_hctl_elem_get_name(helem);
1712 snd_hctl_elem_t **_helem;
1713 /* NOTE: The remove event is defined as '~0U`. */
1714 if (mask == SND_CTL_EVENT_MASK_REMOVE) {
1715 /* NOTE: Unless we remove the pointer to melem from the linked-list at
1716 * private_data of helem, an assertion will be hit in alsa-lib since
1717 * the list is not empty. */
1718 _helem = snd_mixer_elem_get_private(melem);
1719 *_helem = NULL;
1720 snd_mixer_elem_detach(melem, helem);
1721 } else if (mask & SND_CTL_EVENT_MASK_ADD) {
1722 snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
1723 if (iface == SND_CTL_ELEM_IFACE_CARD || iface == SND_CTL_ELEM_IFACE_PCM) {
1724 snd_mixer_t *mixer = snd_mixer_class_get_mixer(class);
1725 snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
1726 const char *name = snd_hctl_elem_get_name(helem);
1727 const int index = snd_hctl_elem_get_index(helem);
1728 const int device = snd_hctl_elem_get_device(helem);
1729 const int subdevice = snd_hctl_elem_get_subdevice(helem);
1730 snd_mixer_elem_t *new_melem;
1731 bool found = true;
1732
1733 new_melem = pa_alsa_mixer_find(mixer, iface, name, index, device, subdevice);
1734 if (!new_melem) {
1735 _helem = pa_xmalloc(sizeof(snd_hctl_elem_t *));
1736 *_helem = helem;
1737 /* Put the hctl pointer as our private data - it will be useful for callbacks */
1738 if ((err = snd_mixer_elem_new(&new_melem, SND_MIXER_ELEM_PULSEAUDIO, 0, _helem, mixer_melem_free)) < 0) {
1739 pa_log_warn("snd_mixer_elem_new failed: %s", pa_alsa_strerror(err));
1740 return 0;
1741 }
1742 found = false;
1743 } else {
1744 _helem = snd_mixer_elem_get_private(new_melem);
1745 if (_helem) {
1746 char *s1, *s2;
1747 snd_ctl_elem_id_t *id1, *id2;
1748 snd_ctl_elem_id_alloca(&id1);
1749 snd_ctl_elem_id_alloca(&id2);
1750 snd_hctl_elem_get_id(helem, id1);
1751 snd_hctl_elem_get_id(*_helem, id2);
1752 s1 = snd_ctl_ascii_elem_id_get(id1);
1753 s2 = snd_ctl_ascii_elem_id_get(id2);
1754 pa_log_warn("mixer_class_event - duplicate mixer controls: %s | %s", s1, s2);
1755 free(s2);
1756 free(s1);
1757 return 0;
1758 }
1759 *_helem = helem;
1760 }
1761
1762 if ((err = snd_mixer_elem_attach(new_melem, helem)) < 0) {
1763 pa_log_warn("snd_mixer_elem_attach failed: %s", pa_alsa_strerror(err));
1764 snd_mixer_elem_free(melem);
1765 return 0;
1766 }
1767
1768 if (!found) {
1769 if ((err = snd_mixer_elem_add(new_melem, class)) < 0) {
1770 pa_log_warn("snd_mixer_elem_add failed: %s", pa_alsa_strerror(err));
1771 return 0;
1772 }
1773 }
1774 }
1775 }
1776 else if (mask & SND_CTL_EVENT_MASK_VALUE) {
1777 snd_mixer_elem_value(melem); /* Calls the element callback */
1778 return 0;
1779 }
1780 else
1781 pa_log_info("Got an unknown mixer class event for %s: mask 0x%x", name, mask);
1782
1783 return 0;
1784 }
1785
prepare_mixer(snd_mixer_t * mixer,const char * dev,snd_hctl_t * hctl)1786 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t *hctl) {
1787 int err;
1788 snd_mixer_class_t *class;
1789
1790 pa_assert(mixer);
1791 pa_assert(dev);
1792
1793 if ((err = snd_mixer_attach_hctl(mixer, hctl)) < 0) {
1794 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1795 return -1;
1796 }
1797
1798 if (snd_mixer_class_malloc(&class)) {
1799 pa_log_info("Failed to allocate mixer class for %s", dev);
1800 return -1;
1801 }
1802 snd_mixer_class_set_event(class, mixer_class_event);
1803 snd_mixer_class_set_compare(class, mixer_class_compare);
1804 if ((err = snd_mixer_class_register(class, mixer)) < 0) {
1805 pa_log_info("Unable register mixer class for %s: %s", dev, pa_alsa_strerror(err));
1806 snd_mixer_class_free(class);
1807 return -1;
1808 }
1809 /* From here on, the mixer class is deallocated by alsa on snd_mixer_close/free. */
1810
1811 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1812 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1813 return -1;
1814 }
1815
1816 if ((err = snd_mixer_load(mixer)) < 0) {
1817 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1818 return -1;
1819 }
1820
1821 pa_log_info("Successfully attached to mixer '%s'", dev);
1822 return 0;
1823 }
1824
pa_alsa_open_mixer(pa_hashmap * mixers,int alsa_card_index,bool probe)1825 snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe) {
1826 char *md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1827 snd_mixer_t *m = pa_alsa_open_mixer_by_name(mixers, md, probe);
1828 pa_xfree(md);
1829 return m;
1830 }
1831
pa_alsa_create_mixer(pa_hashmap * mixers,const char * dev,snd_mixer_t * m,bool probe)1832 pa_alsa_mixer *pa_alsa_create_mixer(pa_hashmap *mixers, const char *dev, snd_mixer_t *m, bool probe) {
1833 pa_alsa_mixer *pm;
1834
1835 pm = pa_xnew0(pa_alsa_mixer, 1);
1836 if (pm == NULL)
1837 return NULL;
1838
1839 pm->used_for_probe_only = probe;
1840 pm->mixer_handle = m;
1841 pa_hashmap_put(mixers, pa_xstrdup(dev), pm);
1842 return pm;
1843 }
1844
pa_alsa_open_mixer_by_name(pa_hashmap * mixers,const char * dev,bool probe)1845 snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, bool probe) {
1846 int err;
1847 snd_mixer_t *m;
1848 snd_hctl_t *hctl;
1849 pa_alsa_mixer *pm;
1850
1851 pa_assert(mixers);
1852 pa_assert(dev);
1853
1854 pm = pa_hashmap_get(mixers, dev);
1855 if (pm) {
1856 if (!probe)
1857 pm->used_for_probe_only = false;
1858 return pm->mixer_handle;
1859 }
1860
1861 if ((err = snd_mixer_open(&m, 0)) < 0) {
1862 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1863 return NULL;
1864 }
1865
1866 err = snd_hctl_open(&hctl, dev, 0);
1867 if (err < 0) {
1868 pa_log("Error opening hctl device: %s", pa_alsa_strerror(err));
1869 goto __close;
1870 }
1871
1872 if (prepare_mixer(m, dev, hctl) >= 0) {
1873 /* get the ALSA card number (index) and ID (alias) and create two identical mixers */
1874 char *p, *dev2, *dev_idx, *dev_id;
1875 snd_ctl_card_info_t *info;
1876 snd_ctl_card_info_alloca(&info);
1877 err = snd_ctl_card_info(snd_hctl_ctl(hctl), info);
1878 if (err < 0)
1879 goto __std;
1880 dev2 = pa_xstrdup(dev);
1881 if (dev2 == NULL)
1882 goto __close;
1883 p = strchr(dev2, ':');
1884 /* sanity check - only hw: devices */
1885 if (p == NULL || (p - dev2) < 2 || !pa_strneq(p - 2, "hw:", 3)) {
1886 pa_xfree(dev2);
1887 goto __std;
1888 }
1889 *p = '\0';
1890 dev_idx = pa_sprintf_malloc("%s:%u", dev2, snd_ctl_card_info_get_card(info));
1891 dev_id = pa_sprintf_malloc("%s:%s", dev2, snd_ctl_card_info_get_id(info));
1892 pa_log_debug("ALSA alias mixers: %s = %s", dev_idx, dev_id);
1893 if (dev_idx && dev_id && (strcmp(dev, dev_idx) == 0 || strcmp(dev, dev_id) == 0)) {
1894 pm = pa_alsa_create_mixer(mixers, dev_idx, m, probe);
1895 if (pm) {
1896 pa_alsa_mixer *pm2;
1897 pm2 = pa_alsa_create_mixer(mixers, dev_id, m, probe);
1898 if (pm2) {
1899 pm->alias = pm2;
1900 pm2->alias = pm;
1901 }
1902 }
1903 }
1904 pa_xfree(dev_id);
1905 pa_xfree(dev_idx);
1906 pa_xfree(dev2);
1907 __std:
1908 if (pm == NULL)
1909 pm = pa_alsa_create_mixer(mixers, dev, m, probe);
1910 if (pm)
1911 return m;
1912 }
1913
1914 __close:
1915 snd_mixer_close(m);
1916 return NULL;
1917 }
1918
pa_alsa_open_mixer_for_pcm(pa_hashmap * mixers,snd_pcm_t * pcm,bool probe)1919 snd_mixer_t *pa_alsa_open_mixer_for_pcm(pa_hashmap *mixers, snd_pcm_t *pcm, bool probe) {
1920 snd_pcm_info_t* info;
1921 snd_pcm_info_alloca(&info);
1922
1923 pa_assert(pcm);
1924
1925 if (snd_pcm_info(pcm, info) >= 0) {
1926 int card_idx;
1927
1928 if ((card_idx = snd_pcm_info_get_card(info)) >= 0)
1929 return pa_alsa_open_mixer(mixers, card_idx, probe);
1930 }
1931
1932 return NULL;
1933 }
1934
pa_alsa_mixer_set_fdlist(pa_hashmap * mixers,snd_mixer_t * mixer_handle,pa_mainloop_api * ml)1935 void pa_alsa_mixer_set_fdlist(pa_hashmap *mixers, snd_mixer_t *mixer_handle, pa_mainloop_api *ml)
1936 {
1937 pa_alsa_mixer *pm;
1938 void *state;
1939
1940 PA_HASHMAP_FOREACH(pm, mixers, state)
1941 if (pm->mixer_handle == mixer_handle) {
1942 pm->used_for_probe_only = false;
1943 if (!pm->fdl) {
1944 pm->fdl = pa_alsa_fdlist_new();
1945 if (pm->fdl)
1946 pa_alsa_fdlist_set_handle(pm->fdl, pm->mixer_handle, NULL, ml);
1947 }
1948 }
1949 }
1950
pa_alsa_mixer_free(pa_alsa_mixer * mixer)1951 void pa_alsa_mixer_free(pa_alsa_mixer *mixer)
1952 {
1953 if (mixer->fdl)
1954 pa_alsa_fdlist_free(mixer->fdl);
1955 if (mixer->mixer_handle && mixer->alias == NULL)
1956 snd_mixer_close(mixer->mixer_handle);
1957 if (mixer->alias)
1958 mixer->alias->alias = NULL;
1959 pa_xfree(mixer);
1960 }
1961
pa_alsa_get_hdmi_eld(snd_hctl_elem_t * elem,pa_hdmi_eld * eld)1962 int pa_alsa_get_hdmi_eld(snd_hctl_elem_t *elem, pa_hdmi_eld *eld) {
1963
1964 /* The ELD format is specific to HDA Intel sound cards and defined in the
1965 HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1966 int err;
1967 snd_ctl_elem_info_t *info;
1968 snd_ctl_elem_value_t *value;
1969 uint8_t *elddata;
1970 unsigned int eldsize, mnl;
1971 unsigned int device;
1972
1973 pa_assert(eld != NULL);
1974 pa_assert(elem != NULL);
1975
1976 /* Does it have any contents? */
1977 snd_ctl_elem_info_alloca(&info);
1978 snd_ctl_elem_value_alloca(&value);
1979 if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1980 (err = snd_hctl_elem_read(elem, value)) < 0) {
1981 pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1982 return -1;
1983 }
1984
1985 device = snd_hctl_elem_get_device(elem);
1986 eldsize = snd_ctl_elem_info_get_count(info);
1987 elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1988 if (elddata == NULL || eldsize == 0) {
1989 pa_log_debug("ELD info empty (for device=%d)", device);
1990 return -1;
1991 }
1992 if (eldsize < 20 || eldsize > 256) {
1993 pa_log_debug("ELD info has wrong size (for device=%d)", device);
1994 return -1;
1995 }
1996
1997 /* Try to fetch monitor name */
1998 mnl = elddata[4] & 0x1f;
1999 if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
2000 pa_log_debug("No monitor name in ELD info (for device=%d)", device);
2001 mnl = 0;
2002 }
2003 memcpy(eld->monitor_name, &elddata[20], mnl);
2004 eld->monitor_name[mnl] = '\0';
2005 if (mnl)
2006 pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
2007
2008 return 0;
2009 }
2010