]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
alsa: Disable timer-scheduling for PCMs with the BATCH flag
[pulseaudio] / src / modules / alsa / alsa-util.c
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, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <sys/types.h>
28 #include <asoundlib.h>
29
30 #include <pulse/sample.h>
31 #include <pulse/xmalloc.h>
32 #include <pulse/timeval.h>
33 #include <pulse/util.h>
34 #include <pulse/utf8.h>
35
36 #include <pulsecore/i18n.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/atomic.h>
41 #include <pulsecore/core-error.h>
42 #include <pulsecore/thread.h>
43 #include <pulsecore/conf-parser.h>
44 #include <pulsecore/core-rtclock.h>
45
46 #include "alsa-util.h"
47 #include "alsa-mixer.h"
48
49 #ifdef HAVE_UDEV
50 #include "udev-util.h"
51 #endif
52
53 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
54
55 static const snd_pcm_format_t format_trans[] = {
56 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
57 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
58 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
59 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
60 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
61 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
62 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
63 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
64 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
65 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
66 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
67 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
68 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
69 };
70
71 static const pa_sample_format_t try_order[] = {
72 PA_SAMPLE_FLOAT32NE,
73 PA_SAMPLE_FLOAT32RE,
74 PA_SAMPLE_S32NE,
75 PA_SAMPLE_S32RE,
76 PA_SAMPLE_S24_32NE,
77 PA_SAMPLE_S24_32RE,
78 PA_SAMPLE_S24NE,
79 PA_SAMPLE_S24RE,
80 PA_SAMPLE_S16NE,
81 PA_SAMPLE_S16RE,
82 PA_SAMPLE_ALAW,
83 PA_SAMPLE_ULAW,
84 PA_SAMPLE_U8
85 };
86
87 unsigned i;
88 int ret;
89
90 pa_assert(pcm_handle);
91 pa_assert(hwparams);
92 pa_assert(f);
93
94 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
95 return ret;
96
97 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
98 snd_pcm_format_description(format_trans[*f]),
99 pa_alsa_strerror(ret));
100
101 if (*f == PA_SAMPLE_FLOAT32BE)
102 *f = PA_SAMPLE_FLOAT32LE;
103 else if (*f == PA_SAMPLE_FLOAT32LE)
104 *f = PA_SAMPLE_FLOAT32BE;
105 else if (*f == PA_SAMPLE_S24BE)
106 *f = PA_SAMPLE_S24LE;
107 else if (*f == PA_SAMPLE_S24LE)
108 *f = PA_SAMPLE_S24BE;
109 else if (*f == PA_SAMPLE_S24_32BE)
110 *f = PA_SAMPLE_S24_32LE;
111 else if (*f == PA_SAMPLE_S24_32LE)
112 *f = PA_SAMPLE_S24_32BE;
113 else if (*f == PA_SAMPLE_S16BE)
114 *f = PA_SAMPLE_S16LE;
115 else if (*f == PA_SAMPLE_S16LE)
116 *f = PA_SAMPLE_S16BE;
117 else if (*f == PA_SAMPLE_S32BE)
118 *f = PA_SAMPLE_S32LE;
119 else if (*f == PA_SAMPLE_S32LE)
120 *f = PA_SAMPLE_S32BE;
121 else
122 goto try_auto;
123
124 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
125 return ret;
126
127 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
128 snd_pcm_format_description(format_trans[*f]),
129 pa_alsa_strerror(ret));
130
131 try_auto:
132
133 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
134 *f = try_order[i];
135
136 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
137 return ret;
138
139 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
140 snd_pcm_format_description(format_trans[*f]),
141 pa_alsa_strerror(ret));
142 }
143
144 return -1;
145 }
146
147 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
148 snd_pcm_uframes_t s;
149 int d, ret;
150
151 pa_assert(pcm_handle);
152 pa_assert(hwparams);
153
154 s = size;
155 d = 0;
156 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
157 s = size;
158 d = -1;
159 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
160 s = size;
161 d = 1;
162 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
163 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
164 return ret;
165 }
166 }
167 }
168
169 return 0;
170 }
171
172 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
173 int ret;
174
175 pa_assert(pcm_handle);
176 pa_assert(hwparams);
177
178 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
179 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
180 return ret;
181 }
182
183 return 0;
184 }
185
186 /* Set the hardware parameters of the given ALSA device. Returns the
187 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
188 int pa_alsa_set_hw_params(
189 snd_pcm_t *pcm_handle,
190 pa_sample_spec *ss,
191 snd_pcm_uframes_t *period_size,
192 snd_pcm_uframes_t *buffer_size,
193 snd_pcm_uframes_t tsched_size,
194 bool *use_mmap,
195 bool *use_tsched,
196 bool require_exact_channel_number) {
197
198 int ret = -1;
199 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
200 int dir;
201 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
202 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
203 bool _use_mmap = use_mmap && *use_mmap;
204 bool _use_tsched = use_tsched && *use_tsched;
205 pa_sample_spec _ss = *ss;
206
207 pa_assert(pcm_handle);
208 pa_assert(ss);
209
210 snd_pcm_hw_params_alloca(&hwparams);
211 snd_pcm_hw_params_alloca(&hwparams_copy);
212
213 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
214 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
215 goto finish;
216 }
217
218 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
219 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
220 goto finish;
221 }
222
223 if (_use_mmap) {
224
225 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
226
227 /* mmap() didn't work, fall back to interleaved */
228
229 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
230 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
231 goto finish;
232 }
233
234 _use_mmap = false;
235 }
236
237 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
238 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
239 goto finish;
240 }
241
242 if (!_use_mmap)
243 _use_tsched = false;
244
245 if (!pa_alsa_pcm_is_hw(pcm_handle))
246 _use_tsched = false;
247
248 /* The PCM pointer is only updated with period granularity */
249 if (snd_pcm_hw_params_is_batch(hwparams))
250 _use_tsched = false;
251
252 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
253 if (_use_tsched) {
254
255 /* try to disable period wakeups if hardware can do so */
256 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
257
258 if ((ret = snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, false)) < 0)
259 /* don't bail, keep going with default mode with period wakeups */
260 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret));
261 else
262 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
263 } else
264 pa_log_info("cannot disable ALSA period wakeups");
265 }
266 #endif
267
268 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
269 goto finish;
270
271 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
272 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
273 goto finish;
274 }
275
276 /* We ignore very small sampling rate deviations */
277 if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
278 _ss.rate = ss->rate;
279
280 if (require_exact_channel_number) {
281 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
282 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
283 goto finish;
284 }
285 } else {
286 unsigned int c = _ss.channels;
287
288 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
289 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
290 goto finish;
291 }
292
293 _ss.channels = c;
294 }
295
296 if (_use_tsched && tsched_size > 0) {
297 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
298 _period_size = _buffer_size;
299 } else {
300 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
301 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
302 }
303
304 if (_buffer_size > 0 || _period_size > 0) {
305 snd_pcm_uframes_t max_frames = 0;
306
307 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
308 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
309 else
310 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
311
312 /* Some ALSA drivers really don't like if we set the buffer
313 * size first and the number of periods second (which would
314 * make a lot more sense to me). So, try a few combinations
315 * before we give up. */
316
317 if (_buffer_size > 0 && _period_size > 0) {
318 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
319
320 /* First try: set buffer size first, followed by period size */
321 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
322 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
323 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
324 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
325 goto success;
326 }
327
328 /* Second try: set period size first, followed by buffer size */
329 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
330 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
331 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
332 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);
333 goto success;
334 }
335 }
336
337 if (_buffer_size > 0) {
338 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
339
340 /* Third try: set only buffer size */
341 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
342 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
343 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);
344 goto success;
345 }
346 }
347
348 if (_period_size > 0) {
349 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
350
351 /* Fourth try: set only period size */
352 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
353 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
354 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);
355 goto success;
356 }
357 }
358 }
359
360 pa_log_debug("Set neither period nor buffer size.");
361
362 /* Last chance, set nothing */
363 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
364 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
365 goto finish;
366 }
367
368 success:
369
370 if (ss->rate != _ss.rate)
371 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
372
373 if (ss->channels != _ss.channels)
374 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
375
376 if (ss->format != _ss.format)
377 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));
378
379 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
380 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
381 goto finish;
382 }
383
384 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
385 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
386 goto finish;
387 }
388
389 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
390 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
391 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
392 goto finish;
393 }
394
395 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
396 if (_use_tsched) {
397 unsigned int no_wakeup;
398 /* see if period wakeups were disabled */
399 snd_pcm_hw_params_get_period_wakeup(pcm_handle, hwparams, &no_wakeup);
400 if (no_wakeup == 0)
401 pa_log_info("ALSA period wakeups disabled");
402 else
403 pa_log_info("ALSA period wakeups were not disabled");
404 }
405 #endif
406
407 ss->rate = _ss.rate;
408 ss->channels = _ss.channels;
409 ss->format = _ss.format;
410
411 pa_assert(_period_size > 0);
412 pa_assert(_buffer_size > 0);
413
414 if (buffer_size)
415 *buffer_size = _buffer_size;
416
417 if (period_size)
418 *period_size = _period_size;
419
420 if (use_mmap)
421 *use_mmap = _use_mmap;
422
423 if (use_tsched)
424 *use_tsched = _use_tsched;
425
426 ret = 0;
427
428 finish:
429
430 return ret;
431 }
432
433 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
434 snd_pcm_sw_params_t *swparams;
435 snd_pcm_uframes_t boundary;
436 int err;
437
438 pa_assert(pcm);
439
440 snd_pcm_sw_params_alloca(&swparams);
441
442 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
443 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
444 return err;
445 }
446
447 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
448 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
449 return err;
450 }
451
452 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
453 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
454 return err;
455 }
456
457 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
458 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
459 return err;
460 }
461
462 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
463 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
464 return err;
465 }
466
467 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
468 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
469 return err;
470 }
471
472 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
473 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
474 return err;
475 }
476
477 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
478 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
479 return err;
480 }
481
482 return 0;
483 }
484
485 snd_pcm_t *pa_alsa_open_by_device_id_auto(
486 const char *dev_id,
487 char **dev,
488 pa_sample_spec *ss,
489 pa_channel_map* map,
490 int mode,
491 snd_pcm_uframes_t *period_size,
492 snd_pcm_uframes_t *buffer_size,
493 snd_pcm_uframes_t tsched_size,
494 bool *use_mmap,
495 bool *use_tsched,
496 pa_alsa_profile_set *ps,
497 pa_alsa_mapping **mapping) {
498
499 char *d;
500 snd_pcm_t *pcm_handle;
501 void *state;
502 pa_alsa_mapping *m;
503
504 pa_assert(dev_id);
505 pa_assert(dev);
506 pa_assert(ss);
507 pa_assert(map);
508 pa_assert(ps);
509
510 /* First we try to find a device string with a superset of the
511 * requested channel map. We iterate through our device table from
512 * top to bottom and take the first that matches. If we didn't
513 * find a working device that way, we iterate backwards, and check
514 * all devices that do not provide a superset of the requested
515 * channel map.*/
516
517 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
518 if (!pa_channel_map_superset(&m->channel_map, map))
519 continue;
520
521 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
522
523 pcm_handle = pa_alsa_open_by_device_id_mapping(
524 dev_id,
525 dev,
526 ss,
527 map,
528 mode,
529 period_size,
530 buffer_size,
531 tsched_size,
532 use_mmap,
533 use_tsched,
534 m);
535
536 if (pcm_handle) {
537 if (mapping)
538 *mapping = m;
539
540 return pcm_handle;
541 }
542 }
543
544 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
545 if (pa_channel_map_superset(&m->channel_map, map))
546 continue;
547
548 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
549
550 pcm_handle = pa_alsa_open_by_device_id_mapping(
551 dev_id,
552 dev,
553 ss,
554 map,
555 mode,
556 period_size,
557 buffer_size,
558 tsched_size,
559 use_mmap,
560 use_tsched,
561 m);
562
563 if (pcm_handle) {
564 if (mapping)
565 *mapping = m;
566
567 return pcm_handle;
568 }
569 }
570
571 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
572 d = pa_sprintf_malloc("hw:%s", dev_id);
573 pa_log_debug("Trying %s as last resort...", d);
574 pcm_handle = pa_alsa_open_by_device_string(
575 d,
576 dev,
577 ss,
578 map,
579 mode,
580 period_size,
581 buffer_size,
582 tsched_size,
583 use_mmap,
584 use_tsched,
585 false);
586 pa_xfree(d);
587
588 if (pcm_handle && mapping)
589 *mapping = NULL;
590
591 return pcm_handle;
592 }
593
594 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
595 const char *dev_id,
596 char **dev,
597 pa_sample_spec *ss,
598 pa_channel_map* map,
599 int mode,
600 snd_pcm_uframes_t *period_size,
601 snd_pcm_uframes_t *buffer_size,
602 snd_pcm_uframes_t tsched_size,
603 bool *use_mmap,
604 bool *use_tsched,
605 pa_alsa_mapping *m) {
606
607 snd_pcm_t *pcm_handle;
608 pa_sample_spec try_ss;
609 pa_channel_map try_map;
610
611 pa_assert(dev_id);
612 pa_assert(dev);
613 pa_assert(ss);
614 pa_assert(map);
615 pa_assert(m);
616
617 try_ss.channels = m->channel_map.channels;
618 try_ss.rate = ss->rate;
619 try_ss.format = ss->format;
620 try_map = m->channel_map;
621
622 pcm_handle = pa_alsa_open_by_template(
623 m->device_strings,
624 dev_id,
625 dev,
626 &try_ss,
627 &try_map,
628 mode,
629 period_size,
630 buffer_size,
631 tsched_size,
632 use_mmap,
633 use_tsched,
634 pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
635
636 if (!pcm_handle)
637 return NULL;
638
639 *ss = try_ss;
640 *map = try_map;
641 pa_assert(map->channels == ss->channels);
642
643 return pcm_handle;
644 }
645
646 snd_pcm_t *pa_alsa_open_by_device_string(
647 const char *device,
648 char **dev,
649 pa_sample_spec *ss,
650 pa_channel_map* map,
651 int mode,
652 snd_pcm_uframes_t *period_size,
653 snd_pcm_uframes_t *buffer_size,
654 snd_pcm_uframes_t tsched_size,
655 bool *use_mmap,
656 bool *use_tsched,
657 bool require_exact_channel_number) {
658
659 int err;
660 char *d;
661 snd_pcm_t *pcm_handle;
662 bool reformat = false;
663
664 pa_assert(device);
665 pa_assert(ss);
666 pa_assert(map);
667
668 d = pa_xstrdup(device);
669
670 for (;;) {
671 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
672
673 if ((err = snd_pcm_open(&pcm_handle, d, mode,
674 SND_PCM_NONBLOCK|
675 SND_PCM_NO_AUTO_RESAMPLE|
676 SND_PCM_NO_AUTO_CHANNELS|
677 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
678 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
679 goto fail;
680 }
681
682 pa_log_debug("Managed to open %s", d);
683
684 if ((err = pa_alsa_set_hw_params(
685 pcm_handle,
686 ss,
687 period_size,
688 buffer_size,
689 tsched_size,
690 use_mmap,
691 use_tsched,
692 require_exact_channel_number)) < 0) {
693
694 if (!reformat) {
695 reformat = true;
696
697 snd_pcm_close(pcm_handle);
698 continue;
699 }
700
701 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
702 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
703 char *t;
704
705 t = pa_sprintf_malloc("plug:%s", d);
706 pa_xfree(d);
707 d = t;
708
709 reformat = false;
710
711 snd_pcm_close(pcm_handle);
712 continue;
713 }
714
715 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
716 snd_pcm_close(pcm_handle);
717
718 goto fail;
719 }
720
721 if (dev)
722 *dev = d;
723 else
724 pa_xfree(d);
725
726 if (ss->channels != map->channels)
727 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
728
729 return pcm_handle;
730 }
731
732 fail:
733 pa_xfree(d);
734
735 return NULL;
736 }
737
738 snd_pcm_t *pa_alsa_open_by_template(
739 char **template,
740 const char *dev_id,
741 char **dev,
742 pa_sample_spec *ss,
743 pa_channel_map* map,
744 int mode,
745 snd_pcm_uframes_t *period_size,
746 snd_pcm_uframes_t *buffer_size,
747 snd_pcm_uframes_t tsched_size,
748 bool *use_mmap,
749 bool *use_tsched,
750 bool require_exact_channel_number) {
751
752 snd_pcm_t *pcm_handle;
753 char **i;
754
755 for (i = template; *i; i++) {
756 char *d;
757
758 d = pa_replace(*i, "%f", dev_id);
759
760 pcm_handle = pa_alsa_open_by_device_string(
761 d,
762 dev,
763 ss,
764 map,
765 mode,
766 period_size,
767 buffer_size,
768 tsched_size,
769 use_mmap,
770 use_tsched,
771 require_exact_channel_number);
772
773 pa_xfree(d);
774
775 if (pcm_handle)
776 return pcm_handle;
777 }
778
779 return NULL;
780 }
781
782 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
783 int err;
784 snd_output_t *out;
785
786 pa_assert(pcm);
787
788 pa_assert_se(snd_output_buffer_open(&out) == 0);
789
790 if ((err = snd_pcm_dump(pcm, out)) < 0)
791 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
792 else {
793 char *s = NULL;
794 snd_output_buffer_string(out, &s);
795 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
796 }
797
798 pa_assert_se(snd_output_close(out) == 0);
799 }
800
801 void pa_alsa_dump_status(snd_pcm_t *pcm) {
802 int err;
803 snd_output_t *out;
804 snd_pcm_status_t *status;
805 char *s = NULL;
806
807 pa_assert(pcm);
808
809 snd_pcm_status_alloca(&status);
810
811 if ((err = snd_output_buffer_open(&out)) < 0) {
812 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
813 return;
814 }
815
816 if ((err = snd_pcm_status(pcm, status)) < 0) {
817 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
818 goto finish;
819 }
820
821 if ((err = snd_pcm_status_dump(status, out)) < 0) {
822 pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err));
823 goto finish;
824 }
825
826 snd_output_buffer_string(out, &s);
827 pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s));
828
829 finish:
830
831 snd_output_close(out);
832 }
833
834 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
835 va_list ap;
836 char *alsa_file;
837
838 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
839
840 va_start(ap, fmt);
841
842 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
843
844 va_end(ap);
845
846 pa_xfree(alsa_file);
847 }
848
849 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
850
851 void pa_alsa_refcnt_inc(void) {
852 /* This is not really thread safe, but we do our best */
853
854 if (pa_atomic_inc(&n_error_handler_installed) == 0)
855 snd_lib_error_set_handler(alsa_error_handler);
856 }
857
858 void pa_alsa_refcnt_dec(void) {
859 int r;
860
861 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
862
863 if (r == 1) {
864 snd_lib_error_set_handler(NULL);
865 snd_config_update_free_global();
866 }
867 }
868
869 bool pa_alsa_init_description(pa_proplist *p) {
870 const char *d, *k;
871 pa_assert(p);
872
873 if (pa_device_init_description(p))
874 return true;
875
876 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
877 d = pa_proplist_gets(p, "alsa.name");
878
879 if (!d)
880 return false;
881
882 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
883
884 if (d && k)
885 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
886 else if (d)
887 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
888
889 return false;
890 }
891
892 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
893 char *cn, *lcn, *dn;
894
895 pa_assert(p);
896 pa_assert(card >= 0);
897
898 pa_proplist_setf(p, "alsa.card", "%i", card);
899
900 if (snd_card_get_name(card, &cn) >= 0) {
901 pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
902 free(cn);
903 }
904
905 if (snd_card_get_longname(card, &lcn) >= 0) {
906 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
907 free(lcn);
908 }
909
910 if ((dn = pa_alsa_get_driver_name(card))) {
911 pa_proplist_sets(p, "alsa.driver_name", dn);
912 pa_xfree(dn);
913 }
914
915 #ifdef HAVE_UDEV
916 pa_udev_get_info(card, p);
917 #endif
918 }
919
920 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
921
922 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
923 [SND_PCM_CLASS_GENERIC] = "generic",
924 [SND_PCM_CLASS_MULTI] = "multi",
925 [SND_PCM_CLASS_MODEM] = "modem",
926 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
927 };
928 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
929 [SND_PCM_CLASS_GENERIC] = "sound",
930 [SND_PCM_CLASS_MULTI] = NULL,
931 [SND_PCM_CLASS_MODEM] = "modem",
932 [SND_PCM_CLASS_DIGITIZER] = NULL
933 };
934 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
935 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
936 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
937 };
938
939 snd_pcm_class_t class;
940 snd_pcm_subclass_t subclass;
941 const char *n, *id, *sdn;
942 int card;
943
944 pa_assert(p);
945 pa_assert(pcm_info);
946
947 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
948
949 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
950 if (class_table[class])
951 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
952 if (alsa_class_table[class])
953 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
954 }
955
956 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
957 if (alsa_subclass_table[subclass])
958 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
959
960 if ((n = snd_pcm_info_get_name(pcm_info))) {
961 char *t = pa_xstrdup(n);
962 pa_proplist_sets(p, "alsa.name", pa_strip(t));
963 pa_xfree(t);
964 }
965
966 if ((id = snd_pcm_info_get_id(pcm_info)))
967 pa_proplist_sets(p, "alsa.id", id);
968
969 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
970 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
971 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
972
973 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
974
975 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
976 pa_alsa_init_proplist_card(c, p, card);
977 }
978
979 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
980 snd_pcm_hw_params_t *hwparams;
981 snd_pcm_info_t *info;
982 int bits, err;
983
984 snd_pcm_hw_params_alloca(&hwparams);
985 snd_pcm_info_alloca(&info);
986
987 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
988 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
989 else {
990
991 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
992 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
993 }
994
995 if ((err = snd_pcm_info(pcm, info)) < 0)
996 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
997 else
998 pa_alsa_init_proplist_pcm_info(c, p, info);
999 }
1000
1001 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1002 int err;
1003 snd_ctl_t *ctl;
1004 snd_ctl_card_info_t *info;
1005 const char *t;
1006
1007 pa_assert(p);
1008
1009 snd_ctl_card_info_alloca(&info);
1010
1011 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1012 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1013 return;
1014 }
1015
1016 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1017 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1018 snd_ctl_close(ctl);
1019 return;
1020 }
1021
1022 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1023 pa_proplist_sets(p, "alsa.mixer_name", t);
1024
1025 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1026 pa_proplist_sets(p, "alsa.components", t);
1027
1028 snd_ctl_close(ctl);
1029 }
1030
1031 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1032 snd_pcm_state_t state;
1033 int err;
1034
1035 pa_assert(pcm);
1036
1037 if (revents & POLLERR)
1038 pa_log_debug("Got POLLERR from ALSA");
1039 if (revents & POLLNVAL)
1040 pa_log_warn("Got POLLNVAL from ALSA");
1041 if (revents & POLLHUP)
1042 pa_log_warn("Got POLLHUP from ALSA");
1043 if (revents & POLLPRI)
1044 pa_log_warn("Got POLLPRI from ALSA");
1045 if (revents & POLLIN)
1046 pa_log_debug("Got POLLIN from ALSA");
1047 if (revents & POLLOUT)
1048 pa_log_debug("Got POLLOUT from ALSA");
1049
1050 state = snd_pcm_state(pcm);
1051 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1052
1053 /* Try to recover from this error */
1054
1055 switch (state) {
1056
1057 case SND_PCM_STATE_XRUN:
1058 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1059 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1060 return -1;
1061 }
1062 break;
1063
1064 case SND_PCM_STATE_SUSPENDED:
1065 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1066 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1067 return -1;
1068 }
1069 break;
1070
1071 default:
1072
1073 snd_pcm_drop(pcm);
1074
1075 if ((err = snd_pcm_prepare(pcm)) < 0) {
1076 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1077 return -1;
1078 }
1079 break;
1080 }
1081
1082 return 0;
1083 }
1084
1085 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1086 int n, err;
1087 struct pollfd *pollfd;
1088 pa_rtpoll_item *item;
1089
1090 pa_assert(pcm);
1091
1092 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1093 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1094 return NULL;
1095 }
1096
1097 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1098 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1099
1100 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1101 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1102 pa_rtpoll_item_free(item);
1103 return NULL;
1104 }
1105
1106 return item;
1107 }
1108
1109 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1110 snd_pcm_sframes_t n;
1111 size_t k;
1112
1113 pa_assert(pcm);
1114 pa_assert(hwbuf_size > 0);
1115 pa_assert(ss);
1116
1117 /* Some ALSA driver expose weird bugs, let's inform the user about
1118 * what is going on */
1119
1120 n = snd_pcm_avail(pcm);
1121
1122 if (n <= 0)
1123 return n;
1124
1125 k = (size_t) n * pa_frame_size(ss);
1126
1127 if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1128 k >= pa_bytes_per_second(ss)*10)) {
1129
1130 PA_ONCE_BEGIN {
1131 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1132 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1133 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1134 (unsigned long) k,
1135 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1136 pa_strnull(dn));
1137 pa_xfree(dn);
1138 pa_alsa_dump(PA_LOG_ERROR, pcm);
1139 } PA_ONCE_END;
1140
1141 /* Mhmm, let's try not to fail completely */
1142 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1143 }
1144
1145 return n;
1146 }
1147
1148 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,
1149 bool capture) {
1150 ssize_t k;
1151 size_t abs_k;
1152 int err;
1153 snd_pcm_sframes_t avail = 0;
1154
1155 pa_assert(pcm);
1156 pa_assert(delay);
1157 pa_assert(hwbuf_size > 0);
1158 pa_assert(ss);
1159
1160 /* Some ALSA driver expose weird bugs, let's inform the user about
1161 * what is going on. We're going to get both the avail and delay values so
1162 * that we can compare and check them for capture.
1163 * This is done with snd_pcm_status() which provides
1164 * avail, delay and timestamp values in a single kernel call to improve
1165 * timer-based scheduling */
1166
1167 if ((err = snd_pcm_status(pcm, status)) < 0)
1168 return err;
1169
1170 avail = snd_pcm_status_get_avail(status);
1171 *delay = snd_pcm_status_get_delay(status);
1172
1173 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1174
1175 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1176
1177 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1178 abs_k >= pa_bytes_per_second(ss)*10)) {
1179
1180 PA_ONCE_BEGIN {
1181 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1182 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1183 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1184 (signed long) k,
1185 k < 0 ? "-" : "",
1186 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1187 pa_strnull(dn));
1188 pa_xfree(dn);
1189 pa_alsa_dump(PA_LOG_ERROR, pcm);
1190 } PA_ONCE_END;
1191
1192 /* Mhmm, let's try not to fail completely */
1193 if (k < 0)
1194 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1195 else
1196 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1197 }
1198
1199 if (capture) {
1200 abs_k = (size_t) avail * pa_frame_size(ss);
1201
1202 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1203 abs_k >= pa_bytes_per_second(ss)*10)) {
1204
1205 PA_ONCE_BEGIN {
1206 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1207 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1208 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1209 (unsigned long) k,
1210 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1211 pa_strnull(dn));
1212 pa_xfree(dn);
1213 pa_alsa_dump(PA_LOG_ERROR, pcm);
1214 } PA_ONCE_END;
1215
1216 /* Mhmm, let's try not to fail completely */
1217 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1218 }
1219
1220 if (PA_UNLIKELY(*delay < avail)) {
1221 PA_ONCE_BEGIN {
1222 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1223 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1224 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1225 (unsigned long) *delay,
1226 (unsigned long) avail,
1227 pa_strnull(dn));
1228 pa_xfree(dn);
1229 pa_alsa_dump(PA_LOG_ERROR, pcm);
1230 } PA_ONCE_END;
1231
1232 /* try to fixup */
1233 *delay = avail;
1234 }
1235 }
1236
1237 return 0;
1238 }
1239
1240 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) {
1241 int r;
1242 snd_pcm_uframes_t before;
1243 size_t k;
1244
1245 pa_assert(pcm);
1246 pa_assert(areas);
1247 pa_assert(offset);
1248 pa_assert(frames);
1249 pa_assert(hwbuf_size > 0);
1250 pa_assert(ss);
1251
1252 before = *frames;
1253
1254 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1255
1256 if (r < 0)
1257 return r;
1258
1259 k = (size_t) *frames * pa_frame_size(ss);
1260
1261 if (PA_UNLIKELY(*frames > before ||
1262 k >= hwbuf_size * 3 ||
1263 k >= pa_bytes_per_second(ss)*10))
1264 PA_ONCE_BEGIN {
1265 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1266 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1267 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1268 (unsigned long) k,
1269 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1270 pa_strnull(dn));
1271 pa_xfree(dn);
1272 pa_alsa_dump(PA_LOG_ERROR, pcm);
1273 } PA_ONCE_END;
1274
1275 return r;
1276 }
1277
1278 char *pa_alsa_get_driver_name(int card) {
1279 char *t, *m, *n;
1280
1281 pa_assert(card >= 0);
1282
1283 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1284 m = pa_readlink(t);
1285 pa_xfree(t);
1286
1287 if (!m)
1288 return NULL;
1289
1290 n = pa_xstrdup(pa_path_get_filename(m));
1291 pa_xfree(m);
1292
1293 return n;
1294 }
1295
1296 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1297 int card;
1298 snd_pcm_info_t* info;
1299 snd_pcm_info_alloca(&info);
1300
1301 pa_assert(pcm);
1302
1303 if (snd_pcm_info(pcm, info) < 0)
1304 return NULL;
1305
1306 if ((card = snd_pcm_info_get_card(info)) < 0)
1307 return NULL;
1308
1309 return pa_alsa_get_driver_name(card);
1310 }
1311
1312 char *pa_alsa_get_reserve_name(const char *device) {
1313 const char *t;
1314 int i;
1315
1316 pa_assert(device);
1317
1318 if ((t = strchr(device, ':')))
1319 device = t+1;
1320
1321 if ((i = snd_card_get_index(device)) < 0) {
1322 int32_t k;
1323
1324 if (pa_atoi(device, &k) < 0)
1325 return NULL;
1326
1327 i = (int) k;
1328 }
1329
1330 return pa_sprintf_malloc("Audio%i", i);
1331 }
1332
1333 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1334 static unsigned int all_rates[] = { 8000, 11025, 12000,
1335 16000, 22050, 24000,
1336 32000, 44100, 48000,
1337 64000, 88200, 96000,
1338 128000, 176400, 192000,
1339 384000 };
1340 bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
1341 snd_pcm_hw_params_t *hwparams;
1342 unsigned int i, j, n, *rates = NULL;
1343 int ret;
1344
1345 snd_pcm_hw_params_alloca(&hwparams);
1346
1347 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1348 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1349 return NULL;
1350 }
1351
1352 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1353 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1354 supported[i] = true;
1355 n++;
1356 }
1357 }
1358
1359 if (n > 0) {
1360 rates = pa_xnew(unsigned int, n + 1);
1361
1362 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1363 if (supported[i])
1364 rates[j++] = all_rates[i];
1365 }
1366
1367 rates[j] = 0;
1368 } else {
1369 rates = pa_xnew(unsigned int, 2);
1370
1371 rates[0] = fallback_rate;
1372 if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1373 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1374 pa_xfree(rates);
1375 return NULL;
1376 }
1377
1378 rates[1] = 0;
1379 }
1380
1381 return rates;
1382 }
1383
1384 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1385 snd_pcm_info_t* info;
1386 snd_pcm_info_alloca(&info);
1387
1388 pa_assert(pcm);
1389
1390 if (snd_pcm_info(pcm, info) < 0)
1391 return false;
1392
1393 return snd_pcm_info_get_card(info) >= 0;
1394 }
1395
1396 bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1397 snd_pcm_info_t* info;
1398 snd_pcm_info_alloca(&info);
1399
1400 pa_assert(pcm);
1401
1402 if (snd_pcm_info(pcm, info) < 0)
1403 return false;
1404
1405 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1406 }
1407
1408 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1409
1410 const char* pa_alsa_strerror(int errnum) {
1411 const char *original = NULL;
1412 char *translated, *t;
1413 char errbuf[128];
1414
1415 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1416 pa_xfree(t);
1417
1418 original = snd_strerror(errnum);
1419
1420 if (!original) {
1421 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1422 original = errbuf;
1423 }
1424
1425 if (!(translated = pa_locale_to_utf8(original))) {
1426 pa_log_warn("Unable to convert error string to locale, filtering.");
1427 translated = pa_utf8_filter(original);
1428 }
1429
1430 PA_STATIC_TLS_SET(cstrerror, translated);
1431
1432 return translated;
1433 }
1434
1435 bool pa_alsa_may_tsched(bool want) {
1436
1437 if (!want)
1438 return false;
1439
1440 if (!pa_rtclock_hrtimer()) {
1441 /* We cannot depend on being woken up in time when the timers
1442 are inaccurate, so let's fallback to classic IO based playback
1443 then. */
1444 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1445 return false; }
1446
1447 if (pa_running_in_vm()) {
1448 /* We cannot depend on being woken up when we ask for in a VM,
1449 * so let's fallback to classic IO based playback then. */
1450 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1451 return false;
1452 }
1453
1454 return true;
1455 }
1456
1457 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
1458 snd_ctl_elem_id_t *id;
1459
1460 snd_ctl_elem_id_alloca(&id);
1461 snd_ctl_elem_id_clear(id);
1462 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
1463 snd_ctl_elem_id_set_name(id, jack_name);
1464
1465 return snd_hctl_find_elem(hctl, id);
1466 }
1467
1468 snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
1469 snd_ctl_elem_id_t *id;
1470
1471 /* See if we can find the ELD control */
1472 snd_ctl_elem_id_alloca(&id);
1473 snd_ctl_elem_id_clear(id);
1474 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1475 snd_ctl_elem_id_set_name(id, "ELD");
1476 snd_ctl_elem_id_set_device(id, device);
1477
1478 return snd_hctl_find_elem(hctl, id);
1479 }
1480
1481 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
1482 int err;
1483
1484 pa_assert(mixer);
1485 pa_assert(dev);
1486
1487 if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1488 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1489 return -1;
1490 }
1491
1492 /* Note: The hctl handle returned should not be freed.
1493 It is closed/freed by alsa-lib on snd_mixer_close/free */
1494 if (hctl && (err = snd_mixer_get_hctl(mixer, dev, hctl)) < 0) {
1495 pa_log_info("Unable to get hctl of mixer %s: %s", dev, pa_alsa_strerror(err));
1496 return -1;
1497 }
1498
1499 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1500 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1501 return -1;
1502 }
1503
1504 if ((err = snd_mixer_load(mixer)) < 0) {
1505 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1506 return -1;
1507 }
1508
1509 pa_log_info("Successfully attached to mixer '%s'", dev);
1510 return 0;
1511 }
1512
1513 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl) {
1514 int err;
1515 snd_mixer_t *m;
1516 char *md;
1517 snd_pcm_info_t* info;
1518 snd_pcm_info_alloca(&info);
1519
1520 if ((err = snd_mixer_open(&m, 0)) < 0) {
1521 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1522 return NULL;
1523 }
1524
1525 /* Then, try by card index */
1526 md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1527 if (prepare_mixer(m, md, hctl) >= 0) {
1528
1529 if (ctl_device)
1530 *ctl_device = md;
1531 else
1532 pa_xfree(md);
1533
1534 return m;
1535 }
1536
1537 pa_xfree(md);
1538
1539 snd_mixer_close(m);
1540 return NULL;
1541 }
1542
1543 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl) {
1544 int err;
1545 snd_mixer_t *m;
1546 const char *dev;
1547 snd_pcm_info_t* info;
1548 snd_pcm_info_alloca(&info);
1549
1550 pa_assert(pcm);
1551
1552 if ((err = snd_mixer_open(&m, 0)) < 0) {
1553 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1554 return NULL;
1555 }
1556
1557 /* First, try by name */
1558 if ((dev = snd_pcm_name(pcm)))
1559 if (prepare_mixer(m, dev, hctl) >= 0) {
1560 if (ctl_device)
1561 *ctl_device = pa_xstrdup(dev);
1562
1563 return m;
1564 }
1565
1566 /* Then, try by card index */
1567 if (snd_pcm_info(pcm, info) >= 0) {
1568 char *md;
1569 int card_idx;
1570
1571 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1572
1573 md = pa_sprintf_malloc("hw:%i", card_idx);
1574
1575 if (!dev || !pa_streq(dev, md))
1576 if (prepare_mixer(m, md, hctl) >= 0) {
1577
1578 if (ctl_device)
1579 *ctl_device = md;
1580 else
1581 pa_xfree(md);
1582
1583 return m;
1584 }
1585
1586 pa_xfree(md);
1587 }
1588 }
1589
1590 snd_mixer_close(m);
1591 return NULL;
1592 }
1593
1594 int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
1595
1596 /* The ELD format is specific to HDA Intel sound cards and defined in the
1597 HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1598 int err;
1599 snd_hctl_elem_t *elem;
1600 snd_ctl_elem_info_t *info;
1601 snd_ctl_elem_value_t *value;
1602 uint8_t *elddata;
1603 unsigned int eldsize, mnl;
1604
1605 pa_assert(eld != NULL);
1606
1607 /* See if we can find the ELD control */
1608 elem = pa_alsa_find_eld_ctl(hctl, device);
1609 if (elem == NULL) {
1610 pa_log_debug("No ELD info control found (for device=%d)", device);
1611 return -1;
1612 }
1613
1614 /* Does it have any contents? */
1615 snd_ctl_elem_info_alloca(&info);
1616 snd_ctl_elem_value_alloca(&value);
1617 if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1618 (err = snd_hctl_elem_read(elem, value)) < 0) {
1619 pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1620 return -1;
1621 }
1622
1623 eldsize = snd_ctl_elem_info_get_count(info);
1624 elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1625 if (elddata == NULL || eldsize == 0) {
1626 pa_log_debug("ELD info empty (for device=%d)", device);
1627 return -1;
1628 }
1629 if (eldsize < 20 || eldsize > 256) {
1630 pa_log_debug("ELD info has wrong size (for device=%d)", device);
1631 return -1;
1632 }
1633
1634 /* Try to fetch monitor name */
1635 mnl = elddata[4] & 0x1f;
1636 if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
1637 pa_log_debug("No monitor name in ELD info (for device=%d)", device);
1638 mnl = 0;
1639 }
1640 memcpy(eld->monitor_name, &elddata[20], mnl);
1641 eld->monitor_name[mnl] = '\0';
1642 if (mnl)
1643 pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
1644
1645 return 0;
1646 }