]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
alsa: remove redundant call to snd_pcm_nonblock()
[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 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", pa_strip(cn));
876 free(cn);
877 }
878
879 if (snd_card_get_longname(card, &lcn) >= 0) {
880 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(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 char *t = pa_xstrdup(n);
940 pa_proplist_sets(p, "alsa.name", pa_strip(t));
941 pa_xfree(t);
942 }
943
944 if ((id = snd_pcm_info_get_id(pcm_info)))
945 pa_proplist_sets(p, "alsa.id", id);
946
947 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
948 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
949 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
950
951 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
952
953 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
954 pa_alsa_init_proplist_card(c, p, card);
955 }
956
957 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
958 snd_pcm_hw_params_t *hwparams;
959 snd_pcm_info_t *info;
960 int bits, err;
961
962 snd_pcm_hw_params_alloca(&hwparams);
963 snd_pcm_info_alloca(&info);
964
965 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
966 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
967 else {
968
969 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
970 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
971 }
972
973 if ((err = snd_pcm_info(pcm, info)) < 0)
974 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
975 else
976 pa_alsa_init_proplist_pcm_info(c, p, info);
977 }
978
979 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
980 int err;
981 snd_ctl_t *ctl;
982 snd_ctl_card_info_t *info;
983 const char *t;
984
985 pa_assert(p);
986
987 snd_ctl_card_info_alloca(&info);
988
989 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
990 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
991 return;
992 }
993
994 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
995 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
996 snd_ctl_close(ctl);
997 return;
998 }
999
1000 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1001 pa_proplist_sets(p, "alsa.mixer_name", t);
1002
1003 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1004 pa_proplist_sets(p, "alsa.components", t);
1005
1006 snd_ctl_close(ctl);
1007 }
1008
1009 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1010 snd_pcm_state_t state;
1011 int err;
1012
1013 pa_assert(pcm);
1014
1015 if (revents & POLLERR)
1016 pa_log_debug("Got POLLERR from ALSA");
1017 if (revents & POLLNVAL)
1018 pa_log_warn("Got POLLNVAL from ALSA");
1019 if (revents & POLLHUP)
1020 pa_log_warn("Got POLLHUP from ALSA");
1021 if (revents & POLLPRI)
1022 pa_log_warn("Got POLLPRI from ALSA");
1023 if (revents & POLLIN)
1024 pa_log_debug("Got POLLIN from ALSA");
1025 if (revents & POLLOUT)
1026 pa_log_debug("Got POLLOUT from ALSA");
1027
1028 state = snd_pcm_state(pcm);
1029 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1030
1031 /* Try to recover from this error */
1032
1033 switch (state) {
1034
1035 case SND_PCM_STATE_XRUN:
1036 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1037 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1038 return -1;
1039 }
1040 break;
1041
1042 case SND_PCM_STATE_SUSPENDED:
1043 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1044 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1045 return -1;
1046 }
1047 break;
1048
1049 default:
1050
1051 snd_pcm_drop(pcm);
1052
1053 if ((err = snd_pcm_prepare(pcm)) < 0) {
1054 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1055 return -1;
1056 }
1057 break;
1058 }
1059
1060 return 0;
1061 }
1062
1063 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1064 int n, err;
1065 struct pollfd *pollfd;
1066 pa_rtpoll_item *item;
1067
1068 pa_assert(pcm);
1069
1070 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1071 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1072 return NULL;
1073 }
1074
1075 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1076 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1077
1078 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1079 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1080 pa_rtpoll_item_free(item);
1081 return NULL;
1082 }
1083
1084 return item;
1085 }
1086
1087 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1088 snd_pcm_sframes_t n;
1089 size_t k;
1090
1091 pa_assert(pcm);
1092 pa_assert(hwbuf_size > 0);
1093 pa_assert(ss);
1094
1095 /* Some ALSA driver expose weird bugs, let's inform the user about
1096 * what is going on */
1097
1098 n = snd_pcm_avail(pcm);
1099
1100 if (n <= 0)
1101 return n;
1102
1103 k = (size_t) n * pa_frame_size(ss);
1104
1105 if (k >= hwbuf_size * 5 ||
1106 k >= pa_bytes_per_second(ss)*10) {
1107
1108 PA_ONCE_BEGIN {
1109 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1110 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1111 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1112 (unsigned long) k,
1113 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1114 pa_strnull(dn));
1115 pa_xfree(dn);
1116 pa_alsa_dump(PA_LOG_ERROR, pcm);
1117 } PA_ONCE_END;
1118
1119 /* Mhmm, let's try not to fail completely */
1120 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1121 }
1122
1123 return n;
1124 }
1125
1126 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture) {
1127 ssize_t k;
1128 size_t abs_k;
1129 int r;
1130 snd_pcm_sframes_t avail = 0;
1131
1132 pa_assert(pcm);
1133 pa_assert(delay);
1134 pa_assert(hwbuf_size > 0);
1135 pa_assert(ss);
1136
1137 /* Some ALSA driver expose weird bugs, let's inform the user about
1138 * what is going on. We're going to get both the avail and delay values so
1139 * that we can compare and check them for capture */
1140
1141 if ((r = snd_pcm_avail_delay(pcm, &avail, 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 if (capture) {
1171 abs_k = (size_t) avail * pa_frame_size(ss);
1172
1173 if (abs_k >= hwbuf_size * 5 ||
1174 abs_k >= pa_bytes_per_second(ss)*10) {
1175
1176 PA_ONCE_BEGIN {
1177 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1178 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1179 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1180 (unsigned long) k,
1181 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1182 pa_strnull(dn));
1183 pa_xfree(dn);
1184 pa_alsa_dump(PA_LOG_ERROR, pcm);
1185 } PA_ONCE_END;
1186
1187 /* Mhmm, let's try not to fail completely */
1188 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1189 }
1190
1191 if (*delay < avail) {
1192 PA_ONCE_BEGIN {
1193 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1194 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1195 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1196 (unsigned long) *delay,
1197 (unsigned long) avail,
1198 pa_strnull(dn));
1199 pa_xfree(dn);
1200 pa_alsa_dump(PA_LOG_ERROR, pcm);
1201 } PA_ONCE_END;
1202
1203 /* try to fixup */
1204 *delay = avail;
1205 }
1206 }
1207
1208 return 0;
1209 }
1210
1211 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) {
1212 int r;
1213 snd_pcm_uframes_t before;
1214 size_t k;
1215
1216 pa_assert(pcm);
1217 pa_assert(areas);
1218 pa_assert(offset);
1219 pa_assert(frames);
1220 pa_assert(hwbuf_size > 0);
1221 pa_assert(ss);
1222
1223 before = *frames;
1224
1225 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1226
1227 if (r < 0)
1228 return r;
1229
1230 k = (size_t) *frames * pa_frame_size(ss);
1231
1232 if (*frames > before ||
1233 k >= hwbuf_size * 3 ||
1234 k >= pa_bytes_per_second(ss)*10)
1235
1236 PA_ONCE_BEGIN {
1237 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1238 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1239 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1240 (unsigned long) k,
1241 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1242 pa_strnull(dn));
1243 pa_xfree(dn);
1244 pa_alsa_dump(PA_LOG_ERROR, pcm);
1245 } PA_ONCE_END;
1246
1247 return r;
1248 }
1249
1250 char *pa_alsa_get_driver_name(int card) {
1251 char *t, *m, *n;
1252
1253 pa_assert(card >= 0);
1254
1255 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1256 m = pa_readlink(t);
1257 pa_xfree(t);
1258
1259 if (!m)
1260 return NULL;
1261
1262 n = pa_xstrdup(pa_path_get_filename(m));
1263 pa_xfree(m);
1264
1265 return n;
1266 }
1267
1268 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1269 int card;
1270 snd_pcm_info_t* info;
1271 snd_pcm_info_alloca(&info);
1272
1273 pa_assert(pcm);
1274
1275 if (snd_pcm_info(pcm, info) < 0)
1276 return NULL;
1277
1278 if ((card = snd_pcm_info_get_card(info)) < 0)
1279 return NULL;
1280
1281 return pa_alsa_get_driver_name(card);
1282 }
1283
1284 char *pa_alsa_get_reserve_name(const char *device) {
1285 const char *t;
1286 int i;
1287
1288 pa_assert(device);
1289
1290 if ((t = strchr(device, ':')))
1291 device = t+1;
1292
1293 if ((i = snd_card_get_index(device)) < 0) {
1294 int32_t k;
1295
1296 if (pa_atoi(device, &k) < 0)
1297 return NULL;
1298
1299 i = (int) k;
1300 }
1301
1302 return pa_sprintf_malloc("Audio%i", i);
1303 }
1304
1305 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1306 snd_pcm_info_t* info;
1307 snd_pcm_info_alloca(&info);
1308
1309 pa_assert(pcm);
1310
1311 if (snd_pcm_info(pcm, info) < 0)
1312 return FALSE;
1313
1314 return snd_pcm_info_get_card(info) >= 0;
1315 }
1316
1317 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1318 snd_pcm_info_t* info;
1319 snd_pcm_info_alloca(&info);
1320
1321 pa_assert(pcm);
1322
1323 if (snd_pcm_info(pcm, info) < 0)
1324 return FALSE;
1325
1326 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1327 }
1328
1329 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1330
1331 const char* pa_alsa_strerror(int errnum) {
1332 const char *original = NULL;
1333 char *translated, *t;
1334 char errbuf[128];
1335
1336 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1337 pa_xfree(t);
1338
1339 original = snd_strerror(errnum);
1340
1341 if (!original) {
1342 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1343 original = errbuf;
1344 }
1345
1346 if (!(translated = pa_locale_to_utf8(original))) {
1347 pa_log_warn("Unable to convert error string to locale, filtering.");
1348 translated = pa_utf8_filter(original);
1349 }
1350
1351 PA_STATIC_TLS_SET(cstrerror, translated);
1352
1353 return translated;
1354 }
1355
1356 pa_bool_t pa_alsa_may_tsched(pa_bool_t want) {
1357
1358 if (!want)
1359 return FALSE;
1360
1361 if (!pa_rtclock_hrtimer()) {
1362 /* We cannot depend on being woken up in time when the timers
1363 are inaccurate, so let's fallback to classic IO based playback
1364 then. */
1365 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1366 return FALSE; }
1367
1368 if (pa_running_in_vm()) {
1369 /* We cannot depend on being woken up when we ask for in a VM,
1370 * so let's fallback to classic IO based playback then. */
1371 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1372 return FALSE;
1373 }
1374
1375 return TRUE;
1376 }