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