Remove pa_bool_t and replace it with bool
[platform/upstream/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 <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 #ifdef __TIZEN__
436     // FIXME : Fix added for VT avsync issue + Reducing voip HW buff size
437 #define VOIP_WIDE_BAND 16000
438 #define VOIP_WB_AVAIL_MIN 160
439 #define VOIP_NB_AVAIL_MIN 80
440 #endif
441
442 #ifdef __TIZEN__
443 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event, int start_threshold,int sampling_rate) {
444 #else
445 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, bool period_event) {
446 #endif
447     snd_pcm_sw_params_t *swparams;
448     snd_pcm_uframes_t boundary;
449     int err;
450
451     pa_assert(pcm);
452
453 #ifdef __TIZEN__
454     if (start_threshold > 0) {
455         avail_min = start_threshold;
456     }
457
458     if (pa_alsa_pcm_is_voip(pcm)) {
459     // FIXME : Fix added for VT avsync issue + Reducing voip HW buff size
460         avail_min = (sampling_rate == VOIP_WIDE_BAND) ? VOIP_WB_AVAIL_MIN :VOIP_NB_AVAIL_MIN;
461     }
462 #endif
463     snd_pcm_sw_params_alloca(&swparams);
464
465     if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
466         pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
467         return err;
468     }
469
470     if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) {
471         pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
472         return err;
473     }
474
475     if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
476         pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
477         return err;
478     }
479
480     if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
481         pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
482         return err;
483     }
484
485 #ifdef __TIZEN__
486     if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
487         pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
488         return err;
489     }
490
491     if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (start_threshold > 0)? (snd_pcm_uframes_t)start_threshold : avail_min)) < 0) {
492         pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
493         return err;
494     }
495 #else
496     if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
497         pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
498         return err;
499     }
500
501     if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
502         pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
503         return err;
504     }
505 #endif
506
507     if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
508         pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
509         return err;
510     }
511
512     if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
513         pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
514         return err;
515     }
516
517     return 0;
518 }
519
520 snd_pcm_t *pa_alsa_open_by_device_id_auto(
521 #ifdef __TIZEN__
522         pa_core *c,
523 #endif
524         const char *dev_id,
525         char **dev,
526         pa_sample_spec *ss,
527         pa_channel_map* map,
528         int mode,
529         snd_pcm_uframes_t *period_size,
530         snd_pcm_uframes_t *buffer_size,
531         snd_pcm_uframes_t tsched_size,
532         bool *use_mmap,
533         bool *use_tsched,
534         pa_alsa_profile_set *ps,
535         pa_alsa_mapping **mapping) {
536
537     char *d;
538     snd_pcm_t *pcm_handle;
539     void *state;
540     pa_alsa_mapping *m;
541
542     pa_assert(dev_id);
543     pa_assert(dev);
544     pa_assert(ss);
545     pa_assert(map);
546     pa_assert(ps);
547
548     /* First we try to find a device string with a superset of the
549      * requested channel map. We iterate through our device table from
550      * top to bottom and take the first that matches. If we didn't
551      * find a working device that way, we iterate backwards, and check
552      * all devices that do not provide a superset of the requested
553      * channel map.*/
554
555     PA_HASHMAP_FOREACH(m, ps->mappings, state) {
556         if (!pa_channel_map_superset(&m->channel_map, map))
557             continue;
558
559         pa_log_debug("Checking for superset %s (%s)", m->name, m->device_strings[0]);
560
561         pcm_handle = pa_alsa_open_by_device_id_mapping(
562 #ifdef __TIZEN__
563                 c,
564 #endif
565                 dev_id,
566                 dev,
567                 ss,
568                 map,
569                 mode,
570                 period_size,
571                 buffer_size,
572                 tsched_size,
573                 use_mmap,
574                 use_tsched,
575                 m);
576
577         if (pcm_handle) {
578             if (mapping)
579                 *mapping = m;
580
581             return pcm_handle;
582         }
583     }
584
585     PA_HASHMAP_FOREACH_BACKWARDS(m, ps->mappings, state) {
586         if (pa_channel_map_superset(&m->channel_map, map))
587             continue;
588
589         pa_log_debug("Checking for subset %s (%s)", m->name, m->device_strings[0]);
590
591         pcm_handle = pa_alsa_open_by_device_id_mapping(
592 #ifdef __TIZEN__
593                 c,
594 #endif
595                 dev_id,
596                 dev,
597                 ss,
598                 map,
599                 mode,
600                 period_size,
601                 buffer_size,
602                 tsched_size,
603                 use_mmap,
604                 use_tsched,
605                 m);
606
607         if (pcm_handle) {
608             if (mapping)
609                 *mapping = m;
610
611             return pcm_handle;
612         }
613     }
614
615     /* OK, we didn't find any good device, so let's try the raw hw: stuff */
616     d = pa_sprintf_malloc("hw:%s", dev_id);
617     pa_log_debug("Trying %s as last resort...", d);
618     pcm_handle = pa_alsa_open_by_device_string(
619 #ifdef __TIZEN__
620             c,
621 #endif
622             d,
623             dev,
624             ss,
625             map,
626             mode,
627             period_size,
628             buffer_size,
629             tsched_size,
630             use_mmap,
631             use_tsched,
632             false);
633     pa_xfree(d);
634
635     if (pcm_handle && mapping)
636         *mapping = NULL;
637
638     return pcm_handle;
639 }
640
641 snd_pcm_t *pa_alsa_open_by_device_id_mapping(
642 #ifdef __TIZEN__
643         pa_core *c,
644 #endif
645         const char *dev_id,
646         char **dev,
647         pa_sample_spec *ss,
648         pa_channel_map* map,
649         int mode,
650         snd_pcm_uframes_t *period_size,
651         snd_pcm_uframes_t *buffer_size,
652         snd_pcm_uframes_t tsched_size,
653         bool *use_mmap,
654         bool *use_tsched,
655         pa_alsa_mapping *m) {
656
657     snd_pcm_t *pcm_handle;
658     pa_sample_spec try_ss;
659     pa_channel_map try_map;
660
661     pa_assert(dev_id);
662     pa_assert(dev);
663     pa_assert(ss);
664     pa_assert(map);
665     pa_assert(m);
666
667     try_ss.channels = m->channel_map.channels;
668     try_ss.rate = ss->rate;
669     try_ss.format = ss->format;
670     try_map = m->channel_map;
671
672     pcm_handle = pa_alsa_open_by_template(
673 #ifdef __TIZEN__
674             c,
675 #endif
676             m->device_strings,
677             dev_id,
678             dev,
679             &try_ss,
680             &try_map,
681             mode,
682             period_size,
683             buffer_size,
684             tsched_size,
685             use_mmap,
686             use_tsched,
687             pa_channel_map_valid(&m->channel_map) /* Query the channel count if we don't know what we want */);
688
689     if (!pcm_handle)
690         return NULL;
691
692     *ss = try_ss;
693     *map = try_map;
694     pa_assert(map->channels == ss->channels);
695
696     return pcm_handle;
697 }
698
699 snd_pcm_t *pa_alsa_open_by_device_string(
700 #ifdef __TIZEN__
701         pa_core *c,
702 #endif
703         const char *device,
704         char **dev,
705         pa_sample_spec *ss,
706         pa_channel_map* map,
707         int mode,
708         snd_pcm_uframes_t *period_size,
709         snd_pcm_uframes_t *buffer_size,
710         snd_pcm_uframes_t tsched_size,
711         bool *use_mmap,
712         bool *use_tsched,
713         bool require_exact_channel_number) {
714
715     int err;
716     char *d;
717     snd_pcm_t *pcm_handle;
718     bool reformat = false;
719
720     pa_assert(device);
721     pa_assert(ss);
722     pa_assert(map);
723
724     d = pa_xstrdup(device);
725
726     for (;;) {
727         pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
728
729         if ((err = snd_pcm_open(&pcm_handle, d, mode,
730                                 SND_PCM_NONBLOCK|
731                                 SND_PCM_NO_AUTO_RESAMPLE|
732                                 SND_PCM_NO_AUTO_CHANNELS|
733                                 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
734             pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
735             goto fail;
736         }
737
738         pa_log_debug("Managed to open %s", d);
739
740         if ((err = pa_alsa_set_hw_params(
741                      pcm_handle,
742                      ss,
743                      period_size,
744                      buffer_size,
745                      tsched_size,
746                      use_mmap,
747                      use_tsched,
748                      require_exact_channel_number)) < 0) {
749
750             if (!reformat) {
751                 reformat = true;
752                 snd_pcm_close(pcm_handle);
753                 continue;
754             }
755
756             /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
757             if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
758                 char *t;
759
760                 t = pa_sprintf_malloc("plug:%s", d);
761                 pa_xfree(d);
762                 d = t;
763
764                 reformat = false;
765                 snd_pcm_close(pcm_handle);
766                 continue;
767             }
768
769             pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
770             snd_pcm_close(pcm_handle);
771
772             goto fail;
773         }
774
775         if (dev)
776             *dev = d;
777         else
778             pa_xfree(d);
779
780         if (ss->channels != map->channels)
781             pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
782
783         return pcm_handle;
784     }
785
786 fail:
787     pa_xfree(d);
788
789     return NULL;
790 }
791
792 snd_pcm_t *pa_alsa_open_by_template(
793 #ifdef __TIZEN__
794         pa_core *c,
795 #endif
796         char **template,
797         const char *dev_id,
798         char **dev,
799         pa_sample_spec *ss,
800         pa_channel_map* map,
801         int mode,
802         snd_pcm_uframes_t *period_size,
803         snd_pcm_uframes_t *buffer_size,
804         snd_pcm_uframes_t tsched_size,
805         bool *use_mmap,
806         bool *use_tsched,
807         bool require_exact_channel_number) {
808
809     snd_pcm_t *pcm_handle;
810     char **i;
811
812     for (i = template; *i; i++) {
813         char *d;
814
815         d = pa_replace(*i, "%f", dev_id);
816
817         pcm_handle = pa_alsa_open_by_device_string(
818 #ifdef __TIZEN__
819                 c,
820 #endif
821                 d,
822                 dev,
823                 ss,
824                 map,
825                 mode,
826                 period_size,
827                 buffer_size,
828                 tsched_size,
829                 use_mmap,
830                 use_tsched,
831                 require_exact_channel_number);
832
833         pa_xfree(d);
834
835         if (pcm_handle)
836             return pcm_handle;
837     }
838
839     return NULL;
840 }
841
842 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
843     int err;
844     snd_output_t *out;
845
846     pa_assert(pcm);
847
848     pa_assert_se(snd_output_buffer_open(&out) == 0);
849
850     if ((err = snd_pcm_dump(pcm, out)) < 0)
851         pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
852     else {
853         char *s = NULL;
854         snd_output_buffer_string(out, &s);
855         pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
856     }
857
858     pa_assert_se(snd_output_close(out) == 0);
859 }
860
861 void pa_alsa_dump_status(snd_pcm_t *pcm) {
862     int err;
863     snd_output_t *out;
864     snd_pcm_status_t *status;
865     char *s = NULL;
866
867     pa_assert(pcm);
868
869     snd_pcm_status_alloca(&status);
870
871     if ((err = snd_output_buffer_open(&out)) < 0) {
872         pa_log_debug("snd_output_buffer_open() failed: %s", pa_cstrerror(err));
873         return;
874     }
875
876     if ((err = snd_pcm_status(pcm, status)) < 0) {
877         pa_log_debug("snd_pcm_status() failed: %s", pa_cstrerror(err));
878         goto finish;
879     }
880
881     if ((err = snd_pcm_status_dump(status, out)) < 0) {
882         pa_log_debug("snd_pcm_status_dump(): %s", pa_alsa_strerror(err));
883         goto finish;
884     }
885
886     snd_output_buffer_string(out, &s);
887     pa_log_debug("snd_pcm_status_dump():\n%s", pa_strnull(s));
888
889 finish:
890
891     snd_output_close(out);
892 }
893
894 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
895     va_list ap;
896     char *alsa_file;
897
898     alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
899
900     va_start(ap, fmt);
901
902     pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
903
904     va_end(ap);
905
906     pa_xfree(alsa_file);
907 }
908
909 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
910
911 void pa_alsa_refcnt_inc(void) {
912     /* This is not really thread safe, but we do our best */
913
914     if (pa_atomic_inc(&n_error_handler_installed) == 0)
915         snd_lib_error_set_handler(alsa_error_handler);
916 }
917
918 void pa_alsa_refcnt_dec(void) {
919     int r;
920
921     pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
922
923     if (r == 1) {
924         snd_lib_error_set_handler(NULL);
925         snd_config_update_free_global();
926     }
927 }
928
929 bool pa_alsa_init_description(pa_proplist *p) {
930     const char *d, *k;
931     pa_assert(p);
932
933     if (pa_device_init_description(p))
934         return true;
935
936     if (!(d = pa_proplist_gets(p, "alsa.card_name")))
937         d = pa_proplist_gets(p, "alsa.name");
938
939     if (!d)
940         return false;
941
942     k = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_DESCRIPTION);
943
944     if (d && k)
945         pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s %s", d, k);
946     else if (d)
947         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, d);
948
949     return false;
950 }
951
952 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
953     char *cn, *lcn, *dn;
954
955     pa_assert(p);
956     pa_assert(card >= 0);
957
958     pa_proplist_setf(p, "alsa.card", "%i", card);
959
960     if (snd_card_get_name(card, &cn) >= 0) {
961         pa_proplist_sets(p, "alsa.card_name", pa_strip(cn));
962         free(cn);
963     }
964
965     if (snd_card_get_longname(card, &lcn) >= 0) {
966         pa_proplist_sets(p, "alsa.long_card_name", pa_strip(lcn));
967         free(lcn);
968     }
969
970     if ((dn = pa_alsa_get_driver_name(card))) {
971         pa_proplist_sets(p, "alsa.driver_name", dn);
972         pa_xfree(dn);
973     }
974
975 #ifdef HAVE_UDEV
976     pa_udev_get_info(card, p);
977 #endif
978 }
979
980 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
981
982     static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
983         [SND_PCM_CLASS_GENERIC] = "generic",
984         [SND_PCM_CLASS_MULTI] = "multi",
985         [SND_PCM_CLASS_MODEM] = "modem",
986         [SND_PCM_CLASS_DIGITIZER] = "digitizer"
987     };
988     static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
989         [SND_PCM_CLASS_GENERIC] = "sound",
990         [SND_PCM_CLASS_MULTI] = NULL,
991         [SND_PCM_CLASS_MODEM] = "modem",
992         [SND_PCM_CLASS_DIGITIZER] = NULL
993     };
994     static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
995         [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
996         [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
997     };
998
999     snd_pcm_class_t class;
1000     snd_pcm_subclass_t subclass;
1001     const char *n, *id, *sdn;
1002     int card;
1003
1004     pa_assert(p);
1005     pa_assert(pcm_info);
1006
1007     pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
1008
1009     if ((class = snd_pcm_info_get_class(pcm_info)) <= SND_PCM_CLASS_LAST) {
1010         if (class_table[class])
1011             pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
1012         if (alsa_class_table[class])
1013             pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
1014     }
1015
1016     if ((subclass = snd_pcm_info_get_subclass(pcm_info)) <= SND_PCM_SUBCLASS_LAST)
1017         if (alsa_subclass_table[subclass])
1018             pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
1019
1020     if ((n = snd_pcm_info_get_name(pcm_info))) {
1021         char *t = pa_xstrdup(n);
1022         pa_proplist_sets(p, "alsa.name", pa_strip(t));
1023         pa_xfree(t);
1024     }
1025
1026     if ((id = snd_pcm_info_get_id(pcm_info)))
1027         pa_proplist_sets(p, "alsa.id", id);
1028
1029     pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
1030     if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
1031         pa_proplist_sets(p, "alsa.subdevice_name", sdn);
1032
1033     pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
1034
1035     if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
1036         pa_alsa_init_proplist_card(c, p, card);
1037 }
1038
1039 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) {
1040     snd_pcm_hw_params_t *hwparams;
1041     snd_pcm_info_t *info;
1042     int bits, err;
1043
1044     snd_pcm_hw_params_alloca(&hwparams);
1045     snd_pcm_info_alloca(&info);
1046
1047     if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
1048         pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
1049     else {
1050
1051         if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
1052             pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
1053     }
1054
1055     if ((err = snd_pcm_info(pcm, info)) < 0)
1056         pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1057     else
1058         pa_alsa_init_proplist_pcm_info(c, p, info);
1059 }
1060
1061 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1062     int err;
1063     snd_ctl_t *ctl;
1064     snd_ctl_card_info_t *info;
1065     const char *t;
1066
1067     pa_assert(p);
1068
1069     snd_ctl_card_info_alloca(&info);
1070
1071     if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1072         pa_log_warn("Error opening low-level control device '%s': %s", name, snd_strerror(err));
1073         return;
1074     }
1075
1076     if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1077         pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1078         snd_ctl_close(ctl);
1079         return;
1080     }
1081
1082     if ((t = snd_ctl_card_info_get_mixername(info)) && *t)
1083         pa_proplist_sets(p, "alsa.mixer_name", t);
1084
1085     if ((t = snd_ctl_card_info_get_components(info)) && *t)
1086         pa_proplist_sets(p, "alsa.components", t);
1087
1088     snd_ctl_close(ctl);
1089 }
1090
1091 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1092     snd_pcm_state_t state;
1093     int err;
1094
1095     pa_assert(pcm);
1096
1097     if (revents & POLLERR)
1098         pa_log_debug("Got POLLERR from ALSA");
1099     if (revents & POLLNVAL)
1100         pa_log_warn("Got POLLNVAL from ALSA");
1101     if (revents & POLLHUP)
1102         pa_log_warn("Got POLLHUP from ALSA");
1103     if (revents & POLLPRI)
1104         pa_log_warn("Got POLLPRI from ALSA");
1105     if (revents & POLLIN)
1106         pa_log_debug("Got POLLIN from ALSA");
1107     if (revents & POLLOUT)
1108         pa_log_debug("Got POLLOUT from ALSA");
1109
1110     state = snd_pcm_state(pcm);
1111     pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1112
1113     /* Try to recover from this error */
1114
1115     switch (state) {
1116
1117         case SND_PCM_STATE_XRUN:
1118             if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1119                 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1120                 return -1;
1121             }
1122             break;
1123
1124         case SND_PCM_STATE_SUSPENDED:
1125             if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1126                 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1127                 return -1;
1128             }
1129             break;
1130
1131         default:
1132
1133             snd_pcm_drop(pcm);
1134
1135             if ((err = snd_pcm_prepare(pcm)) < 0) {
1136                 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1137                 return -1;
1138             }
1139             break;
1140     }
1141
1142     return 0;
1143 }
1144
1145 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1146     int n, err;
1147     struct pollfd *pollfd;
1148     pa_rtpoll_item *item;
1149
1150     pa_assert(pcm);
1151
1152     if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1153         pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1154         return NULL;
1155     }
1156
1157     item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1158     pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1159
1160     if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1161         pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1162         pa_rtpoll_item_free(item);
1163         return NULL;
1164     }
1165
1166     return item;
1167 }
1168
1169 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1170     snd_pcm_sframes_t n;
1171     size_t k;
1172
1173     pa_assert(pcm);
1174     pa_assert(hwbuf_size > 0);
1175     pa_assert(ss);
1176
1177     /* Some ALSA driver expose weird bugs, let's inform the user about
1178      * what is going on */
1179
1180     n = snd_pcm_avail(pcm);
1181
1182     if (n <= 0)
1183         return n;
1184
1185     k = (size_t) n * pa_frame_size(ss);
1186
1187     if (PA_UNLIKELY(k >= hwbuf_size * 5 ||
1188                     k >= pa_bytes_per_second(ss)*10)) {
1189
1190         PA_ONCE_BEGIN {
1191             char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1192             pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1193                      "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1194                    (unsigned long) k,
1195                    (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1196                    pa_strnull(dn));
1197             pa_xfree(dn);
1198             pa_alsa_dump(PA_LOG_ERROR, pcm);
1199         } PA_ONCE_END;
1200
1201         /* Mhmm, let's try not to fail completely */
1202         n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1203     }
1204
1205     return n;
1206 }
1207
1208 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,
1209                        bool capture) {
1210     ssize_t k;
1211     size_t abs_k;
1212     int err;
1213     snd_pcm_sframes_t avail = 0;
1214
1215     pa_assert(pcm);
1216     pa_assert(delay);
1217     pa_assert(hwbuf_size > 0);
1218     pa_assert(ss);
1219
1220     /* Some ALSA driver expose weird bugs, let's inform the user about
1221      * what is going on. We're going to get both the avail and delay values so
1222      * that we can compare and check them for capture.
1223      * This is done with snd_pcm_status() which provides
1224      * avail, delay and timestamp values in a single kernel call to improve
1225      * timer-based scheduling */
1226
1227     if ((err = snd_pcm_status(pcm, status)) < 0)
1228         return err;
1229
1230     avail = snd_pcm_status_get_avail(status);
1231     *delay = snd_pcm_status_get_delay(status);
1232
1233     k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1234
1235     abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1236
1237     if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1238                     abs_k >= pa_bytes_per_second(ss)*10)) {
1239
1240         PA_ONCE_BEGIN {
1241             char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1242             pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1243                      "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1244                    (signed long) k,
1245                    k < 0 ? "-" : "",
1246                    (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1247                    pa_strnull(dn));
1248             pa_xfree(dn);
1249             pa_alsa_dump(PA_LOG_ERROR, pcm);
1250         } PA_ONCE_END;
1251
1252         /* Mhmm, let's try not to fail completely */
1253         if (k < 0)
1254             *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1255         else
1256             *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1257     }
1258
1259     if (capture) {
1260         abs_k = (size_t) avail * pa_frame_size(ss);
1261
1262         if (PA_UNLIKELY(abs_k >= hwbuf_size * 5 ||
1263                         abs_k >= pa_bytes_per_second(ss)*10)) {
1264
1265             PA_ONCE_BEGIN {
1266                 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1267                 pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1268                          "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1269                        (unsigned long) k,
1270                        (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1271                        pa_strnull(dn));
1272                 pa_xfree(dn);
1273                 pa_alsa_dump(PA_LOG_ERROR, pcm);
1274             } PA_ONCE_END;
1275
1276             /* Mhmm, let's try not to fail completely */
1277             avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1278         }
1279
1280         if (PA_UNLIKELY(*delay < avail)) {
1281             PA_ONCE_BEGIN {
1282                 char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1283                 pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
1284                          "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1285                        (unsigned long) *delay,
1286                        (unsigned long) avail,
1287                        pa_strnull(dn));
1288                 pa_xfree(dn);
1289                 pa_alsa_dump(PA_LOG_ERROR, pcm);
1290             } PA_ONCE_END;
1291
1292             /* try to fixup */
1293             *delay = avail;
1294         }
1295     }
1296
1297     return 0;
1298 }
1299
1300 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) {
1301     int r;
1302     snd_pcm_uframes_t before;
1303     size_t k;
1304
1305     pa_assert(pcm);
1306     pa_assert(areas);
1307     pa_assert(offset);
1308     pa_assert(frames);
1309     pa_assert(hwbuf_size > 0);
1310     pa_assert(ss);
1311
1312     before = *frames;
1313
1314     r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1315
1316     if (r < 0)
1317         return r;
1318
1319     k = (size_t) *frames * pa_frame_size(ss);
1320
1321     if (PA_UNLIKELY(*frames > before ||
1322                     k >= hwbuf_size * 3 ||
1323                     k >= pa_bytes_per_second(ss)*10))
1324         PA_ONCE_BEGIN {
1325             char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1326             pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1327                      "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1328                    (unsigned long) k,
1329                    (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1330                    pa_strnull(dn));
1331             pa_xfree(dn);
1332             pa_alsa_dump(PA_LOG_ERROR, pcm);
1333         } PA_ONCE_END;
1334
1335     return r;
1336 }
1337
1338 char *pa_alsa_get_driver_name(int card) {
1339     char *t, *m, *n;
1340
1341     pa_assert(card >= 0);
1342
1343     t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1344     m = pa_readlink(t);
1345     pa_xfree(t);
1346
1347     if (!m)
1348         return NULL;
1349
1350     n = pa_xstrdup(pa_path_get_filename(m));
1351     pa_xfree(m);
1352
1353     return n;
1354 }
1355
1356 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1357     int card;
1358     snd_pcm_info_t* info;
1359     snd_pcm_info_alloca(&info);
1360
1361     pa_assert(pcm);
1362
1363     if (snd_pcm_info(pcm, info) < 0)
1364         return NULL;
1365
1366     if ((card = snd_pcm_info_get_card(info)) < 0)
1367         return NULL;
1368
1369     return pa_alsa_get_driver_name(card);
1370 }
1371
1372 char *pa_alsa_get_reserve_name(const char *device) {
1373     const char *t;
1374     int i;
1375
1376     pa_assert(device);
1377
1378     if ((t = strchr(device, ':')))
1379         device = t+1;
1380
1381     if ((i = snd_card_get_index(device)) < 0) {
1382         int32_t k;
1383
1384         if (pa_atoi(device, &k) < 0)
1385             return NULL;
1386
1387         i = (int) k;
1388     }
1389
1390     return pa_sprintf_malloc("Audio%i", i);
1391 }
1392
1393 unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate) {
1394     static unsigned int all_rates[] = { 8000, 11025, 12000,
1395                                         16000, 22050, 24000,
1396                                         32000, 44100, 48000,
1397                                         64000, 88200, 96000,
1398                                         128000, 176400, 192000,
1399                                         384000 };
1400     bool supported[PA_ELEMENTSOF(all_rates)] = { false, };
1401     snd_pcm_hw_params_t *hwparams;
1402     unsigned int i, j, n, *rates = NULL;
1403     int ret;
1404
1405     snd_pcm_hw_params_alloca(&hwparams);
1406
1407     if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
1408         pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
1409         return NULL;
1410     }
1411
1412     for (i = 0, n = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1413         if (snd_pcm_hw_params_test_rate(pcm, hwparams, all_rates[i], 0) == 0) {
1414             supported[i] = true;
1415             n++;
1416         }
1417     }
1418
1419     if (n > 0) {
1420         rates = pa_xnew(unsigned int, n + 1);
1421
1422         for (i = 0, j = 0; i < PA_ELEMENTSOF(all_rates); i++) {
1423             if (supported[i])
1424                 rates[j++] = all_rates[i];
1425         }
1426
1427         rates[j] = 0;
1428     } else {
1429         rates = pa_xnew(unsigned int, 2);
1430
1431         rates[0] = fallback_rate;
1432         if ((ret = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rates[0], NULL)) < 0) {
1433             pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
1434             pa_xfree(rates);
1435             return NULL;
1436         }
1437
1438         rates[1] = 0;
1439     }
1440
1441     return rates;
1442 }
1443
1444 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1445     snd_pcm_info_t* info;
1446     snd_pcm_info_alloca(&info);
1447
1448     pa_assert(pcm);
1449
1450     if (snd_pcm_info(pcm, info) < 0)
1451         return false;
1452
1453     return snd_pcm_info_get_card(info) >= 0;
1454 }
1455
1456 bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1457     snd_pcm_info_t* info;
1458     snd_pcm_info_alloca(&info);
1459
1460     pa_assert(pcm);
1461
1462     if (snd_pcm_info(pcm, info) < 0)
1463         return false;
1464
1465     return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1466 }
1467
1468 #ifdef __TIZEN__
1469 bool pa_alsa_pcm_is_voip(snd_pcm_t *pcm) {
1470     const char *id = NULL;
1471     snd_pcm_info_t* info;
1472     snd_pcm_info_alloca(&info);
1473
1474     pa_assert(pcm);
1475
1476     if (snd_pcm_info(pcm, info) < 0)
1477         return false;
1478
1479     if (!(id = snd_pcm_info_get_id(info)))
1480         return false;
1481
1482     if(!strncmp(id, "VoIP",4))
1483         return true;
1484
1485     return false;
1486 }
1487 #endif
1488
1489 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1490
1491 const char* pa_alsa_strerror(int errnum) {
1492     const char *original = NULL;
1493     char *translated, *t;
1494     char errbuf[128];
1495
1496     if ((t = PA_STATIC_TLS_GET(cstrerror)))
1497         pa_xfree(t);
1498
1499     original = snd_strerror(errnum);
1500
1501     if (!original) {
1502         pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1503         original = errbuf;
1504     }
1505
1506     if (!(translated = pa_locale_to_utf8(original))) {
1507         pa_log_warn("Unable to convert error string to locale, filtering.");
1508         translated = pa_utf8_filter(original);
1509     }
1510
1511     PA_STATIC_TLS_SET(cstrerror, translated);
1512
1513     return translated;
1514 }
1515
1516 bool pa_alsa_may_tsched(bool want) {
1517
1518     if (!want)
1519         return false;
1520
1521     if (!pa_rtclock_hrtimer()) {
1522         /* We cannot depend on being woken up in time when the timers
1523         are inaccurate, so let's fallback to classic IO based playback
1524         then. */
1525         pa_log_notice("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
1526         return false; }
1527
1528     if (pa_running_in_vm()) {
1529         /* We cannot depend on being woken up when we ask for in a VM,
1530          * so let's fallback to classic IO based playback then. */
1531         pa_log_notice("Disabling timer-based scheduling because running inside a VM.");
1532         return false;
1533     }
1534
1535     return true;
1536 }
1537
1538 snd_hctl_elem_t* pa_alsa_find_jack(snd_hctl_t *hctl, const char* jack_name) {
1539     snd_ctl_elem_id_t *id;
1540
1541     snd_ctl_elem_id_alloca(&id);
1542     snd_ctl_elem_id_clear(id);
1543     snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
1544     snd_ctl_elem_id_set_name(id, jack_name);
1545
1546     return snd_hctl_find_elem(hctl, id);
1547 }
1548
1549 snd_hctl_elem_t* pa_alsa_find_eld_ctl(snd_hctl_t *hctl, int device) {
1550     snd_ctl_elem_id_t *id;
1551
1552     /* See if we can find the ELD control */
1553     snd_ctl_elem_id_alloca(&id);
1554     snd_ctl_elem_id_clear(id);
1555     snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1556     snd_ctl_elem_id_set_name(id, "ELD");
1557     snd_ctl_elem_id_set_device(id, device);
1558
1559     return snd_hctl_find_elem(hctl, id);
1560 }
1561
1562 static int prepare_mixer(snd_mixer_t *mixer, const char *dev, snd_hctl_t **hctl) {
1563     int err;
1564
1565     pa_assert(mixer);
1566     pa_assert(dev);
1567
1568     if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1569         pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1570         return -1;
1571     }
1572
1573     /* Note: The hctl handle returned should not be freed.
1574        It is closed/freed by alsa-lib on snd_mixer_close/free */
1575     if (hctl && (err = snd_mixer_get_hctl(mixer, dev, hctl)) < 0) {
1576         pa_log_info("Unable to get hctl of mixer %s: %s", dev, pa_alsa_strerror(err));
1577         return -1;
1578     }
1579
1580     if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1581         pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1582         return -1;
1583     }
1584
1585     if ((err = snd_mixer_load(mixer)) < 0) {
1586         pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1587         return -1;
1588     }
1589
1590     pa_log_info("Successfully attached to mixer '%s'", dev);
1591     return 0;
1592 }
1593
1594 snd_mixer_t *pa_alsa_open_mixer(int alsa_card_index, char **ctl_device, snd_hctl_t **hctl) {
1595     int err;
1596     snd_mixer_t *m;
1597     char *md;
1598     snd_pcm_info_t* info;
1599     snd_pcm_info_alloca(&info);
1600
1601     if ((err = snd_mixer_open(&m, 0)) < 0) {
1602         pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1603         return NULL;
1604     }
1605
1606     /* Then, try by card index */
1607     md = pa_sprintf_malloc("hw:%i", alsa_card_index);
1608     if (prepare_mixer(m, md, hctl) >= 0) {
1609
1610         if (ctl_device)
1611             *ctl_device = md;
1612         else
1613             pa_xfree(md);
1614
1615         return m;
1616     }
1617
1618     pa_xfree(md);
1619
1620     snd_mixer_close(m);
1621     return NULL;
1622 }
1623
1624 snd_mixer_t *pa_alsa_open_mixer_for_pcm(snd_pcm_t *pcm, char **ctl_device, snd_hctl_t **hctl) {
1625     int err;
1626     snd_mixer_t *m;
1627     const char *dev;
1628     snd_pcm_info_t* info;
1629     snd_pcm_info_alloca(&info);
1630
1631     pa_assert(pcm);
1632
1633     if ((err = snd_mixer_open(&m, 0)) < 0) {
1634         pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1635         return NULL;
1636     }
1637
1638     /* First, try by name */
1639     if ((dev = snd_pcm_name(pcm)))
1640         if (prepare_mixer(m, dev, hctl) >= 0) {
1641             if (ctl_device)
1642                 *ctl_device = pa_xstrdup(dev);
1643
1644             return m;
1645         }
1646
1647     /* Then, try by card index */
1648     if (snd_pcm_info(pcm, info) >= 0) {
1649         char *md;
1650         int card_idx;
1651
1652         if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1653
1654             md = pa_sprintf_malloc("hw:%i", card_idx);
1655
1656             if (!dev || !pa_streq(dev, md))
1657                 if (prepare_mixer(m, md, hctl) >= 0) {
1658
1659                     if (ctl_device)
1660                         *ctl_device = md;
1661                     else
1662                         pa_xfree(md);
1663
1664                     return m;
1665                 }
1666
1667             pa_xfree(md);
1668         }
1669     }
1670
1671     snd_mixer_close(m);
1672     return NULL;
1673 }
1674
1675 int pa_alsa_get_hdmi_eld(snd_hctl_t *hctl, int device, pa_hdmi_eld *eld) {
1676
1677     /* The ELD format is specific to HDA Intel sound cards and defined in the
1678        HDA specification: http://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html */
1679     int err;
1680     snd_hctl_elem_t *elem;
1681     snd_ctl_elem_info_t *info;
1682     snd_ctl_elem_value_t *value;
1683     uint8_t *elddata;
1684     unsigned int eldsize, mnl;
1685
1686     pa_assert(eld != NULL);
1687
1688     /* See if we can find the ELD control */
1689     elem = pa_alsa_find_eld_ctl(hctl, device);
1690     if (elem == NULL) {
1691         pa_log_debug("No ELD info control found (for device=%d)", device);
1692         return -1;
1693     }
1694
1695     /* Does it have any contents? */
1696     snd_ctl_elem_info_alloca(&info);
1697     snd_ctl_elem_value_alloca(&value);
1698     if ((err = snd_hctl_elem_info(elem, info)) < 0 ||
1699        (err = snd_hctl_elem_read(elem, value)) < 0) {
1700         pa_log_warn("Accessing ELD control failed with error %s", snd_strerror(err));
1701         return -1;
1702     }
1703
1704     eldsize = snd_ctl_elem_info_get_count(info);
1705     elddata = (unsigned char *) snd_ctl_elem_value_get_bytes(value);
1706     if (elddata == NULL || eldsize == 0) {
1707         pa_log_debug("ELD info empty (for device=%d)", device);
1708         return -1;
1709     }
1710     if (eldsize < 20 || eldsize > 256) {
1711         pa_log_debug("ELD info has wrong size (for device=%d)", device);
1712         return -1;
1713     }
1714
1715     /* Try to fetch monitor name */
1716     mnl = elddata[4] & 0x1f;
1717     if (mnl == 0 || mnl > 16 || 20 + mnl > eldsize) {
1718         pa_log_debug("No monitor name in ELD info (for device=%d)", device);
1719         mnl = 0;
1720     }
1721     memcpy(eld->monitor_name, &elddata[20], mnl);
1722     eld->monitor_name[mnl] = '\0';
1723     if (mnl)
1724         pa_log_debug("Monitor name in ELD info is '%s' (for device=%d)", eld->monitor_name, device);
1725
1726     return 0;
1727 }
1728
1729 #ifdef __TIZEN__
1730 int pa_alsa_set_mixer_control(const char *ctl_name, int val)
1731 {
1732     snd_ctl_t *handle;
1733     snd_ctl_elem_value_t *control;
1734     snd_ctl_elem_id_t *id;
1735     snd_ctl_elem_info_t *info;
1736     snd_ctl_elem_type_t type;
1737
1738     char *card_name = NULL;
1739     int ret = 0, count = 0, i = 0;
1740
1741     snd_card_get_name(0, &card_name);
1742     if(!card_name)
1743         card_name = strdup("default");
1744
1745     ret = snd_ctl_open(&handle, card_name, 0);
1746     if (ret < 0) {
1747         pa_log_error("snd_ctl_open error, card: %s: %s", card_name, snd_strerror(ret));
1748         if (card_name != NULL) {
1749             free(card_name);
1750             card_name = NULL;
1751         }
1752         return -1;
1753     }
1754     if (card_name != NULL) {
1755         free(card_name);
1756         card_name = NULL;
1757     }
1758     // Get Element Info
1759
1760     snd_ctl_elem_id_alloca(&id);
1761     snd_ctl_elem_info_alloca(&info);
1762     snd_ctl_elem_value_alloca(&control);
1763
1764     snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
1765     snd_ctl_elem_id_set_name(id, ctl_name);
1766
1767     snd_ctl_elem_info_set_id(info, id);
1768     if(snd_ctl_elem_info(handle, info) < 0 ) {
1769         pa_log_error("Cannot find control element: %s", ctl_name);
1770         goto close;
1771     }
1772     snd_ctl_elem_info_get_id(info, id);
1773
1774     type = snd_ctl_elem_info_get_type(info);
1775     count = snd_ctl_elem_info_get_count(info);
1776
1777     snd_ctl_elem_value_set_id(control, id);
1778
1779     snd_ctl_elem_read(handle, control);
1780
1781     pa_log_debug("type(%d), count(%d): ", type, count);
1782
1783     switch (type) {
1784     case SND_CTL_ELEM_TYPE_BOOLEAN:
1785         for (i = 0; i < count; i++)
1786             snd_ctl_elem_value_set_boolean(control, i, val);
1787         break;
1788     case SND_CTL_ELEM_TYPE_INTEGER:
1789         for (i = 0; i < count; i++)
1790             snd_ctl_elem_value_set_integer(control, i,val);
1791         break;
1792     case SND_CTL_ELEM_TYPE_ENUMERATED:
1793         for (i = 0; i < count; i++)
1794             snd_ctl_elem_value_set_enumerated(control, i,val);
1795         break;
1796
1797     default:
1798         pa_log_warn("unsupported control element type");
1799         goto close;
1800     }
1801
1802     snd_ctl_elem_write(handle, control);
1803
1804     snd_ctl_close(handle);
1805
1806     return 0;
1807
1808 close:
1809     pa_log_error("Error");
1810     snd_ctl_close(handle);
1811     return -1;
1812 }
1813 #endif