]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
Whitespace cleanup: Remove all multiple newlines
[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_status_t *status, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss,
1145 pa_bool_t capture) {
1146 ssize_t k;
1147 size_t abs_k;
1148 int err;
1149 snd_pcm_sframes_t avail = 0;
1150
1151 pa_assert(pcm);
1152 pa_assert(delay);
1153 pa_assert(hwbuf_size > 0);
1154 pa_assert(ss);
1155
1156 /* Some ALSA driver expose weird bugs, let's inform the user about
1157 * what is going on. We're going to get both the avail and delay values so
1158 * that we can compare and check them for capture.
1159 * This is done with snd_pcm_status() which provides
1160 * avail, delay and timestamp values in a single kernel call to improve
1161 * timer-based scheduling */
1162
1163 if ((err = snd_pcm_status(pcm, status)) < 0)
1164 return err;
1165
1166 avail = snd_pcm_status_get_avail(status);
1167 *delay = snd_pcm_status_get_delay(status);
1168
1169 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1170
1171 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1172
1173 if (PA_UNLIKELY(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_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1179 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1180 (signed long) k,
1181 k < 0 ? "-" : "",
1182 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1183 pa_strnull(dn));
1184 pa_xfree(dn);
1185 pa_alsa_dump(PA_LOG_ERROR, pcm);
1186 } PA_ONCE_END;
1187
1188 /* Mhmm, let's try not to fail completely */
1189 if (k < 0)
1190 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1191 else
1192 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1193 }
1194
1195 if (capture) {
1196 abs_k = (size_t) avail * pa_frame_size(ss);
1197
1198 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1199 abs_k >= pa_bytes_per_second(ss)*10)) {
1200
1201 PA_ONCE_BEGIN {
1202 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1203 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1204 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1205 (unsigned long) k,
1206 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1207 pa_strnull(dn));
1208 pa_xfree(dn);
1209 pa_alsa_dump(PA_LOG_ERROR, pcm);
1210 } PA_ONCE_END;
1211
1212 /* Mhmm, let's try not to fail completely */
1213 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1214 }
1215
1216 if (PA_UNLIKELY(*delay < avail)) {
1217 PA_ONCE_BEGIN {
1218 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1219 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1220 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1221 (unsigned long) *delay,
1222 (unsigned long) avail,
1223 pa_strnull(dn));
1224 pa_xfree(dn);
1225 pa_alsa_dump(PA_LOG_ERROR, pcm);
1226 } PA_ONCE_END;
1227
1228 /* try to fixup */
1229 *delay = avail;
1230 }
1231 }
1232
1233 return 0;
1234 }
1235
1236 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) {
1237 int r;
1238 snd_pcm_uframes_t before;
1239 size_t k;
1240
1241 pa_assert(pcm);
1242 pa_assert(areas);
1243 pa_assert(offset);
1244 pa_assert(frames);
1245 pa_assert(hwbuf_size > 0);
1246 pa_assert(ss);
1247
1248 before = *frames;
1249
1250 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1251
1252 if (r < 0)
1253 return r;
1254
1255 k = (size_t) *frames * pa_frame_size(ss);
1256
1257 if (PA_UNLIKELY(*frames > before ||
1258 k >= hwbuf_size * 3 ||
1259 k >= pa_bytes_per_second(ss)*10))
1260 PA_ONCE_BEGIN {
1261 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1262 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1263 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1264 (unsigned long) k,
1265 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1266 pa_strnull(dn));
1267 pa_xfree(dn);
1268 pa_alsa_dump(PA_LOG_ERROR, pcm);
1269 } PA_ONCE_END;
1270
1271 return r;
1272 }
1273
1274 char *pa_alsa_get_driver_name(int card) {
1275 char *t, *m, *n;
1276
1277 pa_assert(card >= 0);
1278
1279 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1280 m = pa_readlink(t);
1281 pa_xfree(t);
1282
1283 if (!m)
1284 return NULL;
1285
1286 n = pa_xstrdup(pa_path_get_filename(m));
1287 pa_xfree(m);
1288
1289 return n;
1290 }
1291
1292 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1293 int card;
1294 snd_pcm_info_t* info;
1295 snd_pcm_info_alloca(&info);
1296
1297 pa_assert(pcm);
1298
1299 if (snd_pcm_info(pcm, info) < 0)
1300 return NULL;
1301
1302 if ((card = snd_pcm_info_get_card(info)) < 0)
1303 return NULL;
1304
1305 return pa_alsa_get_driver_name(card);
1306 }
1307
1308 char *pa_alsa_get_reserve_name(const char *device) {
1309 const char *t;
1310 int i;
1311
1312 pa_assert(device);
1313
1314 if ((t = strchr(device, ':')))
1315 device = t+1;
1316
1317 if ((i = snd_card_get_index(device)) < 0) {
1318 int32_t k;
1319
1320 if (pa_atoi(device, &k) < 0)
1321 return NULL;
1322
1323 i = (int) k;
1324 }
1325
1326 return pa_sprintf_malloc("Audio%i", i);
1327 }
1328
1329 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1330 static unsigned int all_rates[] = { 8000, 11025, 12000,
1331 16000, 22050, 24000,
1332 32000, 44100, 48000,
1333 64000, 88200, 96000,
1334 128000, 176400, 192000,
1335 384000 };
1336 pa_bool_t supported[PA_ELEMENTSOF(all_rates)] = { FALSE, };
1337 snd_pcm_hw_params_t *hwparams;
1338 unsigned int i, j, n, *rates = NULL;
1339 int ret;
1340
1341 snd_pcm_hw_params_alloca(&hwparams);
1342
1343 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1344 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1345 return NULL;
1346 }
1347
1348 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1349 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1350 supported[i] = TRUE;
1351 n++;
1352 }
1353 }
1354
1355 if (n > 0) {
1356 rates = pa_xnew(unsigned int, n + 1);
1357
1358 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1359 if (supported[i])
1360 rates[j++] = all_rates[i];
1361 }
1362
1363 rates[j] = 0;
1364 } else {
1365 rates = pa_xnew(unsigned int, 2);
1366
1367 rates[0] = fallback_rate;
1368 if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1369 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1370 pa_xfree(rates);
1371 return NULL;
1372 }
1373
1374 rates[1] = 0;
1375 }
1376
1377 return rates;
1378 }
1379
1380 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1381 snd_pcm_info_t* info;
1382 snd_pcm_info_alloca(&info);
1383
1384 pa_assert(pcm);
1385
1386 if (snd_pcm_info(pcm, info) < 0)
1387 return FALSE;
1388
1389 return snd_pcm_info_get_card(info) >= 0;
1390 }
1391
1392 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1393 snd_pcm_info_t* info;
1394 snd_pcm_info_alloca(&info);
1395
1396 pa_assert(pcm);
1397
1398 if (snd_pcm_info(pcm, info) < 0)
1399 return FALSE;
1400
1401 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1402 }
1403
1404 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1405
1406 const char* pa_alsa_strerror(int errnum) {
1407 const char *original = NULL;
1408 char *translated, *t;
1409 char errbuf[128];
1410
1411 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1412 pa_xfree(t);
1413
1414 original = snd_strerror(errnum);
1415
1416 if (!original) {
1417 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1418 original = errbuf;
1419 }
1420
1421 if (!(translated = pa_locale_to_utf8(original))) {
1422 pa_log_warn("Unable to convert error string to locale, filtering.");
1423 translated = pa_utf8_filter(original);
1424 }
1425
1426 PA_STATIC_TLS_SET(cstrerror, translated);
1427
1428 return translated;
1429 }
1430
1431 pa_bool_t pa_alsa_may_tsched(pa_bool_t want) {
1432
1433 if (!want)
1434 return FALSE;
1435
1436 if (!pa_rtclock_hrtimer()) {
1437 /* We cannot depend on being woken up in time when the timers
1438 are inaccurate, so let's fallback to classic IO based playback
1439 then. */
1440 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1441 return FALSE; }
1442
1443 if (pa_running_in_vm()) {
1444 /* We cannot depend on being woken up when we ask for in a VM,
1445 * so let's fallback to classic IO based playback then. */
1446 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1447 return FALSE;
1448 }
1449
1450 return TRUE;
1451 }
1452
1453 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
1454 snd_ctl_elem_id_t *id;
1455
1456 snd_ctl_elem_id_alloca(&id);
1457 snd_ctl_elem_id_clear(id);
1458 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
1459 snd_ctl_elem_id_set_name(id, jack_name);
1460
1461 return snd_hctl_find_elem(hctl, id);
1462 }
1463
1464 snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
1465 snd_ctl_elem_id_t *id;
1466
1467 /* See if we can find the ELD control */
1468 snd_ctl_elem_id_alloca(&id);
1469 snd_ctl_elem_id_clear(id);
1470 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1471 snd_ctl_elem_id_set_name(id, "ELD");
1472 snd_ctl_elem_id_set_device(id, device);
1473
1474 return snd_hctl_find_elem(hctl, id);
1475 }
1476
1477 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
1478 int err;
1479
1480 pa_assert(mixer);
1481 pa_assert(dev);
1482
1483 if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1484 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1485 return -1;
1486 }
1487
1488 /* Note: The hctl handle returned should not be freed.
1489 It is closed/freed by alsa-lib on snd_mixer_close/free */
1490 if (hctl && (err = snd_mixer_get_hctl(mixer, dev, hctl)) < 0) {
1491 pa_log_info("Unable to get hctl of mixer %s: %s", dev, pa_alsa_strerror(err));
1492 return -1;
1493 }
1494
1495 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1496 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1497 return -1;
1498 }
1499
1500 if ((err = snd_mixer_load(mixer)) < 0) {
1501 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1502 return -1;
1503 }
1504
1505 pa_log_info("Successfully attached to mixer '%s'", dev);
1506 return 0;
1507 }
1508
1509 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl) {
1510 int err;
1511 snd_mixer_t *m;
1512 char *md;
1513 snd_pcm_info_t* info;
1514 snd_pcm_info_alloca(&info);
1515
1516 if ((err = snd_mixer_open(&m, 0)) < 0) {
1517 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1518 return NULL;
1519 }
1520
1521 /* Then, try by card index */
1522 md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1523 if (prepare_mixer(m, md, hctl) >= 0) {
1524
1525 if (ctl_device)
1526 *ctl_device = md;
1527 else
1528 pa_xfree(md);
1529
1530 return m;
1531 }
1532
1533 pa_xfree(md);
1534
1535 snd_mixer_close(m);
1536 return NULL;
1537 }
1538
1539 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl) {
1540 int err;
1541 snd_mixer_t *m;
1542 const char *dev;
1543 snd_pcm_info_t* info;
1544 snd_pcm_info_alloca(&info);
1545
1546 pa_assert(pcm);
1547
1548 if ((err = snd_mixer_open(&m, 0)) < 0) {
1549 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1550 return NULL;
1551 }
1552
1553 /* First, try by name */
1554 if ((dev = snd_pcm_name(pcm)))
1555 if (prepare_mixer(m, dev, hctl) >= 0) {
1556 if (ctl_device)
1557 *ctl_device = pa_xstrdup(dev);
1558
1559 return m;
1560 }
1561
1562 /* Then, try by card index */
1563 if (snd_pcm_info(pcm, info) >= 0) {
1564 char *md;
1565 int card_idx;
1566
1567 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1568
1569 md = pa_sprintf_malloc("hw:%i", card_idx);
1570
1571 if (!dev || !pa_streq(dev, md))
1572 if (prepare_mixer(m, md, hctl) >= 0) {
1573
1574 if (ctl_device)
1575 *ctl_device = md;
1576 else
1577 pa_xfree(md);
1578
1579 return m;
1580 }
1581
1582 pa_xfree(md);
1583 }
1584 }
1585
1586 snd_mixer_close(m);
1587 return NULL;
1588 }
1589
1590 int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
1591
1592 /* The ELD format is specific to HDA Intel sound cards and defined in the
1593 HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1594 int err;
1595 snd_hctl_elem_t *elem;
1596 snd_ctl_elem_info_t *info;
1597 snd_ctl_elem_value_t *value;
1598 uint8_t *elddata;
1599 unsigned int eldsize, mnl;
1600
1601 pa_assert(eld != NULL);
1602
1603 /* See if we can find the ELD control */
1604 elem = pa_alsa_find_eld_ctl(hctl, device);
1605 if (elem == NULL) {
1606 pa_log_debug("No ELD info control found (for device=%d)", device);
1607 return -1;
1608 }
1609
1610 /* Does it have any contents? */
1611 snd_ctl_elem_info_alloca(&info);
1612 snd_ctl_elem_value_alloca(&value);
1613 if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1614 (err = snd_hctl_elem_read(elem, value)) < 0) {
1615 pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1616 return -1;
1617 }
1618
1619 eldsize = snd_ctl_elem_info_get_count(info);
1620 elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1621 if (elddata == NULL || eldsize == 0) {
1622 pa_log_debug("ELD info empty (for device=%d)", device);
1623 return -1;
1624 }
1625 if (eldsize < 20 || eldsize > 256) {
1626 pa_log_debug("ELD info has wrong size (for device=%d)", device);
1627 return -1;
1628 }
1629
1630 /* Try to fetch monitor name */
1631 mnl = elddata[4] & 0x1f;
1632 if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
1633 pa_log_debug("No monitor name in ELD info (for device=%d)", device);
1634 mnl = 0;
1635 }
1636 memcpy(eld->monitor_name, &elddata[20], mnl);
1637 eld->monitor_name[mnl] = '\0';
1638 if (mnl)
1639 pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
1640
1641 return 0;
1642 }