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