]> code.delx.au - pulseaudio/blob - src/modules/alsa/alsa-util.c
dca1f2e4c54d43554a15cfd3f9fffad58305e305
[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 bool *use_mmap,
195 bool *use_tsched,
196 bool 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 bool _use_mmap = use_mmap && *use_mmap;
204 bool _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 /* The PCM pointer is only updated with period granularity */
249 if (snd_pcm_hw_params_is_batch(hwparams)) {
250 pa_log_info("Disabling tsched mode since BATCH flag is set");
251 _use_tsched = false;
252 }
253
254 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
255 if (_use_tsched) {
256
257 /* try to disable period wakeups if hardware can do so */
258 if (snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
259
260 if ((ret = snd_pcm_hw_params_set_period_wakeup(pcm_handle, hwparams, false)) < 0)
261 /* don't bail, keep going with default mode with period wakeups */
262 pa_log_debug("snd_pcm_hw_params_set_period_wakeup() failed: %s", pa_alsa_strerror(ret));
263 else
264 pa_log_info("Trying to disable ALSA period wakeups, using timers only");
265 } else
266 pa_log_info("cannot disable ALSA period wakeups");
267 }
268 #endif
269
270 if ((ret = set_format(pcm_handle, hwparams, &_ss.format)) < 0)
271 goto finish;
272
273 if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &_ss.rate, NULL)) < 0) {
274 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
275 goto finish;
276 }
277
278 /* We ignore very small sampling rate deviations */
279 if (_ss.rate >= ss->rate*.95 && _ss.rate <= ss->rate*1.05)
280 _ss.rate = ss->rate;
281
282 if (require_exact_channel_number) {
283 if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, _ss.channels)) < 0) {
284 pa_log_debug("snd_pcm_hw_params_set_channels(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
285 goto finish;
286 }
287 } else {
288 unsigned int c = _ss.channels;
289
290 if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
291 pa_log_debug("snd_pcm_hw_params_set_channels_near(%u) failed: %s", _ss.channels, pa_alsa_strerror(ret));
292 goto finish;
293 }
294
295 _ss.channels = c;
296 }
297
298 if (_use_tsched && tsched_size > 0) {
299 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * _ss.rate) / ss->rate);
300 _period_size = _buffer_size;
301 } else {
302 _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * _ss.rate) / ss->rate);
303 _buffer_size = (snd_pcm_uframes_t) (((uint64_t) _buffer_size * _ss.rate) / ss->rate);
304 }
305
306 if (_buffer_size > 0 || _period_size > 0) {
307 snd_pcm_uframes_t max_frames = 0;
308
309 if ((ret = snd_pcm_hw_params_get_buffer_size_max(hwparams, &max_frames)) < 0)
310 pa_log_warn("snd_pcm_hw_params_get_buffer_size_max() failed: %s", pa_alsa_strerror(ret));
311 else
312 pa_log_debug("Maximum hw buffer size is %lu ms", (long unsigned) (max_frames * PA_MSEC_PER_SEC / _ss.rate));
313
314 /* Some ALSA drivers really don't like if we set the buffer
315 * size first and the number of periods second (which would
316 * make a lot more sense to me). So, try a few combinations
317 * before we give up. */
318
319 if (_buffer_size > 0 && _period_size > 0) {
320 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
321
322 /* First try: set buffer size first, followed by period size */
323 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
324 set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
325 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
326 pa_log_debug("Set buffer size first (to %lu samples), period size second (to %lu samples).", (unsigned long) _buffer_size, (unsigned long) _period_size);
327 goto success;
328 }
329
330 /* Second try: set period size first, followed by buffer size */
331 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
332 set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
333 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
334 pa_log_debug("Set period size first (to %lu samples), buffer size second (to %lu samples).", (unsigned long) _period_size, (unsigned long) _buffer_size);
335 goto success;
336 }
337 }
338
339 if (_buffer_size > 0) {
340 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
341
342 /* Third try: set only buffer size */
343 if (set_buffer_size(pcm_handle, hwparams_copy, _buffer_size) >= 0 &&
344 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
345 pa_log_debug("Set only buffer size (to %lu samples).", (unsigned long) _buffer_size);
346 goto success;
347 }
348 }
349
350 if (_period_size > 0) {
351 snd_pcm_hw_params_copy(hwparams_copy, hwparams);
352
353 /* Fourth try: set only period size */
354 if (set_period_size(pcm_handle, hwparams_copy, _period_size) >= 0 &&
355 snd_pcm_hw_params(pcm_handle, hwparams_copy) >= 0) {
356 pa_log_debug("Set only period size (to %lu samples).", (unsigned long) _period_size);
357 goto success;
358 }
359 }
360 }
361
362 pa_log_debug("Set neither period nor buffer size.");
363
364 /* Last chance, set nothing */
365 if ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
366 pa_log_info("snd_pcm_hw_params failed: %s", pa_alsa_strerror(ret));
367 goto finish;
368 }
369
370 success:
371
372 if (ss->rate != _ss.rate)
373 pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, _ss.rate);
374
375 if (ss->channels != _ss.channels)
376 pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, _ss.channels);
377
378 if (ss->format != _ss.format)
379 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));
380
381 if ((ret = snd_pcm_prepare(pcm_handle)) < 0) {
382 pa_log_info("snd_pcm_prepare() failed: %s", pa_alsa_strerror(ret));
383 goto finish;
384 }
385
386 if ((ret = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) {
387 pa_log_info("snd_pcm_hw_params_current() failed: %s", pa_alsa_strerror(ret));
388 goto finish;
389 }
390
391 if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
392 (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
393 pa_log_info("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", pa_alsa_strerror(ret));
394 goto finish;
395 }
396
397 #if (SND_LIB_VERSION >= ((1<<16)|(0<<8)|24)) /* API additions in 1.0.24 */
398 if (_use_tsched) {
399 unsigned int no_wakeup;
400 /* see if period wakeups were disabled */
401 snd_pcm_hw_params_get_period_wakeup(pcm_handle, hwparams, &no_wakeup);
402 if (no_wakeup == 0)
403 pa_log_info("ALSA period wakeups disabled");
404 else
405 pa_log_info("ALSA period wakeups were not disabled");
406 }
407 #endif
408
409 ss->rate = _ss.rate;
410 ss->channels = _ss.channels;
411 ss->format = _ss.format;
412
413 pa_assert(_period_size > 0);
414 pa_assert(_buffer_size > 0);
415
416 if (buffer_size)
417 *buffer_size = _buffer_size;
418
419 if (period_size)
420 *period_size = _period_size;
421
422 if (use_mmap)
423 *use_mmap = _use_mmap;
424
425 if (use_tsched)
426 *use_tsched = _use_tsched;
427
428 ret = 0;
429
430 finish:
431
432 return ret;
433 }
434
435 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
436 snd_pcm_sw_params_t *swparams;
437 snd_pcm_uframes_t boundary;
438 int err;
439
440 pa_assert(pcm);
441
442 snd_pcm_sw_params_alloca(&swparams);
443
444 if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
445 pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
446 return err;
447 }
448
449 if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
450 pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
451 return err;
452 }
453
454 if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
455 pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
456 return err;
457 }
458
459 if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
460 pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
461 return err;
462 }
463
464 if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
465 pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
466 return err;
467 }
468
469 if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
470 pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
471 return err;
472 }
473
474 if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
475 pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
476 return err;
477 }
478
479 if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
480 pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
481 return err;
482 }
483
484 return 0;
485 }
486
487 snd_pcm_t *pa_alsa_open_by_device_id_auto(
488 const char *dev_id,
489 char **dev,
490 pa_sample_spec *ss,
491 pa_channel_map* map,
492 int mode,
493 snd_pcm_uframes_t *period_size,
494 snd_pcm_uframes_t *buffer_size,
495 snd_pcm_uframes_t tsched_size,
496 bool *use_mmap,
497 bool *use_tsched,
498 pa_alsa_profile_set *ps,
499 pa_alsa_mapping **mapping) {
500
501 char *d;
502 snd_pcm_t *pcm_handle;
503 void *state;
504 pa_alsa_mapping *m;
505
506 pa_assert(dev_id);
507 pa_assert(dev);
508 pa_assert(ss);
509 pa_assert(map);
510 pa_assert(ps);
511
512 /* First we try to find a device string with a superset of the
513 * requested channel map. We iterate through our device table from
514 * top to bottom and take the first that matches. If we didn't
515 * find a working device that way, we iterate backwards, and check
516 * all devices that do not provide a superset of the requested
517 * channel map.*/
518
519 PA_HASHMAP_FOREACH(m, ps->mappings, state) {
520 if (!pa_channel_map_superset(&m->channel_map, map))
521 continue;
522
523 pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
524
525 pcm_handle = pa_alsa_open_by_device_id_mapping(
526 dev_id,
527 dev,
528 ss,
529 map,
530 mode,
531 period_size,
532 buffer_size,
533 tsched_size,
534 use_mmap,
535 use_tsched,
536 m);
537
538 if (pcm_handle) {
539 if (mapping)
540 *mapping = m;
541
542 return pcm_handle;
543 }
544 }
545
546 PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
547 if (pa_channel_map_superset(&m->channel_map, map))
548 continue;
549
550 pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
551
552 pcm_handle = pa_alsa_open_by_device_id_mapping(
553 dev_id,
554 dev,
555 ss,
556 map,
557 mode,
558 period_size,
559 buffer_size,
560 tsched_size,
561 use_mmap,
562 use_tsched,
563 m);
564
565 if (pcm_handle) {
566 if (mapping)
567 *mapping = m;
568
569 return pcm_handle;
570 }
571 }
572
573 /* OK, we didn't find any good device, so let's try the raw hw: stuff */
574 d = pa_sprintf_malloc("hw:%s", dev_id);
575 pa_log_debug("Trying %s as last resort...", d);
576 pcm_handle = pa_alsa_open_by_device_string(
577 d,
578 dev,
579 ss,
580 map,
581 mode,
582 period_size,
583 buffer_size,
584 tsched_size,
585 use_mmap,
586 use_tsched,
587 false);
588 pa_xfree(d);
589
590 if (pcm_handle && mapping)
591 *mapping = NULL;
592
593 return pcm_handle;
594 }
595
596 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
597 const char *dev_id,
598 char **dev,
599 pa_sample_spec *ss,
600 pa_channel_map* map,
601 int mode,
602 snd_pcm_uframes_t *period_size,
603 snd_pcm_uframes_t *buffer_size,
604 snd_pcm_uframes_t tsched_size,
605 bool *use_mmap,
606 bool *use_tsched,
607 pa_alsa_mapping *m) {
608
609 snd_pcm_t *pcm_handle;
610 pa_sample_spec try_ss;
611 pa_channel_map try_map;
612
613 pa_assert(dev_id);
614 pa_assert(dev);
615 pa_assert(ss);
616 pa_assert(map);
617 pa_assert(m);
618
619 try_ss.channels = m->channel_map.channels;
620 try_ss.rate = ss->rate;
621 try_ss.format = ss->format;
622 try_map = m->channel_map;
623
624 pcm_handle = pa_alsa_open_by_template(
625 m->device_strings,
626 dev_id,
627 dev,
628 &try_ss,
629 &try_map,
630 mode,
631 period_size,
632 buffer_size,
633 tsched_size,
634 use_mmap,
635 use_tsched,
636 pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
637
638 if (!pcm_handle)
639 return NULL;
640
641 *ss = try_ss;
642 *map = try_map;
643 pa_assert(map->channels == ss->channels);
644
645 return pcm_handle;
646 }
647
648 snd_pcm_t *pa_alsa_open_by_device_string(
649 const char *device,
650 char **dev,
651 pa_sample_spec *ss,
652 pa_channel_map* map,
653 int mode,
654 snd_pcm_uframes_t *period_size,
655 snd_pcm_uframes_t *buffer_size,
656 snd_pcm_uframes_t tsched_size,
657 bool *use_mmap,
658 bool *use_tsched,
659 bool require_exact_channel_number) {
660
661 int err;
662 char *d;
663 snd_pcm_t *pcm_handle;
664 bool reformat = false;
665
666 pa_assert(device);
667 pa_assert(ss);
668 pa_assert(map);
669
670 d = pa_xstrdup(device);
671
672 for (;;) {
673 pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
674
675 if ((err = snd_pcm_open(&pcm_handle, d, mode,
676 SND_PCM_NONBLOCK|
677 SND_PCM_NO_AUTO_RESAMPLE|
678 SND_PCM_NO_AUTO_CHANNELS|
679 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
680 pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
681 goto fail;
682 }
683
684 pa_log_debug("Managed to open %s", d);
685
686 if ((err = pa_alsa_set_hw_params(
687 pcm_handle,
688 ss,
689 period_size,
690 buffer_size,
691 tsched_size,
692 use_mmap,
693 use_tsched,
694 require_exact_channel_number)) < 0) {
695
696 if (!reformat) {
697 reformat = true;
698
699 snd_pcm_close(pcm_handle);
700 continue;
701 }
702
703 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
704 if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
705 char *t;
706
707 t = pa_sprintf_malloc("plug:%s", d);
708 pa_xfree(d);
709 d = t;
710
711 reformat = false;
712
713 snd_pcm_close(pcm_handle);
714 continue;
715 }
716
717 pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
718 snd_pcm_close(pcm_handle);
719
720 goto fail;
721 }
722
723 if (dev)
724 *dev = d;
725 else
726 pa_xfree(d);
727
728 if (ss->channels != map->channels)
729 pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
730
731 return pcm_handle;
732 }
733
734 fail:
735 pa_xfree(d);
736
737 return NULL;
738 }
739
740 snd_pcm_t *pa_alsa_open_by_template(
741 char **template,
742 const char *dev_id,
743 char **dev,
744 pa_sample_spec *ss,
745 pa_channel_map* map,
746 int mode,
747 snd_pcm_uframes_t *period_size,
748 snd_pcm_uframes_t *buffer_size,
749 snd_pcm_uframes_t tsched_size,
750 bool *use_mmap,
751 bool *use_tsched,
752 bool require_exact_channel_number) {
753
754 snd_pcm_t *pcm_handle;
755 char **i;
756
757 for (i = template; *i; i++) {
758 char *d;
759
760 d = pa_replace(*i, "%f", dev_id);
761
762 pcm_handle = pa_alsa_open_by_device_string(
763 d,
764 dev,
765 ss,
766 map,
767 mode,
768 period_size,
769 buffer_size,
770 tsched_size,
771 use_mmap,
772 use_tsched,
773 require_exact_channel_number);
774
775 pa_xfree(d);
776
777 if (pcm_handle)
778 return pcm_handle;
779 }
780
781 return NULL;
782 }
783
784 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
785 int err;
786 snd_output_t *out;
787
788 pa_assert(pcm);
789
790 pa_assert_se(snd_output_buffer_open(&out) == 0);
791
792 if ((err = snd_pcm_dump(pcm, out)) < 0)
793 pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
794 else {
795 char *s = NULL;
796 snd_output_buffer_string(out, &s);
797 pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
798 }
799
800 pa_assert_se(snd_output_close(out) == 0);
801 }
802
803 void pa_alsa_dump_status(snd_pcm_t *pcm) {
804 int err;
805 snd_output_t *out;
806 snd_pcm_status_t *status;
807 char *s = NULL;
808
809 pa_assert(pcm);
810
811 snd_pcm_status_alloca(&status);
812
813 if ((err = snd_output_buffer_open(&out)) < 0) {
814 pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
815 return;
816 }
817
818 if ((err = snd_pcm_status(pcm, status)) < 0) {
819 pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
820 goto finish;
821 }
822
823 if ((err = snd_pcm_status_dump(status, out)) < 0) {
824 pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err));
825 goto finish;
826 }
827
828 snd_output_buffer_string(out, &s);
829 pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s));
830
831 finish:
832
833 snd_output_close(out);
834 }
835
836 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
837 va_list ap;
838 char *alsa_file;
839
840 alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
841
842 va_start(ap, fmt);
843
844 pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
845
846 va_end(ap);
847
848 pa_xfree(alsa_file);
849 }
850
851 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
852
853 void pa_alsa_refcnt_inc(void) {
854 /* This is not really thread safe, but we do our best */
855
856 if (pa_atomic_inc(&n_error_handler_installed) == 0)
857 snd_lib_error_set_handler(alsa_error_handler);
858 }
859
860 void pa_alsa_refcnt_dec(void) {
861 int r;
862
863 pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
864
865 if (r == 1) {
866 snd_lib_error_set_handler(NULL);
867 snd_config_update_free_global();
868 }
869 }
870
871 bool pa_alsa_init_description(pa_proplist *p, pa_card *card) {
872 const char *d, *k;
873 pa_assert(p);
874
875 if (pa_device_init_description(p, card))
876 return true;
877
878 if (!(d = pa_proplist_gets(p, "alsa.card_name")))
879 d = pa_proplist_gets(p, "alsa.name");
880
881 if (!d)
882 return false;
883
884 k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
885
886 if (d && k)
887 pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
888 else if (d)
889 pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
890
891 return false;
892 }
893
894 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
895 char *cn, *lcn, *dn;
896
897 pa_assert(p);
898 pa_assert(card >= 0);
899
900 pa_proplist_setf(p, "alsa.card", "%i", card);
901
902 if (snd_card_get_name(card, &cn) >= 0) {
903 pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
904 free(cn);
905 }
906
907 if (snd_card_get_longname(card, &lcn) >= 0) {
908 pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
909 free(lcn);
910 }
911
912 if ((dn = pa_alsa_get_driver_name(card))) {
913 pa_proplist_sets(p, "alsa.driver_name", dn);
914 pa_xfree(dn);
915 }
916
917 #ifdef HAVE_UDEV
918 pa_udev_get_info(card, p);
919 #endif
920 }
921
922 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
923
924 static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
925 [SND_PCM_CLASS_GENERIC] = "generic",
926 [SND_PCM_CLASS_MULTI] = "multi",
927 [SND_PCM_CLASS_MODEM] = "modem",
928 [SND_PCM_CLASS_DIGITIZER] = "digitizer"
929 };
930 static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
931 [SND_PCM_CLASS_GENERIC] = "sound",
932 [SND_PCM_CLASS_MULTI] = NULL,
933 [SND_PCM_CLASS_MODEM] = "modem",
934 [SND_PCM_CLASS_DIGITIZER] = NULL
935 };
936 static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
937 [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
938 [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
939 };
940
941 snd_pcm_class_t class;
942 snd_pcm_subclass_t subclass;
943 const char *n, *id, *sdn;
944 int card;
945
946 pa_assert(p);
947 pa_assert(pcm_info);
948
949 pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
950
951 if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
952 if (class_table[class])
953 pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
954 if (alsa_class_table[class])
955 pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
956 }
957
958 if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
959 if (alsa_subclass_table[subclass])
960 pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
961
962 if ((n = snd_pcm_info_get_name(pcm_info))) {
963 char *t = pa_xstrdup(n);
964 pa_proplist_sets(p, "alsa.name", pa_strip(t));
965 pa_xfree(t);
966 }
967
968 if ((id = snd_pcm_info_get_id(pcm_info)))
969 pa_proplist_sets(p, "alsa.id", id);
970
971 pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
972 if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
973 pa_proplist_sets(p, "alsa.subdevice_name", sdn);
974
975 pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
976
977 if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
978 pa_alsa_init_proplist_card(c, p, card);
979 }
980
981 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
982 snd_pcm_hw_params_t *hwparams;
983 snd_pcm_info_t *info;
984 int bits, err;
985
986 snd_pcm_hw_params_alloca(&hwparams);
987 snd_pcm_info_alloca(&info);
988
989 if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
990 pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
991 else {
992
993 if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
994 pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
995 }
996
997 if ((err = snd_pcm_info(pcm, info)) < 0)
998 pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
999 else
1000 pa_alsa_init_proplist_pcm_info(c, p, info);
1001 }
1002
1003 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1004 int err;
1005 snd_ctl_t *ctl;
1006 snd_ctl_card_info_t *info;
1007 const char *t;
1008
1009 pa_assert(p);
1010
1011 snd_ctl_card_info_alloca(&info);
1012
1013 if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1014 pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1015 return;
1016 }
1017
1018 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1019 pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1020 snd_ctl_close(ctl);
1021 return;
1022 }
1023
1024 if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1025 pa_proplist_sets(p, "alsa.mixer_name", t);
1026
1027 if ((t = snd_ctl_card_info_get_components(info)) && *t)
1028 pa_proplist_sets(p, "alsa.components", t);
1029
1030 snd_ctl_close(ctl);
1031 }
1032
1033 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1034 snd_pcm_state_t state;
1035 int err;
1036
1037 pa_assert(pcm);
1038
1039 if (revents & POLLERR)
1040 pa_log_debug("Got POLLERR from ALSA");
1041 if (revents & POLLNVAL)
1042 pa_log_warn("Got POLLNVAL from ALSA");
1043 if (revents & POLLHUP)
1044 pa_log_warn("Got POLLHUP from ALSA");
1045 if (revents & POLLPRI)
1046 pa_log_warn("Got POLLPRI from ALSA");
1047 if (revents & POLLIN)
1048 pa_log_debug("Got POLLIN from ALSA");
1049 if (revents & POLLOUT)
1050 pa_log_debug("Got POLLOUT from ALSA");
1051
1052 state = snd_pcm_state(pcm);
1053 pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1054
1055 /* Try to recover from this error */
1056
1057 switch (state) {
1058
1059 case SND_PCM_STATE_XRUN:
1060 if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1061 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1062 return -1;
1063 }
1064 break;
1065
1066 case SND_PCM_STATE_SUSPENDED:
1067 if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1068 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1069 return -1;
1070 }
1071 break;
1072
1073 default:
1074
1075 snd_pcm_drop(pcm);
1076
1077 if ((err = snd_pcm_prepare(pcm)) < 0) {
1078 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1079 return -1;
1080 }
1081 break;
1082 }
1083
1084 return 0;
1085 }
1086
1087 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1088 int n, err;
1089 struct pollfd *pollfd;
1090 pa_rtpoll_item *item;
1091
1092 pa_assert(pcm);
1093
1094 if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1095 pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1096 return NULL;
1097 }
1098
1099 item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1100 pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1101
1102 if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1103 pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1104 pa_rtpoll_item_free(item);
1105 return NULL;
1106 }
1107
1108 return item;
1109 }
1110
1111 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1112 snd_pcm_sframes_t n;
1113 size_t k;
1114
1115 pa_assert(pcm);
1116 pa_assert(hwbuf_size > 0);
1117 pa_assert(ss);
1118
1119 /* Some ALSA driver expose weird bugs, let's inform the user about
1120 * what is going on */
1121
1122 n = snd_pcm_avail(pcm);
1123
1124 if (n <= 0)
1125 return n;
1126
1127 k = (size_t) n * pa_frame_size(ss);
1128
1129 if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1130 k >= pa_bytes_per_second(ss)*10)) {
1131
1132 PA_ONCE_BEGIN {
1133 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1134 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1135 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1136 (unsigned long) k,
1137 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1138 pa_strnull(dn));
1139 pa_xfree(dn);
1140 pa_alsa_dump(PA_LOG_ERROR, pcm);
1141 } PA_ONCE_END;
1142
1143 /* Mhmm, let's try not to fail completely */
1144 n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1145 }
1146
1147 return n;
1148 }
1149
1150 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,
1151 bool capture) {
1152 ssize_t k;
1153 size_t abs_k;
1154 int err;
1155 snd_pcm_sframes_t avail = 0;
1156
1157 pa_assert(pcm);
1158 pa_assert(delay);
1159 pa_assert(hwbuf_size > 0);
1160 pa_assert(ss);
1161
1162 /* Some ALSA driver expose weird bugs, let's inform the user about
1163 * what is going on. We're going to get both the avail and delay values so
1164 * that we can compare and check them for capture.
1165 * This is done with snd_pcm_status() which provides
1166 * avail, delay and timestamp values in a single kernel call to improve
1167 * timer-based scheduling */
1168
1169 if ((err = snd_pcm_status(pcm, status)) < 0)
1170 return err;
1171
1172 avail = snd_pcm_status_get_avail(status);
1173 *delay = snd_pcm_status_get_delay(status);
1174
1175 k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1176
1177 abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1178
1179 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1180 abs_k >= pa_bytes_per_second(ss)*10)) {
1181
1182 PA_ONCE_BEGIN {
1183 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1184 pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1185 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1186 (signed long) k,
1187 k < 0 ? "-" : "",
1188 (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1189 pa_strnull(dn));
1190 pa_xfree(dn);
1191 pa_alsa_dump(PA_LOG_ERROR, pcm);
1192 } PA_ONCE_END;
1193
1194 /* Mhmm, let's try not to fail completely */
1195 if (k < 0)
1196 *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1197 else
1198 *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1199 }
1200
1201 if (capture) {
1202 abs_k = (size_t) avail * pa_frame_size(ss);
1203
1204 if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1205 abs_k >= pa_bytes_per_second(ss)*10)) {
1206
1207 PA_ONCE_BEGIN {
1208 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1209 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1210 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1211 (unsigned long) k,
1212 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1213 pa_strnull(dn));
1214 pa_xfree(dn);
1215 pa_alsa_dump(PA_LOG_ERROR, pcm);
1216 } PA_ONCE_END;
1217
1218 /* Mhmm, let's try not to fail completely */
1219 avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1220 }
1221
1222 if (PA_UNLIKELY(*delay < avail)) {
1223 PA_ONCE_BEGIN {
1224 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1225 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1226 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1227 (unsigned long) *delay,
1228 (unsigned long) avail,
1229 pa_strnull(dn));
1230 pa_xfree(dn);
1231 pa_alsa_dump(PA_LOG_ERROR, pcm);
1232 } PA_ONCE_END;
1233
1234 /* try to fixup */
1235 *delay = avail;
1236 }
1237 }
1238
1239 return 0;
1240 }
1241
1242 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) {
1243 int r;
1244 snd_pcm_uframes_t before;
1245 size_t k;
1246
1247 pa_assert(pcm);
1248 pa_assert(areas);
1249 pa_assert(offset);
1250 pa_assert(frames);
1251 pa_assert(hwbuf_size > 0);
1252 pa_assert(ss);
1253
1254 before = *frames;
1255
1256 r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1257
1258 if (r < 0)
1259 return r;
1260
1261 k = (size_t) *frames * pa_frame_size(ss);
1262
1263 if (PA_UNLIKELY(*frames > before ||
1264 k >= hwbuf_size * 3 ||
1265 k >= pa_bytes_per_second(ss)*10))
1266 PA_ONCE_BEGIN {
1267 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1268 pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1269 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1270 (unsigned long) k,
1271 (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1272 pa_strnull(dn));
1273 pa_xfree(dn);
1274 pa_alsa_dump(PA_LOG_ERROR, pcm);
1275 } PA_ONCE_END;
1276
1277 return r;
1278 }
1279
1280 char *pa_alsa_get_driver_name(int card) {
1281 char *t, *m, *n;
1282
1283 pa_assert(card >= 0);
1284
1285 t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1286 m = pa_readlink(t);
1287 pa_xfree(t);
1288
1289 if (!m)
1290 return NULL;
1291
1292 n = pa_xstrdup(pa_path_get_filename(m));
1293 pa_xfree(m);
1294
1295 return n;
1296 }
1297
1298 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1299 int card;
1300 snd_pcm_info_t* info;
1301 snd_pcm_info_alloca(&info);
1302
1303 pa_assert(pcm);
1304
1305 if (snd_pcm_info(pcm, info) < 0)
1306 return NULL;
1307
1308 if ((card = snd_pcm_info_get_card(info)) < 0)
1309 return NULL;
1310
1311 return pa_alsa_get_driver_name(card);
1312 }
1313
1314 char *pa_alsa_get_reserve_name(const char *device) {
1315 const char *t;
1316 int i;
1317
1318 pa_assert(device);
1319
1320 if ((t = strchr(device, ':')))
1321 device = t+1;
1322
1323 if ((i = snd_card_get_index(device)) < 0) {
1324 int32_t k;
1325
1326 if (pa_atoi(device, &k) < 0)
1327 return NULL;
1328
1329 i = (int) k;
1330 }
1331
1332 return pa_sprintf_malloc("Audio%i", i);
1333 }
1334
1335 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1336 static unsigned int all_rates[] = { 8000, 11025, 12000,
1337 16000, 22050, 24000,
1338 32000, 44100, 48000,
1339 64000, 88200, 96000,
1340 128000, 176400, 192000,
1341 384000 };
1342 bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
1343 snd_pcm_hw_params_t *hwparams;
1344 unsigned int i, j, n, *rates = NULL;
1345 int ret;
1346
1347 snd_pcm_hw_params_alloca(&hwparams);
1348
1349 if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1350 pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1351 return NULL;
1352 }
1353
1354 for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1355 if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1356 supported[i] = true;
1357 n++;
1358 }
1359 }
1360
1361 if (n > 0) {
1362 rates = pa_xnew(unsigned int, n + 1);
1363
1364 for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1365 if (supported[i])
1366 rates[j++] = all_rates[i];
1367 }
1368
1369 rates[j] = 0;
1370 } else {
1371 rates = pa_xnew(unsigned int, 2);
1372
1373 rates[0] = fallback_rate;
1374 if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1375 pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1376 pa_xfree(rates);
1377 return NULL;
1378 }
1379
1380 rates[1] = 0;
1381 }
1382
1383 return rates;
1384 }
1385
1386 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1387 snd_pcm_info_t* info;
1388 snd_pcm_info_alloca(&info);
1389
1390 pa_assert(pcm);
1391
1392 if (snd_pcm_info(pcm, info) < 0)
1393 return false;
1394
1395 return snd_pcm_info_get_card(info) >= 0;
1396 }
1397
1398 bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1399 snd_pcm_info_t* info;
1400 snd_pcm_info_alloca(&info);
1401
1402 pa_assert(pcm);
1403
1404 if (snd_pcm_info(pcm, info) < 0)
1405 return false;
1406
1407 return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1408 }
1409
1410 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1411
1412 const char* pa_alsa_strerror(int errnum) {
1413 const char *original = NULL;
1414 char *translated, *t;
1415 char errbuf[128];
1416
1417 if ((t = PA_STATIC_TLS_GET(cstrerror)))
1418 pa_xfree(t);
1419
1420 original = snd_strerror(errnum);
1421
1422 if (!original) {
1423 pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1424 original = errbuf;
1425 }
1426
1427 if (!(translated = pa_locale_to_utf8(original))) {
1428 pa_log_warn("Unable to convert error string to locale, filtering.");
1429 translated = pa_utf8_filter(original);
1430 }
1431
1432 PA_STATIC_TLS_SET(cstrerror, translated);
1433
1434 return translated;
1435 }
1436
1437 bool pa_alsa_may_tsched(bool want) {
1438
1439 if (!want)
1440 return false;
1441
1442 if (!pa_rtclock_hrtimer()) {
1443 /* We cannot depend on being woken up in time when the timers
1444 are inaccurate, so let's fallback to classic IO based playback
1445 then. */
1446 pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1447 return false; }
1448
1449 if (pa_running_in_vm()) {
1450 /* We cannot depend on being woken up when we ask for in a VM,
1451 * so let's fallback to classic IO based playback then. */
1452 pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1453 return false;
1454 }
1455
1456 return true;
1457 }
1458
1459 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
1460 snd_ctl_elem_id_t *id;
1461
1462 snd_ctl_elem_id_alloca(&id);
1463 snd_ctl_elem_id_clear(id);
1464 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
1465 snd_ctl_elem_id_set_name(id, jack_name);
1466
1467 return snd_hctl_find_elem(hctl, id);
1468 }
1469
1470 snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
1471 snd_ctl_elem_id_t *id;
1472
1473 /* See if we can find the ELD control */
1474 snd_ctl_elem_id_alloca(&id);
1475 snd_ctl_elem_id_clear(id);
1476 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1477 snd_ctl_elem_id_set_name(id, "ELD");
1478 snd_ctl_elem_id_set_device(id, device);
1479
1480 return snd_hctl_find_elem(hctl, id);
1481 }
1482
1483 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
1484 int err;
1485
1486 pa_assert(mixer);
1487 pa_assert(dev);
1488
1489 if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1490 pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1491 return -1;
1492 }
1493
1494 /* Note: The hctl handle returned should not be freed.
1495 It is closed/freed by alsa-lib on snd_mixer_close/free */
1496 if (hctl && (err = snd_mixer_get_hctl(mixer, dev, hctl)) < 0) {
1497 pa_log_info("Unable to get hctl of mixer %s: %s", dev, pa_alsa_strerror(err));
1498 return -1;
1499 }
1500
1501 if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1502 pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1503 return -1;
1504 }
1505
1506 if ((err = snd_mixer_load(mixer)) < 0) {
1507 pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1508 return -1;
1509 }
1510
1511 pa_log_info("Successfully attached to mixer '%s'", dev);
1512 return 0;
1513 }
1514
1515 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl) {
1516 int err;
1517 snd_mixer_t *m;
1518 char *md;
1519 snd_pcm_info_t* info;
1520 snd_pcm_info_alloca(&info);
1521
1522 if ((err = snd_mixer_open(&m, 0)) < 0) {
1523 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1524 return NULL;
1525 }
1526
1527 /* Then, try by card index */
1528 md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1529 if (prepare_mixer(m, md, hctl) >= 0) {
1530
1531 if (ctl_device)
1532 *ctl_device = md;
1533 else
1534 pa_xfree(md);
1535
1536 return m;
1537 }
1538
1539 pa_xfree(md);
1540
1541 snd_mixer_close(m);
1542 return NULL;
1543 }
1544
1545 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl) {
1546 int err;
1547 snd_mixer_t *m;
1548 const char *dev;
1549 snd_pcm_info_t* info;
1550 snd_pcm_info_alloca(&info);
1551
1552 pa_assert(pcm);
1553
1554 if ((err = snd_mixer_open(&m, 0)) < 0) {
1555 pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1556 return NULL;
1557 }
1558
1559 /* First, try by name */
1560 if ((dev = snd_pcm_name(pcm)))
1561 if (prepare_mixer(m, dev, hctl) >= 0) {
1562 if (ctl_device)
1563 *ctl_device = pa_xstrdup(dev);
1564
1565 return m;
1566 }
1567
1568 /* Then, try by card index */
1569 if (snd_pcm_info(pcm, info) >= 0) {
1570 char *md;
1571 int card_idx;
1572
1573 if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1574
1575 md = pa_sprintf_malloc("hw:%i", card_idx);
1576
1577 if (!dev || !pa_streq(dev, md))
1578 if (prepare_mixer(m, md, hctl) >= 0) {
1579
1580 if (ctl_device)
1581 *ctl_device = md;
1582 else
1583 pa_xfree(md);
1584
1585 return m;
1586 }
1587
1588 pa_xfree(md);
1589 }
1590 }
1591
1592 snd_mixer_close(m);
1593 return NULL;
1594 }
1595
1596 int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
1597
1598 /* The ELD format is specific to HDA Intel sound cards and defined in the
1599 HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1600 int err;
1601 snd_hctl_elem_t *elem;
1602 snd_ctl_elem_info_t *info;
1603 snd_ctl_elem_value_t *value;
1604 uint8_t *elddata;
1605 unsigned int eldsize, mnl;
1606
1607 pa_assert(eld != NULL);
1608
1609 /* See if we can find the ELD control */
1610 elem = pa_alsa_find_eld_ctl(hctl, device);
1611 if (elem == NULL) {
1612 pa_log_debug("No ELD info control found (for device=%d)", device);
1613 return -1;
1614 }
1615
1616 /* Does it have any contents? */
1617 snd_ctl_elem_info_alloca(&info);
1618 snd_ctl_elem_value_alloca(&value);
1619 if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1620 (err = snd_hctl_elem_read(elem, value)) < 0) {
1621 pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1622 return -1;
1623 }
1624
1625 eldsize = snd_ctl_elem_info_get_count(info);
1626 elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1627 if (elddata == NULL || eldsize == 0) {
1628 pa_log_debug("ELD info empty (for device=%d)", device);
1629 return -1;
1630 }
1631 if (eldsize < 20 || eldsize > 256) {
1632 pa_log_debug("ELD info has wrong size (for device=%d)", device);
1633 return -1;
1634 }
1635
1636 /* Try to fetch monitor name */
1637 mnl = elddata[4] & 0x1f;
1638 if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
1639 pa_log_debug("No monitor name in ELD info (for device=%d)", device);
1640 mnl = 0;
1641 }
1642 memcpy(eld->monitor_name, &elddata[20], mnl);
1643 eld->monitor_name[mnl] = '\0';
1644 if (mnl)
1645 pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
1646
1647 return 0;
1648 }