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