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