]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
Merge remote branch 'origin/merge-queue'
[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 <limits.h>
29 #include <asoundlib.h>
30
31 #include <pulse/sample.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/i18n.h>
36 #include <pulse/utf8.h>
37
38 #include <pulsecore/log.h>
39 #include <pulsecore/macro.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/atomic.h>
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/once.h>
44 #include <pulsecore/thread.h>
45 #include <pulsecore/conf-parser.h>
46 #include <pulsecore/core-rtclock.h>
47
48 #include "alsa-util.h"
49 #include "alsa-mixer.h"
50
51 #ifdef HAVE_HAL
52 #include "hal-util.h"
53 #endif
54
55 #ifdef HAVE_UDEV
56 #include "udev-util.h"
57 #endif
58
59 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
60
61 static const snd_pcm_format_t format_trans[] = {
62 [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
63 [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
64 [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
65 [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
66 [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
67 [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
68 [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
69 [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
70 [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
71 [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
72 [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
73 [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
74 [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
75 };
76
77 static const pa_sample_format_t try_order[] = {
78 PA_SAMPLE_FLOAT32NE,
79 PA_SAMPLE_FLOAT32RE,
80 PA_SAMPLE_S32NE,
81 PA_SAMPLE_S32RE,
82 PA_SAMPLE_S24_32NE,
83 PA_SAMPLE_S24_32RE,
84 PA_SAMPLE_S24NE,
85 PA_SAMPLE_S24RE,
86 PA_SAMPLE_S16NE,
87 PA_SAMPLE_S16RE,
88 PA_SAMPLE_ALAW,
89 PA_SAMPLE_ULAW,
90 PA_SAMPLE_U8
91 };
92
93 unsigned i;
94 int ret;
95
96 pa_assert(pcm_handle);
97 pa_assert(hwparams);
98 pa_assert(f);
99
100 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
101 return ret;
102
103 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
104 snd_pcm_format_description(format_trans[*f]),
105 pa_alsa_strerror(ret));
106
107 if (*f == PA_SAMPLE_FLOAT32BE)
108 *f = PA_SAMPLE_FLOAT32LE;
109 else if (*f == PA_SAMPLE_FLOAT32LE)
110 *f = PA_SAMPLE_FLOAT32BE;
111 else if (*f == PA_SAMPLE_S24BE)
112 *f = PA_SAMPLE_S24LE;
113 else if (*f == PA_SAMPLE_S24LE)
114 *f = PA_SAMPLE_S24BE;
115 else if (*f == PA_SAMPLE_S24_32BE)
116 *f = PA_SAMPLE_S24_32LE;
117 else if (*f == PA_SAMPLE_S24_32LE)
118 *f = PA_SAMPLE_S24_32BE;
119 else if (*f == PA_SAMPLE_S16BE)
120 *f = PA_SAMPLE_S16LE;
121 else if (*f == PA_SAMPLE_S16LE)
122 *f = PA_SAMPLE_S16BE;
123 else if (*f == PA_SAMPLE_S32BE)
124 *f = PA_SAMPLE_S32LE;
125 else if (*f == PA_SAMPLE_S32LE)
126 *f = PA_SAMPLE_S32BE;
127 else
128 goto try_auto;
129
130 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
131 return ret;
132
133 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
134 snd_pcm_format_description(format_trans[*f]),
135 pa_alsa_strerror(ret));
136
137 try_auto:
138
139 for (i = 0; i < PA_ELEMENTSOF(try_order); i++) {
140 *f = try_order[i];
141
142 if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
143 return ret;
144
145 pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
146 snd_pcm_format_description(format_trans[*f]),
147 pa_alsa_strerror(ret));
148 }
149
150 return -1;
151 }
152
153 static int set_period_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
154 snd_pcm_uframes_t s;
155 int d, ret;
156
157 pa_assert(pcm_handle);
158 pa_assert(hwparams);
159
160 s = size;
161 d = 0;
162 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
163 s = size;
164 d = -1;
165 if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d) < 0) {
166 s = size;
167 d = 1;
168 if ((ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &s, &d)) < 0) {
169 pa_log_info("snd_pcm_hw_params_set_period_size_near() failed: %s", pa_alsa_strerror(ret));
170 return ret;
171 }
172 }
173 }
174
175 return 0;
176 }
177
178 static int set_buffer_size(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, snd_pcm_uframes_t size) {
179 int ret;
180
181 pa_assert(pcm_handle);
182 pa_assert(hwparams);
183
184 if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &size)) < 0) {
185 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
186 return ret;
187 }
188
189 return 0;
190 }
191
192 /* Set the hardware parameters of the given ALSA device. Returns the
193 * selected fragment settings in *buffer_size and *period_size. If tsched mode can be enabled */
194 int pa_alsa_set_hw_params(
195 snd_pcm_t *pcm_handle,
196 pa_sample_spec *ss,
197 snd_pcm_uframes_t *period_size,
198 snd_pcm_uframes_t *buffer_size,
199 snd_pcm_uframes_t tsched_size,
200 pa_bool_t *use_mmap,
201 pa_bool_t *use_tsched,
202 pa_bool_t require_exact_channel_number) {
203
204 int ret = -1;
205 snd_pcm_hw_params_t *hwparams, *hwparams_copy;
206 int dir;
207 snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
208 snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
209 pa_bool_t _use_mmap = use_mmap && *use_mmap;
210 pa_bool_t _use_tsched = use_tsched && *use_tsched;
211 pa_sample_spec _ss = *ss;
212
213 pa_assert(pcm_handle);
214 pa_assert(ss);
215
216 snd_pcm_hw_params_alloca(&hwparams);
217 snd_pcm_hw_params_alloca(&hwparams_copy);
218
219 if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
220 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
221 goto finish;
222 }
223
224 if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
225 pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
226 goto finish;
227 }
228
229 if (_use_mmap) {
230
231 if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
232
233 /* mmap() didn't work, fall back to interleaved */
234
235 if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
236 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
237 goto finish;
238 }
239
240 _use_mmap = FALSE;
241 }
242
243 } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
244 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
245 goto finish;
246 }
247
248 if (!_use_mmap)
249 _use_tsched = FALSE;
250
251 if (!pa_alsa_pcm_is_hw(pcm_handle))
252 _use_tsched = FALSE;
253
254 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
255 goto finish;
256
257 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
258 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
259 goto finish;
260 }
261
262 if (require_exact_channel_number) {
263 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
264 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
265 goto finish;
266 }
267 } else {
268 unsigned int c = _ss.channels;
269
270 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
271 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
272 goto finish;
273 }
274
275 _ss.channels = c;
276 }
277
278 if (_use_tsched && tsched_size > 0) {
279 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
280 _period_size = _buffer_size;
281 } else {
282 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
283 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
284 }
285
286 if (_buffer_size > 0 || _period_size > 0) {
287 snd_pcm_uframes_t max_frames = 0;
288
289 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
290 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
291 else
292 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
293
294 /* Some ALSA drivers really don't like if we set the buffer
295 * size first and the number of periods second. (which would
296 * make a lot more sense to me) So, try a few combinations
297 * before we give up. */
298
299 if (_buffer_size > 0 && _period_size > 0) {
300 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
301
302 /* First try: set buffer size first, followed by period size */
303 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
304 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
305 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
306 pa_log_debug("Set buffer size first, period size second.");
307 goto success;
308 }
309
310 /* Second try: set period size first, followed by buffer size */
311 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
312 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
313 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
314 pa_log_debug("Set period size first, buffer size second.");
315 goto success;
316 }
317 }
318
319 if (_buffer_size > 0) {
320 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
321
322 /* Third try: set only buffer size */
323 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
324 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
325 pa_log_debug("Set only buffer size second.");
326 goto success;
327 }
328 }
329
330 if (_period_size > 0) {
331 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
332
333 /* Fourth try: set only period size */
334 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
335 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
336 pa_log_debug("Set only period size second.");
337 goto success;
338 }
339 }
340 }
341
342 pa_log_debug("Set neither period nor buffer size.");
343
344 /* Last chance, set nothing */
345 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
346 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
347 goto finish;
348 }
349
350 success:
351
352 if (ss->rate != _ss.rate)
353 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
354
355 if (ss->channels != _ss.channels)
356 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
357
358 if (ss->format != _ss.format)
359 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));
360
361 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
362 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
363 goto finish;
364 }
365
366 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
367 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
368 goto finish;
369 }
370
371 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
372 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
373 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
374 goto finish;
375 }
376
377 /* If the sample rate deviates too much, we need to resample */
378 if (_ss.rate < ss->rate*.95 || _ss.rate > ss->rate*1.05)
379 ss->rate = _ss.rate;
380 ss->channels = _ss.channels;
381 ss->format = _ss.format;
382
383 pa_assert(_period_size > 0);
384 pa_assert(_buffer_size > 0);
385
386 if (buffer_size)
387 *buffer_size = _buffer_size;
388
389 if (period_size)
390 *period_size = _period_size;
391
392 if (use_mmap)
393 *use_mmap = _use_mmap;
394
395 if (use_tsched)
396 *use_tsched = _use_tsched;
397
398 ret = 0;
399
400 snd_pcm_nonblock(pcm_handle, 1);
401
402 finish:
403
404 return ret;
405 }
406
407 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, pa_bool_t period_event) {
408 snd_pcm_sw_params_t *swparams;
409 snd_pcm_uframes_t boundary;
410 int err;
411
412 pa_assert(pcm);
413
414 snd_pcm_sw_params_alloca(&swparams);
415
416 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
417 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
418 return err;
419 }
420
421 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
422 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
423 return err;
424 }
425
426 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
427 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
428 return err;
429 }
430
431 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
432 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
433 return err;
434 }
435
436 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
437 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
438 return err;
439 }
440
441 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
442 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
443 return err;
444 }
445
446 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
447 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
448 return err;
449 }
450
451 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
452 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
453 return err;
454 }
455
456 return 0;
457 }
458
459 snd_pcm_t *pa_alsa_open_by_device_id_auto(
460 const char *dev_id,
461 char **dev,
462 pa_sample_spec *ss,
463 pa_channel_map* map,
464 int mode,
465 snd_pcm_uframes_t *period_size,
466 snd_pcm_uframes_t *buffer_size,
467 snd_pcm_uframes_t tsched_size,
468 pa_bool_t *use_mmap,
469 pa_bool_t *use_tsched,
470 pa_alsa_profile_set *ps,
471 pa_alsa_mapping **mapping) {
472
473 char *d;
474 snd_pcm_t *pcm_handle;
475 void *state;
476 pa_alsa_mapping *m;
477
478 pa_assert(dev_id);
479 pa_assert(dev);
480 pa_assert(ss);
481 pa_assert(map);
482 pa_assert(ps);
483
484 /* First we try to find a device string with a superset of the
485 * requested channel map. We iterate through our device table from
486 * top to bottom and take the first that matches. If we didn't
487 * find a working device that way, we iterate backwards, and check
488 * all devices that do not provide a superset of the requested
489 * channel map.*/
490
491 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
492 if (!pa_channel_map_superset(&m->channel_map, map))
493 continue;
494
495 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
496
497 pcm_handle = pa_alsa_open_by_device_id_mapping(
498 dev_id,
499 dev,
500 ss,
501 map,
502 mode,
503 period_size,
504 buffer_size,
505 tsched_size,
506 use_mmap,
507 use_tsched,
508 m);
509
510 if (pcm_handle) {
511 if (mapping)
512 *mapping = m;
513
514 return pcm_handle;
515 }
516 }
517
518 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
519 if (pa_channel_map_superset(&m->channel_map, map))
520 continue;
521
522 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
523
524 pcm_handle = pa_alsa_open_by_device_id_mapping(
525 dev_id,
526 dev,
527 ss,
528 map,
529 mode,
530 period_size,
531 buffer_size,
532 tsched_size,
533 use_mmap,
534 use_tsched,
535 m);
536
537 if (pcm_handle) {
538 if (mapping)
539 *mapping = m;
540
541 return pcm_handle;
542 }
543 }
544
545 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
546 d = pa_sprintf_malloc("hw:%s", dev_id);
547 pa_log_debug("Trying %s as last resort...", d);
548 pcm_handle = pa_alsa_open_by_device_string(
549 d,
550 dev,
551 ss,
552 map,
553 mode,
554 period_size,
555 buffer_size,
556 tsched_size,
557 use_mmap,
558 use_tsched,
559 FALSE);
560 pa_xfree(d);
561
562 if (pcm_handle && mapping)
563 *mapping = NULL;
564
565 return pcm_handle;
566 }
567
568 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
569 const char *dev_id,
570 char **dev,
571 pa_sample_spec *ss,
572 pa_channel_map* map,
573 int mode,
574 snd_pcm_uframes_t *period_size,
575 snd_pcm_uframes_t *buffer_size,
576 snd_pcm_uframes_t tsched_size,
577 pa_bool_t *use_mmap,
578 pa_bool_t *use_tsched,
579 pa_alsa_mapping *m) {
580
581 snd_pcm_t *pcm_handle;
582 pa_sample_spec try_ss;
583 pa_channel_map try_map;
584
585 pa_assert(dev_id);
586 pa_assert(dev);
587 pa_assert(ss);
588 pa_assert(map);
589 pa_assert(m);
590
591 try_ss.channels = m->channel_map.channels;
592 try_ss.rate = ss->rate;
593 try_ss.format = ss->format;
594 try_map = m->channel_map;
595
596 pcm_handle = pa_alsa_open_by_template(
597 m->device_strings,
598 dev_id,
599 dev,
600 &try_ss,
601 &try_map,
602 mode,
603 period_size,
604 buffer_size,
605 tsched_size,
606 use_mmap,
607 use_tsched,
608 TRUE);
609
610 if (!pcm_handle)
611 return NULL;
612
613 *ss = try_ss;
614 *map = try_map;
615 pa_assert(map->channels == ss->channels);
616
617 return pcm_handle;
618 }
619
620 snd_pcm_t *pa_alsa_open_by_device_string(
621 const char *device,
622 char **dev,
623 pa_sample_spec *ss,
624 pa_channel_map* map,
625 int mode,
626 snd_pcm_uframes_t *period_size,
627 snd_pcm_uframes_t *buffer_size,
628 snd_pcm_uframes_t tsched_size,
629 pa_bool_t *use_mmap,
630 pa_bool_t *use_tsched,
631 pa_bool_t require_exact_channel_number) {
632
633 int err;
634 char *d;
635 snd_pcm_t *pcm_handle;
636 pa_bool_t reformat = FALSE;
637
638 pa_assert(device);
639 pa_assert(ss);
640 pa_assert(map);
641
642 d = pa_xstrdup(device);
643
644 for (;;) {
645 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
646
647 if ((err = snd_pcm_open(&pcm_handle, d, mode,
648 SND_PCM_NONBLOCK|
649 SND_PCM_NO_AUTO_RESAMPLE|
650 SND_PCM_NO_AUTO_CHANNELS|
651 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
652 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
653 goto fail;
654 }
655
656 pa_log_debug("Managed to open %s", d);
657
658 if ((err = pa_alsa_set_hw_params(
659 pcm_handle,
660 ss,
661 period_size,
662 buffer_size,
663 tsched_size,
664 use_mmap,
665 use_tsched,
666 require_exact_channel_number)) < 0) {
667
668 if (!reformat) {
669 reformat = TRUE;
670
671 snd_pcm_close(pcm_handle);
672 continue;
673 }
674
675 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
676 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
677 char *t;
678
679 t = pa_sprintf_malloc("plug:%s", d);
680 pa_xfree(d);
681 d = t;
682
683 reformat = FALSE;
684
685 snd_pcm_close(pcm_handle);
686 continue;
687 }
688
689 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
690 snd_pcm_close(pcm_handle);
691
692 goto fail;
693 }
694
695 if (dev)
696 *dev = d;
697 else
698 pa_xfree(d);
699
700 if (ss->channels != map->channels)
701 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
702
703 return pcm_handle;
704 }
705
706 fail:
707 pa_xfree(d);
708
709 return NULL;
710 }
711
712 snd_pcm_t *pa_alsa_open_by_template(
713 char **template,
714 const char *dev_id,
715 char **dev,
716 pa_sample_spec *ss,
717 pa_channel_map* map,
718 int mode,
719 snd_pcm_uframes_t *period_size,
720 snd_pcm_uframes_t *buffer_size,
721 snd_pcm_uframes_t tsched_size,
722 pa_bool_t *use_mmap,
723 pa_bool_t *use_tsched,
724 pa_bool_t require_exact_channel_number) {
725
726 snd_pcm_t *pcm_handle;
727 char **i;
728
729 for (i = template; *i; i++) {
730 char *d;
731
732 d = pa_replace(*i, "%f", dev_id);
733
734 pcm_handle = pa_alsa_open_by_device_string(
735 d,
736 dev,
737 ss,
738 map,
739 mode,
740 period_size,
741 buffer_size,
742 tsched_size,
743 use_mmap,
744 use_tsched,
745 require_exact_channel_number);
746
747 pa_xfree(d);
748
749 if (pcm_handle)
750 return pcm_handle;
751 }
752
753 return NULL;
754 }
755
756 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
757 int err;
758 snd_output_t *out;
759
760 pa_assert(pcm);
761
762 pa_assert_se(snd_output_buffer_open(&out) == 0);
763
764 if ((err = snd_pcm_dump(pcm, out)) < 0)
765 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
766 else {
767 char *s = NULL;
768 snd_output_buffer_string(out, &s);
769 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
770 }
771
772 pa_assert_se(snd_output_close(out) == 0);
773 }
774
775 void pa_alsa_dump_status(snd_pcm_t *pcm) {
776 int err;
777 snd_output_t *out;
778 snd_pcm_status_t *status;
779 char *s = NULL;
780
781 pa_assert(pcm);
782
783 snd_pcm_status_alloca(&status);
784
785 if ((err = snd_output_buffer_open(&out)) < 0) {
786 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
787 return;
788 }
789
790 if ((err = snd_pcm_status(pcm, status)) < 0) {
791 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
792 goto finish;
793 }
794
795 if ((err = snd_pcm_status_dump(status, out)) < 0) {
796 pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
797 goto finish;
798 }
799
800 snd_output_buffer_string(out, &s);
801 pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
802
803 finish:
804
805 snd_output_close(out);
806 }
807
808 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
809 va_list ap;
810 char *alsa_file;
811
812 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
813
814 va_start(ap, fmt);
815
816 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
817
818 va_end(ap);
819
820 pa_xfree(alsa_file);
821 }
822
823 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
824
825 void pa_alsa_refcnt_inc(void) {
826 /* This is not really thread safe, but we do our best */
827
828 if (pa_atomic_inc(&n_error_handler_installed) == 0)
829 snd_lib_error_set_handler(alsa_error_handler);
830 }
831
832 void pa_alsa_refcnt_dec(void) {
833 int r;
834
835 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
836
837 if (r == 1) {
838 snd_lib_error_set_handler(NULL);
839 snd_config_update_free_global();
840 }
841 }
842
843 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
844 const char *d, *k;
845 pa_assert(p);
846
847 if (pa_device_init_description(p))
848 return TRUE;
849
850 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
851 d = pa_proplist_gets(p, "alsa.name");
852
853 if (!d)
854 return FALSE;
855
856 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
857
858 if (d && k)
859 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, _("%s %s"), d, k);
860 else if (d)
861 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
862
863 return FALSE;
864 }
865
866 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
867 char *cn, *lcn, *dn;
868
869 pa_assert(p);
870 pa_assert(card >= 0);
871
872 pa_proplist_setf(p, "alsa.card", "%i", card);
873
874 if (snd_card_get_name(card, &cn) >= 0) {
875 pa_proplist_sets(p, "alsa.card_name", cn);
876 free(cn);
877 }
878
879 if (snd_card_get_longname(card, &lcn) >= 0) {
880 pa_proplist_sets(p, "alsa.long_card_name", lcn);
881 free(lcn);
882 }
883
884 if ((dn = pa_alsa_get_driver_name(card))) {
885 pa_proplist_sets(p, "alsa.driver_name", dn);
886 pa_xfree(dn);
887 }
888
889 #ifdef HAVE_UDEV
890 pa_udev_get_info(card, p);
891 #endif
892
893 #ifdef HAVE_HAL
894 pa_hal_get_info(c, p, card);
895 #endif
896 }
897
898 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
899
900 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
901 [SND_PCM_CLASS_GENERIC] = "generic",
902 [SND_PCM_CLASS_MULTI] = "multi",
903 [SND_PCM_CLASS_MODEM] = "modem",
904 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
905 };
906 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
907 [SND_PCM_CLASS_GENERIC] = "sound",
908 [SND_PCM_CLASS_MULTI] = NULL,
909 [SND_PCM_CLASS_MODEM] = "modem",
910 [SND_PCM_CLASS_DIGITIZER] = NULL
911 };
912 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
913 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
914 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
915 };
916
917 snd_pcm_class_t class;
918 snd_pcm_subclass_t subclass;
919 const char *n, *id, *sdn;
920 int card;
921
922 pa_assert(p);
923 pa_assert(pcm_info);
924
925 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
926
927 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
928 if (class_table[class])
929 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
930 if (alsa_class_table[class])
931 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
932 }
933
934 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
935 if (alsa_subclass_table[subclass])
936 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
937
938 if ((n = snd_pcm_info_get_name(pcm_info)))
939 pa_proplist_sets(p, "alsa.name", n);
940
941 if ((id = snd_pcm_info_get_id(pcm_info)))
942 pa_proplist_sets(p, "alsa.id", id);
943
944 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
945 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
946 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
947
948 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
949
950 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
951 pa_alsa_init_proplist_card(c, p, card);
952 }
953
954 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
955 snd_pcm_hw_params_t *hwparams;
956 snd_pcm_info_t *info;
957 int bits, err;
958
959 snd_pcm_hw_params_alloca(&hwparams);
960 snd_pcm_info_alloca(&info);
961
962 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
963 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
964 else {
965
966 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
967 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
968 }
969
970 if ((err = snd_pcm_info(pcm, info)) < 0)
971 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
972 else
973 pa_alsa_init_proplist_pcm_info(c, p, info);
974 }
975
976 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
977 int err;
978 snd_ctl_t *ctl;
979 snd_ctl_card_info_t *info;
980 const char *t;
981
982 pa_assert(p);
983
984 snd_ctl_card_info_alloca(&info);
985
986 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
987 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
988 return;
989 }
990
991 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
992 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
993 snd_ctl_close(ctl);
994 return;
995 }
996
997 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
998 pa_proplist_sets(p, "alsa.mixer_name", t);
999
1000 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1001 pa_proplist_sets(p, "alsa.components", t);
1002
1003 snd_ctl_close(ctl);
1004 }
1005
1006 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1007 snd_pcm_state_t state;
1008 int err;
1009
1010 pa_assert(pcm);
1011
1012 if (revents & POLLERR)
1013 pa_log_debug("Got POLLERR from ALSA");
1014 if (revents & POLLNVAL)
1015 pa_log_warn("Got POLLNVAL from ALSA");
1016 if (revents & POLLHUP)
1017 pa_log_warn("Got POLLHUP from ALSA");
1018 if (revents & POLLPRI)
1019 pa_log_warn("Got POLLPRI from ALSA");
1020 if (revents & POLLIN)
1021 pa_log_debug("Got POLLIN from ALSA");
1022 if (revents & POLLOUT)
1023 pa_log_debug("Got POLLOUT from ALSA");
1024
1025 state = snd_pcm_state(pcm);
1026 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1027
1028 /* Try to recover from this error */
1029
1030 switch (state) {
1031
1032 case SND_PCM_STATE_XRUN:
1033 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1034 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1035 return -1;
1036 }
1037 break;
1038
1039 case SND_PCM_STATE_SUSPENDED:
1040 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1041 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1042 return -1;
1043 }
1044 break;
1045
1046 default:
1047
1048 snd_pcm_drop(pcm);
1049
1050 if ((err = snd_pcm_prepare(pcm)) < 0) {
1051 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1052 return -1;
1053 }
1054 break;
1055 }
1056
1057 return 0;
1058 }
1059
1060 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1061 int n, err;
1062 struct pollfd *pollfd;
1063 pa_rtpoll_item *item;
1064
1065 pa_assert(pcm);
1066
1067 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1068 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1069 return NULL;
1070 }
1071
1072 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1073 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1074
1075 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1076 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1077 pa_rtpoll_item_free(item);
1078 return NULL;
1079 }
1080
1081 return item;
1082 }
1083
1084 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1085 snd_pcm_sframes_t n;
1086 size_t k;
1087
1088 pa_assert(pcm);
1089 pa_assert(hwbuf_size > 0);
1090 pa_assert(ss);
1091
1092 /* Some ALSA driver expose weird bugs, let's inform the user about
1093 * what is going on */
1094
1095 n = snd_pcm_avail(pcm);
1096
1097 if (n <= 0)
1098 return n;
1099
1100 k = (size_t) n * pa_frame_size(ss);
1101
1102 if (k >= hwbuf_size * 5 ||
1103 k >= pa_bytes_per_second(ss)*10) {
1104
1105 PA_ONCE_BEGIN {
1106 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1107 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1108 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1109 (unsigned long) k,
1110 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1111 pa_strnull(dn));
1112 pa_xfree(dn);
1113 pa_alsa_dump(PA_LOG_ERROR, pcm);
1114 } PA_ONCE_END;
1115
1116 /* Mhmm, let's try not to fail completely */
1117 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1118 }
1119
1120 return n;
1121 }
1122
1123 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1124 ssize_t k;
1125 size_t abs_k;
1126 int r;
1127
1128 pa_assert(pcm);
1129 pa_assert(delay);
1130 pa_assert(hwbuf_size > 0);
1131 pa_assert(ss);
1132
1133 /* Some ALSA driver expose weird bugs, let's inform the user about
1134 * what is going on */
1135
1136 if ((r = snd_pcm_delay(pcm, delay)) < 0)
1137 return r;
1138
1139 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1140
1141 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1142
1143 if (abs_k >= hwbuf_size * 5 ||
1144 abs_k >= pa_bytes_per_second(ss)*10) {
1145
1146 PA_ONCE_BEGIN {
1147 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1148 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1149 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1150 (signed long) k,
1151 k < 0 ? "-" : "",
1152 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1153 pa_strnull(dn));
1154 pa_xfree(dn);
1155 pa_alsa_dump(PA_LOG_ERROR, pcm);
1156 } PA_ONCE_END;
1157
1158 /* Mhmm, let's try not to fail completely */
1159 if (k < 0)
1160 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1161 else
1162 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1163 }
1164
1165 return 0;
1166 }
1167
1168 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) {
1169 int r;
1170 snd_pcm_uframes_t before;
1171 size_t k;
1172
1173 pa_assert(pcm);
1174 pa_assert(areas);
1175 pa_assert(offset);
1176 pa_assert(frames);
1177 pa_assert(hwbuf_size > 0);
1178 pa_assert(ss);
1179
1180 before = *frames;
1181
1182 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1183
1184 if (r < 0)
1185 return r;
1186
1187 k = (size_t) *frames * pa_frame_size(ss);
1188
1189 if (*frames > before ||
1190 k >= hwbuf_size * 3 ||
1191 k >= pa_bytes_per_second(ss)*10)
1192
1193 PA_ONCE_BEGIN {
1194 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1195 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1196 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1197 (unsigned long) k,
1198 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1199 pa_strnull(dn));
1200 pa_xfree(dn);
1201 pa_alsa_dump(PA_LOG_ERROR, pcm);
1202 } PA_ONCE_END;
1203
1204 return r;
1205 }
1206
1207 char *pa_alsa_get_driver_name(int card) {
1208 char *t, *m, *n;
1209
1210 pa_assert(card >= 0);
1211
1212 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1213 m = pa_readlink(t);
1214 pa_xfree(t);
1215
1216 if (!m)
1217 return NULL;
1218
1219 n = pa_xstrdup(pa_path_get_filename(m));
1220 pa_xfree(m);
1221
1222 return n;
1223 }
1224
1225 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1226 int card;
1227 snd_pcm_info_t* info;
1228 snd_pcm_info_alloca(&info);
1229
1230 pa_assert(pcm);
1231
1232 if (snd_pcm_info(pcm, info) < 0)
1233 return NULL;
1234
1235 if ((card = snd_pcm_info_get_card(info)) < 0)
1236 return NULL;
1237
1238 return pa_alsa_get_driver_name(card);
1239 }
1240
1241 char *pa_alsa_get_reserve_name(const char *device) {
1242 const char *t;
1243 int i;
1244
1245 pa_assert(device);
1246
1247 if ((t = strchr(device, ':')))
1248 device = t+1;
1249
1250 if ((i = snd_card_get_index(device)) < 0) {
1251 int32_t k;
1252
1253 if (pa_atoi(device, &k) < 0)
1254 return NULL;
1255
1256 i = (int) k;
1257 }
1258
1259 return pa_sprintf_malloc("Audio%i", i);
1260 }
1261
1262 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1263 snd_pcm_info_t* info;
1264 snd_pcm_info_alloca(&info);
1265
1266 pa_assert(pcm);
1267
1268 if (snd_pcm_info(pcm, info) < 0)
1269 return FALSE;
1270
1271 return snd_pcm_info_get_card(info) >= 0;
1272 }
1273
1274 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1275 snd_pcm_info_t* info;
1276 snd_pcm_info_alloca(&info);
1277
1278 pa_assert(pcm);
1279
1280 if (snd_pcm_info(pcm, info) < 0)
1281 return FALSE;
1282
1283 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1284 }
1285
1286 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1287
1288 const char* pa_alsa_strerror(int errnum) {
1289 const char *original = NULL;
1290 char *translated, *t;
1291 char errbuf[128];
1292
1293 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1294 pa_xfree(t);
1295
1296 original = snd_strerror(errnum);
1297
1298 if (!original) {
1299 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1300 original = errbuf;
1301 }
1302
1303 if (!(translated = pa_locale_to_utf8(original))) {
1304 pa_log_warn("Unable to convert error string to locale, filtering.");
1305 translated = pa_utf8_filter(original);
1306 }
1307
1308 PA_STATIC_TLS_SET(cstrerror, translated);
1309
1310 return translated;
1311 }
1312
1313 pa_bool_t pa_alsa_may_tsched(pa_bool_t want) {
1314
1315 if (!want)
1316 return FALSE;
1317
1318 if (!pa_rtclock_hrtimer()) {
1319 /* We cannot depend on being woken up in time when the timers
1320 are inaccurate, so let's fallback to classic IO based playback
1321 then. */
1322 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1323 return FALSE; }
1324
1325 if (pa_running_in_vm()) {
1326 /* We cannot depend on being woken up when we ask for in a VM,
1327 * so let's fallback to classic IO based playback then. */
1328 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1329 return FALSE;
1330 }
1331
1332
1333 return TRUE;
1334 }