Sending translation for Portuguese
[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 <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
46 #include "alsa-util.h"
47
48 #ifdef HAVE_HAL
49 #include "hal-util.h"
50 #endif
51
52 #ifdef HAVE_UDEV
53 #include "udev-util.h"
54 #endif
55
56 struct pa_alsa_fdlist {
57     unsigned num_fds;
58     struct pollfd *fds;
59     /* This is a temporary buffer used to avoid lots of mallocs */
60     struct pollfd *work_fds;
61
62     snd_mixer_t *mixer;
63
64     pa_mainloop_api *m;
65     pa_defer_event *defer;
66     pa_io_event **ios;
67
68     pa_bool_t polled;
69
70     void (*cb)(void *userdata);
71     void *userdata;
72 };
73
74 static void io_cb(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
75
76     struct pa_alsa_fdlist *fdl = userdata;
77     int err;
78     unsigned i;
79     unsigned short revents;
80
81     pa_assert(a);
82     pa_assert(fdl);
83     pa_assert(fdl->mixer);
84     pa_assert(fdl->fds);
85     pa_assert(fdl->work_fds);
86
87     if (fdl->polled)
88         return;
89
90     fdl->polled = TRUE;
91
92     memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
93
94     for (i = 0; i < fdl->num_fds; i++) {
95         if (e == fdl->ios[i]) {
96             if (events & PA_IO_EVENT_INPUT)
97                 fdl->work_fds[i].revents |= POLLIN;
98             if (events & PA_IO_EVENT_OUTPUT)
99                 fdl->work_fds[i].revents |= POLLOUT;
100             if (events & PA_IO_EVENT_ERROR)
101                 fdl->work_fds[i].revents |= POLLERR;
102             if (events & PA_IO_EVENT_HANGUP)
103                 fdl->work_fds[i].revents |= POLLHUP;
104             break;
105         }
106     }
107
108     pa_assert(i != fdl->num_fds);
109
110     if ((err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents)) < 0) {
111         pa_log_error("Unable to get poll revent: %s", pa_alsa_strerror(err));
112         return;
113     }
114
115     a->defer_enable(fdl->defer, 1);
116
117     if (revents)
118         snd_mixer_handle_events(fdl->mixer);
119 }
120
121 static void defer_cb(pa_mainloop_api*a, pa_defer_event* e, void *userdata) {
122     struct pa_alsa_fdlist *fdl = userdata;
123     unsigned num_fds, i;
124     int err, n;
125     struct pollfd *temp;
126
127     pa_assert(a);
128     pa_assert(fdl);
129     pa_assert(fdl->mixer);
130
131     a->defer_enable(fdl->defer, 0);
132
133     if ((n = snd_mixer_poll_descriptors_count(fdl->mixer)) < 0) {
134         pa_log("snd_mixer_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
135         return;
136     }
137     num_fds = (unsigned) n;
138
139     if (num_fds != fdl->num_fds) {
140         if (fdl->fds)
141             pa_xfree(fdl->fds);
142         if (fdl->work_fds)
143             pa_xfree(fdl->work_fds);
144         fdl->fds = pa_xnew0(struct pollfd, num_fds);
145         fdl->work_fds = pa_xnew(struct pollfd, num_fds);
146     }
147
148     memset(fdl->work_fds, 0, sizeof(struct pollfd) * num_fds);
149
150     if ((err = snd_mixer_poll_descriptors(fdl->mixer, fdl->work_fds, num_fds)) < 0) {
151         pa_log_error("Unable to get poll descriptors: %s", pa_alsa_strerror(err));
152         return;
153     }
154
155     fdl->polled = FALSE;
156
157     if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0)
158         return;
159
160     if (fdl->ios) {
161         for (i = 0; i < fdl->num_fds; i++)
162             a->io_free(fdl->ios[i]);
163
164         if (num_fds != fdl->num_fds) {
165             pa_xfree(fdl->ios);
166             fdl->ios = NULL;
167         }
168     }
169
170     if (!fdl->ios)
171         fdl->ios = pa_xnew(pa_io_event*, num_fds);
172
173     /* Swap pointers */
174     temp = fdl->work_fds;
175     fdl->work_fds = fdl->fds;
176     fdl->fds = temp;
177
178     fdl->num_fds = num_fds;
179
180     for (i = 0;i < num_fds;i++)
181         fdl->ios[i] = a->io_new(a, fdl->fds[i].fd,
182             ((fdl->fds[i].events & POLLIN) ? PA_IO_EVENT_INPUT : 0) |
183             ((fdl->fds[i].events & POLLOUT) ? PA_IO_EVENT_OUTPUT : 0),
184             io_cb, fdl);
185 }
186
187 struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) {
188     struct pa_alsa_fdlist *fdl;
189
190     fdl = pa_xnew0(struct pa_alsa_fdlist, 1);
191
192     return fdl;
193 }
194
195 void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl) {
196     pa_assert(fdl);
197
198     if (fdl->defer) {
199         pa_assert(fdl->m);
200         fdl->m->defer_free(fdl->defer);
201     }
202
203     if (fdl->ios) {
204         unsigned i;
205         pa_assert(fdl->m);
206         for (i = 0; i < fdl->num_fds; i++)
207             fdl->m->io_free(fdl->ios[i]);
208         pa_xfree(fdl->ios);
209     }
210
211     if (fdl->fds)
212         pa_xfree(fdl->fds);
213     if (fdl->work_fds)
214         pa_xfree(fdl->work_fds);
215
216     pa_xfree(fdl);
217 }
218
219 int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m) {
220     pa_assert(fdl);
221     pa_assert(mixer_handle);
222     pa_assert(m);
223     pa_assert(!fdl->m);
224
225     fdl->mixer = mixer_handle;
226     fdl->m = m;
227     fdl->defer = m->defer_new(m, defer_cb, fdl);
228
229     return 0;
230 }
231
232 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
233
234     static const snd_pcm_format_t format_trans[] = {
235         [PA_SAMPLE_U8] = SND_PCM_FORMAT_U8,
236         [PA_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW,
237         [PA_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW,
238         [PA_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE,
239         [PA_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE,
240         [PA_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE,
241         [PA_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE,
242         [PA_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE,
243         [PA_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE,
244         [PA_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE,
245         [PA_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE,
246         [PA_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE,
247         [PA_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE,
248     };
249
250     static const pa_sample_format_t try_order[] = {
251         PA_SAMPLE_FLOAT32NE,
252         PA_SAMPLE_FLOAT32RE,
253         PA_SAMPLE_S32NE,
254         PA_SAMPLE_S32RE,
255         PA_SAMPLE_S24_32NE,
256         PA_SAMPLE_S24_32RE,
257         PA_SAMPLE_S24NE,
258         PA_SAMPLE_S24RE,
259         PA_SAMPLE_S16NE,
260         PA_SAMPLE_S16RE,
261         PA_SAMPLE_ALAW,
262         PA_SAMPLE_ULAW,
263         PA_SAMPLE_U8,
264         PA_SAMPLE_INVALID
265     };
266
267     int i, ret;
268
269     pa_assert(pcm_handle);
270     pa_assert(f);
271
272     if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
273         return ret;
274
275     pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
276                  snd_pcm_format_description(format_trans[*f]),
277                  pa_alsa_strerror(ret));
278
279
280     if (*f == PA_SAMPLE_FLOAT32BE)
281         *f = PA_SAMPLE_FLOAT32LE;
282     else if (*f == PA_SAMPLE_FLOAT32LE)
283         *f = PA_SAMPLE_FLOAT32BE;
284     else if (*f == PA_SAMPLE_S24BE)
285         *f = PA_SAMPLE_S24LE;
286     else if (*f == PA_SAMPLE_S24LE)
287         *f = PA_SAMPLE_S24BE;
288     else if (*f == PA_SAMPLE_S24_32BE)
289         *f = PA_SAMPLE_S24_32LE;
290     else if (*f == PA_SAMPLE_S24_32LE)
291         *f = PA_SAMPLE_S24_32BE;
292     else if (*f == PA_SAMPLE_S16BE)
293         *f = PA_SAMPLE_S16LE;
294     else if (*f == PA_SAMPLE_S16LE)
295         *f = PA_SAMPLE_S16BE;
296     else if (*f == PA_SAMPLE_S32BE)
297         *f = PA_SAMPLE_S32LE;
298     else if (*f == PA_SAMPLE_S32LE)
299         *f = PA_SAMPLE_S32BE;
300     else
301         goto try_auto;
302
303     if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
304         return ret;
305
306     pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
307                  snd_pcm_format_description(format_trans[*f]),
308                  pa_alsa_strerror(ret));
309
310 try_auto:
311
312     for (i = 0; try_order[i] != PA_SAMPLE_INVALID; i++) {
313         *f = try_order[i];
314
315         if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
316             return ret;
317
318         pa_log_debug("snd_pcm_hw_params_set_format(%s) failed: %s",
319                      snd_pcm_format_description(format_trans[*f]),
320                      pa_alsa_strerror(ret));
321     }
322
323     return -1;
324 }
325
326 /* Set the hardware parameters of the given ALSA device. Returns the
327  * selected fragment settings in *period and *period_size */
328 int pa_alsa_set_hw_params(
329         snd_pcm_t *pcm_handle,
330         pa_sample_spec *ss,
331         uint32_t *periods,
332         snd_pcm_uframes_t *period_size,
333         snd_pcm_uframes_t tsched_size,
334         pa_bool_t *use_mmap,
335         pa_bool_t *use_tsched,
336         pa_bool_t require_exact_channel_number) {
337
338     int ret = -1;
339     snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
340     unsigned int _periods = periods ? *periods : 0;
341     unsigned int r = ss->rate;
342     unsigned int c = ss->channels;
343     pa_sample_format_t f = ss->format;
344     snd_pcm_hw_params_t *hwparams;
345     pa_bool_t _use_mmap = use_mmap && *use_mmap;
346     pa_bool_t _use_tsched = use_tsched && *use_tsched;
347     int dir;
348
349     pa_assert(pcm_handle);
350     pa_assert(ss);
351
352     snd_pcm_hw_params_alloca(&hwparams);
353
354     if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
355         pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
356         goto finish;
357     }
358
359     if ((ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) {
360         pa_log_debug("snd_pcm_hw_params_set_rate_resample() failed: %s", pa_alsa_strerror(ret));
361         goto finish;
362     }
363
364     if (_use_mmap) {
365
366         if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
367
368             /* mmap() didn't work, fall back to interleaved */
369
370             if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
371                 pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
372                 goto finish;
373             }
374
375             _use_mmap = FALSE;
376         }
377
378     } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
379         pa_log_debug("snd_pcm_hw_params_set_access() failed: %s", pa_alsa_strerror(ret));
380         goto finish;
381     }
382
383     if (!_use_mmap)
384         _use_tsched = FALSE;
385
386     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
387         goto finish;
388
389     if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0) {
390         pa_log_debug("snd_pcm_hw_params_set_rate_near() failed: %s", pa_alsa_strerror(ret));
391         goto finish;
392     }
393
394     if (require_exact_channel_number) {
395         if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0) {
396             pa_log_debug("snd_pcm_hw_params_set_channels() failed: %s", pa_alsa_strerror(ret));
397             goto finish;
398         }
399     } else {
400         if ((ret = snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c)) < 0) {
401             pa_log_debug("snd_pcm_hw_params_set_channels_near() failed: %s", pa_alsa_strerror(ret));
402             goto finish;
403         }
404     }
405
406     if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0) {
407         pa_log_debug("snd_pcm_hw_params_set_periods_integer() failed: %s", pa_alsa_strerror(ret));
408         goto finish;
409     }
410
411     if (_period_size && tsched_size && _periods) {
412
413         /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
414         _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
415         tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
416
417         if (_use_tsched) {
418             snd_pcm_uframes_t buffer_size;
419
420             pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size) == 0);
421             pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
422
423             _period_size = tsched_size;
424             _periods = 1;
425         }
426
427         if (_period_size > 0 && _periods > 0) {
428             snd_pcm_uframes_t buffer_size;
429
430             buffer_size = _periods * _period_size;
431
432             if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
433                 pa_log_info("snd_pcm_hw_params_set_buffer_size_near() failed: %s", pa_alsa_strerror(ret));
434         }
435
436         if (_periods > 0) {
437
438             /* First we pass 0 as direction to get exactly what we
439              * asked for. That this is necessary is presumably a bug
440              * in ALSA. All in all this is mostly a hint to ALSA, so
441              * we don't care if this fails. */
442
443             dir = 0;
444             if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir) < 0) {
445                 dir = 1;
446                 if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir) < 0) {
447                     dir = -1;
448                     if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
449                         pa_log_info("snd_pcm_hw_params_set_periods_near() failed: %s", pa_alsa_strerror(ret));
450                 }
451             }
452         }
453     }
454
455     if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
456         goto finish;
457
458     if (ss->rate != r)
459         pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
460
461     if (ss->channels != c)
462         pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
463
464     if (ss->format != f)
465         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(f));
466
467     if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
468         goto finish;
469
470     if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
471         (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0)
472         goto finish;
473
474     /* If the sample rate deviates too much, we need to resample */
475     if (r < ss->rate*.95 || r > ss->rate*1.05)
476         ss->rate = r;
477     ss->channels = (uint8_t) c;
478     ss->format = f;
479
480     pa_assert(_periods > 0);
481     pa_assert(_period_size > 0);
482
483     if (periods)
484         *periods = _periods;
485
486     if (period_size)
487         *period_size = _period_size;
488
489     if (use_mmap)
490         *use_mmap = _use_mmap;
491
492     if (use_tsched)
493         *use_tsched = _use_tsched;
494
495     ret = 0;
496
497     snd_pcm_nonblock(pcm_handle, 1);
498
499 finish:
500
501     return ret;
502 }
503
504 int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
505     snd_pcm_sw_params_t *swparams;
506     snd_pcm_uframes_t boundary;
507     int err;
508
509     pa_assert(pcm);
510
511     snd_pcm_sw_params_alloca(&swparams);
512
513     if ((err = snd_pcm_sw_params_current(pcm, swparams) < 0)) {
514         pa_log_warn("Unable to determine current swparams: %s\n", pa_alsa_strerror(err));
515         return err;
516     }
517
518     if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, 0)) < 0) {
519         pa_log_warn("Unable to disable period event: %s\n", pa_alsa_strerror(err));
520         return err;
521     }
522
523     if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) {
524         pa_log_warn("Unable to enable time stamping: %s\n", pa_alsa_strerror(err));
525         return err;
526     }
527
528     if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) {
529         pa_log_warn("Unable to get boundary: %s\n", pa_alsa_strerror(err));
530         return err;
531     }
532
533     if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) {
534         pa_log_warn("Unable to set stop threshold: %s\n", pa_alsa_strerror(err));
535         return err;
536     }
537
538     if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) -1)) < 0) {
539         pa_log_warn("Unable to set start threshold: %s\n", pa_alsa_strerror(err));
540         return err;
541     }
542
543     if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
544         pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", pa_alsa_strerror(err));
545         return err;
546     }
547
548     if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) {
549         pa_log_warn("Unable to set sw params: %s\n", pa_alsa_strerror(err));
550         return err;
551     }
552
553     return 0;
554 }
555
556 static const struct pa_alsa_profile_info device_table[] = {
557     {{ 1, { PA_CHANNEL_POSITION_MONO }},
558      "hw", NULL,
559      N_("Analog Mono"),
560      "analog-mono",
561      1,
562      "Master", "PCM",
563      "Capture", "Mic" },
564
565     {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
566      "front", "hw",
567      N_("Analog Stereo"),
568      "analog-stereo",
569      10,
570      "Master", "PCM",
571      "Capture", "Mic" },
572
573     {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
574      "iec958", NULL,
575      N_("Digital Stereo (IEC958)"),
576      "iec958-stereo",
577      5,
578      "IEC958", NULL,
579      "IEC958 In", NULL },
580
581     {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
582      "hdmi", NULL,
583      N_("Digital Stereo (HDMI)"),
584      "hdmi-stereo",
585      4,
586      "IEC958", NULL,
587      "IEC958 In", NULL },
588
589     {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
590             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
591      "surround40", NULL,
592      N_("Analog Surround 4.0"),
593      "analog-surround-40",
594      7,
595      "Master", "PCM",
596      "Capture", "Mic" },
597
598     {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
599             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
600      "a52", NULL,
601      N_("Digital Surround 4.0 (IEC958/AC3)"),
602      "iec958-ac3-surround-40",
603      2,
604      "Master", "PCM",
605      "Capture", "Mic" },
606
607     {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
608             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
609             PA_CHANNEL_POSITION_LFE }},
610      "surround41", NULL,
611      N_("Analog Surround 4.1"),
612      "analog-surround-41",
613      7,
614      "Master", "PCM",
615      "Capture", "Mic" },
616
617     {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
618             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
619             PA_CHANNEL_POSITION_CENTER }},
620      "surround50", NULL,
621      N_("Analog Surround 5.0"),
622      "analog-surround-50",
623      7,
624      "Master", "PCM",
625      "Capture", "Mic" },
626
627     {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
628             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
629             PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }},
630      "surround51", NULL,
631      N_("Analog Surround 5.1"),
632      "analog-surround-51",
633      8,
634      "Master", "PCM",
635      "Capture", "Mic" },
636
637     {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
638             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
639             PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE}},
640      "a52", NULL,
641      N_("Digital Surround 5.1 (IEC958/AC3)"),
642      "iec958-ac3-surround-51",
643      3,
644      "IEC958", NULL,
645      "IEC958 In", NULL },
646
647     {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
648             PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
649             PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
650             PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }},
651      "surround71", NULL,
652      N_("Analog Surround 7.1"),
653      "analog-surround-71",
654      7,
655      "Master", "PCM",
656      "Capture", "Mic" },
657
658     {{ 0, { 0 }}, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
659 };
660
661 static snd_pcm_t *open_by_device_string_with_fallback(
662         const char *prefix,
663         const char *prefix_fallback,
664         const char *dev_id,
665         char **dev,
666         pa_sample_spec *ss,
667         pa_channel_map* map,
668         int mode,
669         uint32_t *nfrags,
670         snd_pcm_uframes_t *period_size,
671         snd_pcm_uframes_t tsched_size,
672         pa_bool_t *use_mmap,
673         pa_bool_t *use_tsched,
674         pa_bool_t require_exact_channel_number) {
675
676     snd_pcm_t *pcm_handle;
677     char *d;
678
679     d = pa_sprintf_malloc("%s:%s", prefix, dev_id);
680
681     pcm_handle = pa_alsa_open_by_device_string(
682             d,
683             dev,
684             ss,
685             map,
686             mode,
687             nfrags,
688             period_size,
689             tsched_size,
690             use_mmap,
691             use_tsched,
692             require_exact_channel_number);
693     pa_xfree(d);
694
695     if (!pcm_handle && prefix_fallback) {
696
697         d = pa_sprintf_malloc("%s:%s", prefix_fallback, dev_id);
698
699         pcm_handle = pa_alsa_open_by_device_string(
700                 d,
701                 dev,
702                 ss,
703                 map,
704                 mode,
705                 nfrags,
706                 period_size,
707                 tsched_size,
708                 use_mmap,
709                 use_tsched,
710                 require_exact_channel_number);
711         pa_xfree(d);
712     }
713
714     return pcm_handle;
715 }
716
717 snd_pcm_t *pa_alsa_open_by_device_id_auto(
718         const char *dev_id,
719         char **dev,
720         pa_sample_spec *ss,
721         pa_channel_map* map,
722         int mode,
723         uint32_t *nfrags,
724         snd_pcm_uframes_t *period_size,
725         snd_pcm_uframes_t tsched_size,
726         pa_bool_t *use_mmap,
727         pa_bool_t *use_tsched,
728         const pa_alsa_profile_info **profile) {
729
730     int i;
731     int direction = 1;
732     char *d;
733     snd_pcm_t *pcm_handle;
734
735     pa_assert(dev_id);
736     pa_assert(dev);
737     pa_assert(ss);
738     pa_assert(map);
739     pa_assert(nfrags);
740     pa_assert(period_size);
741
742     /* First we try to find a device string with a superset of the
743      * requested channel map and open it without the plug: prefix. We
744      * iterate through our device table from top to bottom and take
745      * the first that matches. If we didn't find a working device that
746      * way, we iterate backwards, and check all devices that do not
747      * provide a superset of the requested channel map.*/
748
749     i = 0;
750     for (;;) {
751
752         if ((direction > 0) == pa_channel_map_superset(&device_table[i].map, map)) {
753             pa_sample_spec try_ss;
754
755             pa_log_debug("Checking for %s (%s)", device_table[i].name, device_table[i].alsa_name);
756
757             try_ss.channels = device_table[i].map.channels;
758             try_ss.rate = ss->rate;
759             try_ss.format = ss->format;
760
761             pcm_handle = open_by_device_string_with_fallback(
762                     device_table[i].alsa_name,
763                     device_table[i].alsa_name_fallback,
764                     dev_id,
765                     dev,
766                     &try_ss,
767                     map,
768                     mode,
769                     nfrags,
770                     period_size,
771                     tsched_size,
772                     use_mmap,
773                     use_tsched,
774                     TRUE);
775
776             if (pcm_handle) {
777
778                 *ss = try_ss;
779                 *map = device_table[i].map;
780                 pa_assert(map->channels == ss->channels);
781
782                 if (profile)
783                     *profile = &device_table[i];
784
785                 return pcm_handle;
786             }
787
788         }
789
790         if (direction > 0) {
791             if (!device_table[i+1].alsa_name) {
792                 /* OK, so we are at the end of our list. Let's turn
793                  * back. */
794                 direction = -1;
795             } else {
796                 /* We are not at the end of the list, so let's simply
797                  * try the next entry */
798                 i++;
799             }
800         }
801
802         if (direction < 0) {
803
804             if (device_table[i+1].alsa_name &&
805                 device_table[i].map.channels == device_table[i+1].map.channels) {
806
807                 /* OK, the next entry has the same number of channels,
808                  * let's try it */
809                 i++;
810
811             } else {
812                 /* Hmm, so the next entry does not have the same
813                  * number of channels, so let's go backwards until we
814                  * find the next entry with a different number of
815                  * channels */
816
817                 for (i--; i >= 0; i--)
818                     if (device_table[i].map.channels != device_table[i+1].map.channels)
819                         break;
820
821                 /* Hmm, there is no entry with a different number of
822                  * entries, then we're done */
823                 if (i < 0)
824                     break;
825
826                 /* OK, now lets find go back as long as we have the same number of channels */
827                 for (; i > 0; i--)
828                     if (device_table[i].map.channels != device_table[i-1].map.channels)
829                         break;
830             }
831         }
832     }
833
834     /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
835
836     d = pa_sprintf_malloc("hw:%s", dev_id);
837     pa_log_debug("Trying %s as last resort...", d);
838     pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
839     pa_xfree(d);
840
841     if (pcm_handle && profile)
842         *profile = NULL;
843
844     return pcm_handle;
845 }
846
847 snd_pcm_t *pa_alsa_open_by_device_id_profile(
848         const char *dev_id,
849         char **dev,
850         pa_sample_spec *ss,
851         pa_channel_map* map,
852         int mode,
853         uint32_t *nfrags,
854         snd_pcm_uframes_t *period_size,
855         snd_pcm_uframes_t tsched_size,
856         pa_bool_t *use_mmap,
857         pa_bool_t *use_tsched,
858         const pa_alsa_profile_info *profile) {
859
860     snd_pcm_t *pcm_handle;
861     pa_sample_spec try_ss;
862
863     pa_assert(dev_id);
864     pa_assert(dev);
865     pa_assert(ss);
866     pa_assert(map);
867     pa_assert(nfrags);
868     pa_assert(period_size);
869     pa_assert(profile);
870
871     try_ss.channels = profile->map.channels;
872     try_ss.rate = ss->rate;
873     try_ss.format = ss->format;
874
875     pcm_handle = open_by_device_string_with_fallback(
876             profile->alsa_name,
877             profile->alsa_name_fallback,
878             dev_id,
879             dev,
880             &try_ss,
881             map,
882             mode,
883             nfrags,
884             period_size,
885             tsched_size,
886             use_mmap,
887             use_tsched,
888             TRUE);
889
890     if (!pcm_handle)
891         return NULL;
892
893     *ss = try_ss;
894     *map = profile->map;
895     pa_assert(map->channels == ss->channels);
896
897     return pcm_handle;
898 }
899
900 snd_pcm_t *pa_alsa_open_by_device_string(
901         const char *device,
902         char **dev,
903         pa_sample_spec *ss,
904         pa_channel_map* map,
905         int mode,
906         uint32_t *nfrags,
907         snd_pcm_uframes_t *period_size,
908         snd_pcm_uframes_t tsched_size,
909         pa_bool_t *use_mmap,
910         pa_bool_t *use_tsched,
911         pa_bool_t require_exact_channel_number) {
912
913     int err;
914     char *d;
915     snd_pcm_t *pcm_handle;
916     pa_bool_t reformat = FALSE;
917
918     pa_assert(device);
919     pa_assert(ss);
920     pa_assert(map);
921
922     d = pa_xstrdup(device);
923
924     for (;;) {
925         pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
926
927         /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
928          * 1.0.17a would then ignore the SND_PCM_NO_xxx flags. Instead
929          * we enable nonblock mode afterwards via
930          * snd_pcm_nonblock(). Also see
931          * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
932
933         if ((err = snd_pcm_open(&pcm_handle, d, mode,
934                                 /*SND_PCM_NONBLOCK|*/
935                                 SND_PCM_NO_AUTO_RESAMPLE|
936                                 SND_PCM_NO_AUTO_CHANNELS|
937                                 (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
938             pa_log_info("Error opening PCM device %s: %s", d, pa_alsa_strerror(err));
939             goto fail;
940         }
941
942         pa_log_debug("Managed to open %s", d);
943
944         if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
945
946             if (!reformat) {
947                 reformat = TRUE;
948
949                 snd_pcm_close(pcm_handle);
950                 continue;
951             }
952
953             /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
954
955             if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
956                 char *t;
957
958                 t = pa_sprintf_malloc("plug:%s", d);
959                 pa_xfree(d);
960                 d = t;
961
962                 reformat = FALSE;
963
964                 snd_pcm_close(pcm_handle);
965                 continue;
966             }
967
968             pa_log_info("Failed to set hardware parameters on %s: %s", d, pa_alsa_strerror(err));
969             snd_pcm_close(pcm_handle);
970
971             goto fail;
972         }
973
974         if (dev)
975             *dev = d;
976         else
977             pa_xfree(d);
978
979         if (ss->channels != map->channels)
980             pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
981
982         return pcm_handle;
983     }
984
985 fail:
986     pa_xfree(d);
987
988     return NULL;
989 }
990
991 int pa_alsa_probe_profiles(
992         const char *dev_id,
993         const pa_sample_spec *ss,
994         void (*cb)(const pa_alsa_profile_info *sink, const pa_alsa_profile_info *source, void *userdata),
995         void *userdata) {
996
997     const pa_alsa_profile_info *i;
998
999     pa_assert(dev_id);
1000     pa_assert(ss);
1001     pa_assert(cb);
1002
1003     /* We try each combination of playback/capture. We also try to
1004      * open only for capture resp. only for sink. Don't get confused
1005      * by the trailing entry in device_table we use for this! */
1006
1007     for (i = device_table; i < device_table + PA_ELEMENTSOF(device_table); i++) {
1008         const pa_alsa_profile_info *j;
1009         snd_pcm_t *pcm_i = NULL;
1010
1011         if (i->alsa_name) {
1012             pa_sample_spec try_ss;
1013             pa_channel_map try_map;
1014
1015             pa_log_debug("Checking for playback on %s (%s)", i->name, i->alsa_name);
1016
1017             try_ss = *ss;
1018             try_ss.channels = i->map.channels;
1019             try_map = i->map;
1020
1021             pcm_i = open_by_device_string_with_fallback(
1022                     i->alsa_name,
1023                     i->alsa_name_fallback,
1024                     dev_id,
1025                     NULL,
1026                     &try_ss, &try_map,
1027                     SND_PCM_STREAM_PLAYBACK,
1028                     NULL, NULL, 0, NULL, NULL,
1029                     TRUE);
1030
1031             if (!pcm_i)
1032                 continue;
1033         }
1034
1035         for (j = device_table; j < device_table + PA_ELEMENTSOF(device_table); j++) {
1036             snd_pcm_t *pcm_j = NULL;
1037
1038             if (j->alsa_name) {
1039                 pa_sample_spec try_ss;
1040                 pa_channel_map try_map;
1041
1042                 pa_log_debug("Checking for capture on %s (%s)", j->name, j->alsa_name);
1043
1044                 try_ss = *ss;
1045                 try_ss.channels = j->map.channels;
1046                 try_map = j->map;
1047
1048                 pcm_j = open_by_device_string_with_fallback(
1049                         j->alsa_name,
1050                         j->alsa_name_fallback,
1051                         dev_id,
1052                         NULL,
1053                         &try_ss, &try_map,
1054                         SND_PCM_STREAM_CAPTURE,
1055                         NULL, NULL, 0, NULL, NULL,
1056                         TRUE);
1057
1058                 if (!pcm_j)
1059                     continue;
1060             }
1061
1062             if (pcm_j)
1063                 snd_pcm_close(pcm_j);
1064
1065             if (i->alsa_name || j->alsa_name)
1066                 cb(i->alsa_name ? i : NULL,
1067                    j->alsa_name ? j : NULL, userdata);
1068         }
1069
1070         if (pcm_i)
1071             snd_pcm_close(pcm_i);
1072     }
1073
1074     return TRUE;
1075 }
1076
1077 int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
1078     int err;
1079
1080     pa_assert(mixer);
1081     pa_assert(dev);
1082
1083     if ((err = snd_mixer_attach(mixer, dev)) < 0) {
1084         pa_log_info("Unable to attach to mixer %s: %s", dev, pa_alsa_strerror(err));
1085         return -1;
1086     }
1087
1088     if ((err = snd_mixer_selem_register(mixer, NULL, NULL)) < 0) {
1089         pa_log_warn("Unable to register mixer: %s", pa_alsa_strerror(err));
1090         return -1;
1091     }
1092
1093     if ((err = snd_mixer_load(mixer)) < 0) {
1094         pa_log_warn("Unable to load mixer: %s", pa_alsa_strerror(err));
1095         return -1;
1096     }
1097
1098     pa_log_info("Successfully attached to mixer '%s'", dev);
1099
1100     return 0;
1101 }
1102
1103 static pa_bool_t elem_has_volume(snd_mixer_elem_t *elem, pa_bool_t playback) {
1104     pa_assert(elem);
1105
1106     if (playback && snd_mixer_selem_has_playback_volume(elem))
1107         return TRUE;
1108
1109     if (!playback && snd_mixer_selem_has_capture_volume(elem))
1110         return TRUE;
1111
1112     return FALSE;
1113 }
1114
1115 static pa_bool_t elem_has_switch(snd_mixer_elem_t *elem, pa_bool_t playback) {
1116     pa_assert(elem);
1117
1118     if (playback && snd_mixer_selem_has_playback_switch(elem))
1119         return TRUE;
1120
1121     if (!playback && snd_mixer_selem_has_capture_switch(elem))
1122         return TRUE;
1123
1124     return FALSE;
1125 }
1126
1127 snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback) {
1128     snd_mixer_elem_t *elem = NULL, *fallback_elem = NULL;
1129     snd_mixer_selem_id_t *sid = NULL;
1130
1131     snd_mixer_selem_id_alloca(&sid);
1132
1133     pa_assert(mixer);
1134     pa_assert(name);
1135
1136     snd_mixer_selem_id_set_name(sid, name);
1137     snd_mixer_selem_id_set_index(sid, 0);
1138
1139     if ((elem = snd_mixer_find_selem(mixer, sid))) {
1140
1141         if (elem_has_volume(elem, playback) &&
1142             elem_has_switch(elem, playback))
1143             goto success;
1144
1145         if (!elem_has_volume(elem, playback) &&
1146             !elem_has_switch(elem, playback))
1147             elem = NULL;
1148     }
1149
1150     pa_log_info("Cannot find mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
1151
1152     if (fallback) {
1153         snd_mixer_selem_id_set_name(sid, fallback);
1154         snd_mixer_selem_id_set_index(sid, 0);
1155
1156         if ((fallback_elem = snd_mixer_find_selem(mixer, sid))) {
1157
1158             if (elem_has_volume(fallback_elem, playback) &&
1159                 elem_has_switch(fallback_elem, playback)) {
1160                 elem = fallback_elem;
1161                 goto success;
1162             }
1163
1164             if (!elem_has_volume(fallback_elem, playback) &&
1165                 !elem_has_switch(fallback_elem, playback))
1166                 fallback_elem = NULL;
1167         }
1168
1169         pa_log_info("Cannot find fallback mixer control \"%s\" or mixer control is no combination of switch/volume.", snd_mixer_selem_id_get_name(sid));
1170     }
1171
1172     if (elem && fallback_elem) {
1173
1174         /* Hmm, so we have both elements, but neither has both mute
1175          * and volume. Let's prefer the one with the volume */
1176
1177         if (elem_has_volume(elem, playback))
1178             goto success;
1179
1180         if (elem_has_volume(fallback_elem, playback)) {
1181             elem = fallback_elem;
1182             goto success;
1183         }
1184     }
1185
1186     if (!elem && fallback_elem)
1187         elem = fallback_elem;
1188
1189 success:
1190
1191     if (elem)
1192         pa_log_info("Using mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
1193
1194     return elem;
1195 }
1196
1197 int pa_alsa_find_mixer_and_elem(
1198         snd_pcm_t *pcm,
1199         char **ctl_device,
1200         snd_mixer_t **_m,
1201         snd_mixer_elem_t **_e,
1202         const char *control_name,
1203         const pa_alsa_profile_info *profile) {
1204
1205     int err;
1206     snd_mixer_t *m;
1207     snd_mixer_elem_t *e;
1208     pa_bool_t found = FALSE;
1209     const char *dev;
1210
1211     pa_assert(pcm);
1212     pa_assert(_m);
1213     pa_assert(_e);
1214
1215     if (control_name && *control_name == 0) {
1216         pa_log_debug("Hardware mixer usage disabled because empty control name passed");
1217         return -1;
1218     }
1219
1220     if ((err = snd_mixer_open(&m, 0)) < 0) {
1221         pa_log("Error opening mixer: %s", pa_alsa_strerror(err));
1222         return -1;
1223     }
1224
1225     /* First, try by name */
1226     if ((dev = snd_pcm_name(pcm)))
1227         if (pa_alsa_prepare_mixer(m, dev) >= 0) {
1228             found = TRUE;
1229
1230             if (ctl_device)
1231                 *ctl_device = pa_xstrdup(dev);
1232         }
1233
1234     /* Then, try by card index */
1235     if (!found) {
1236         snd_pcm_info_t* info;
1237         snd_pcm_info_alloca(&info);
1238
1239         if (snd_pcm_info(pcm, info) >= 0) {
1240             char *md;
1241             int card_idx;
1242
1243             if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
1244
1245                 md = pa_sprintf_malloc("hw:%i", card_idx);
1246
1247                 if (!dev || !pa_streq(dev, md))
1248                     if (pa_alsa_prepare_mixer(m, md) >= 0) {
1249                         found = TRUE;
1250
1251                         if (ctl_device) {
1252                             *ctl_device = md;
1253                             md = NULL;
1254                         }
1255                     }
1256
1257                 pa_xfree(md);
1258             }
1259         }
1260     }
1261
1262     if (!found) {
1263         snd_mixer_close(m);
1264         return -1;
1265     }
1266
1267     switch (snd_pcm_stream(pcm)) {
1268
1269         case SND_PCM_STREAM_PLAYBACK:
1270             if (control_name)
1271                 e = pa_alsa_find_elem(m, control_name, NULL, TRUE);
1272             else if (profile)
1273                 e = pa_alsa_find_elem(m, profile->playback_control_name, profile->playback_control_fallback, TRUE);
1274             else
1275                 e = pa_alsa_find_elem(m, "Master", "PCM", TRUE);
1276             break;
1277
1278         case SND_PCM_STREAM_CAPTURE:
1279             if (control_name)
1280                 e = pa_alsa_find_elem(m, control_name, NULL, FALSE);
1281             else if (profile)
1282                 e = pa_alsa_find_elem(m, profile->record_control_name, profile->record_control_fallback, FALSE);
1283             else
1284                 e = pa_alsa_find_elem(m, "Capture", "Mic", FALSE);
1285             break;
1286
1287         default:
1288             pa_assert_not_reached();
1289     }
1290
1291     if (!e) {
1292         if (ctl_device)
1293             pa_xfree(*ctl_device);
1294
1295         snd_mixer_close(m);
1296         return -1;
1297     }
1298
1299     pa_assert(e && m);
1300
1301     *_m = m;
1302     *_e = e;
1303
1304     return 0;
1305 }
1306
1307 static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = {
1308     [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
1309
1310     [PA_CHANNEL_POSITION_FRONT_CENTER] = SND_MIXER_SCHN_FRONT_CENTER,
1311     [PA_CHANNEL_POSITION_FRONT_LEFT] = SND_MIXER_SCHN_FRONT_LEFT,
1312     [PA_CHANNEL_POSITION_FRONT_RIGHT] = SND_MIXER_SCHN_FRONT_RIGHT,
1313
1314     [PA_CHANNEL_POSITION_REAR_CENTER] = SND_MIXER_SCHN_REAR_CENTER,
1315     [PA_CHANNEL_POSITION_REAR_LEFT] = SND_MIXER_SCHN_REAR_LEFT,
1316     [PA_CHANNEL_POSITION_REAR_RIGHT] = SND_MIXER_SCHN_REAR_RIGHT,
1317
1318     [PA_CHANNEL_POSITION_LFE] = SND_MIXER_SCHN_WOOFER,
1319
1320     [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1321     [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1322
1323     [PA_CHANNEL_POSITION_SIDE_LEFT] = SND_MIXER_SCHN_SIDE_LEFT,
1324     [PA_CHANNEL_POSITION_SIDE_RIGHT] = SND_MIXER_SCHN_SIDE_RIGHT,
1325
1326     [PA_CHANNEL_POSITION_AUX0] = SND_MIXER_SCHN_UNKNOWN,
1327     [PA_CHANNEL_POSITION_AUX1] = SND_MIXER_SCHN_UNKNOWN,
1328     [PA_CHANNEL_POSITION_AUX2] = SND_MIXER_SCHN_UNKNOWN,
1329     [PA_CHANNEL_POSITION_AUX3] = SND_MIXER_SCHN_UNKNOWN,
1330     [PA_CHANNEL_POSITION_AUX4] = SND_MIXER_SCHN_UNKNOWN,
1331     [PA_CHANNEL_POSITION_AUX5] = SND_MIXER_SCHN_UNKNOWN,
1332     [PA_CHANNEL_POSITION_AUX6] = SND_MIXER_SCHN_UNKNOWN,
1333     [PA_CHANNEL_POSITION_AUX7] = SND_MIXER_SCHN_UNKNOWN,
1334     [PA_CHANNEL_POSITION_AUX8] = SND_MIXER_SCHN_UNKNOWN,
1335     [PA_CHANNEL_POSITION_AUX9] =  SND_MIXER_SCHN_UNKNOWN,
1336     [PA_CHANNEL_POSITION_AUX10] = SND_MIXER_SCHN_UNKNOWN,
1337     [PA_CHANNEL_POSITION_AUX11] = SND_MIXER_SCHN_UNKNOWN,
1338     [PA_CHANNEL_POSITION_AUX12] = SND_MIXER_SCHN_UNKNOWN,
1339     [PA_CHANNEL_POSITION_AUX13] = SND_MIXER_SCHN_UNKNOWN,
1340     [PA_CHANNEL_POSITION_AUX14] = SND_MIXER_SCHN_UNKNOWN,
1341     [PA_CHANNEL_POSITION_AUX15] = SND_MIXER_SCHN_UNKNOWN,
1342     [PA_CHANNEL_POSITION_AUX16] = SND_MIXER_SCHN_UNKNOWN,
1343     [PA_CHANNEL_POSITION_AUX17] = SND_MIXER_SCHN_UNKNOWN,
1344     [PA_CHANNEL_POSITION_AUX18] = SND_MIXER_SCHN_UNKNOWN,
1345     [PA_CHANNEL_POSITION_AUX19] = SND_MIXER_SCHN_UNKNOWN,
1346     [PA_CHANNEL_POSITION_AUX20] = SND_MIXER_SCHN_UNKNOWN,
1347     [PA_CHANNEL_POSITION_AUX21] = SND_MIXER_SCHN_UNKNOWN,
1348     [PA_CHANNEL_POSITION_AUX22] = SND_MIXER_SCHN_UNKNOWN,
1349     [PA_CHANNEL_POSITION_AUX23] = SND_MIXER_SCHN_UNKNOWN,
1350     [PA_CHANNEL_POSITION_AUX24] = SND_MIXER_SCHN_UNKNOWN,
1351     [PA_CHANNEL_POSITION_AUX25] = SND_MIXER_SCHN_UNKNOWN,
1352     [PA_CHANNEL_POSITION_AUX26] = SND_MIXER_SCHN_UNKNOWN,
1353     [PA_CHANNEL_POSITION_AUX27] = SND_MIXER_SCHN_UNKNOWN,
1354     [PA_CHANNEL_POSITION_AUX28] = SND_MIXER_SCHN_UNKNOWN,
1355     [PA_CHANNEL_POSITION_AUX29] = SND_MIXER_SCHN_UNKNOWN,
1356     [PA_CHANNEL_POSITION_AUX30] = SND_MIXER_SCHN_UNKNOWN,
1357     [PA_CHANNEL_POSITION_AUX31] = SND_MIXER_SCHN_UNKNOWN,
1358
1359     [PA_CHANNEL_POSITION_TOP_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1360
1361     [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1362     [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = SND_MIXER_SCHN_UNKNOWN,
1363     [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = SND_MIXER_SCHN_UNKNOWN,
1364
1365     [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = SND_MIXER_SCHN_UNKNOWN,
1366     [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = SND_MIXER_SCHN_UNKNOWN,
1367     [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SND_MIXER_SCHN_UNKNOWN
1368 };
1369
1370
1371 int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback) {
1372     unsigned i;
1373     pa_bool_t alsa_channel_used[SND_MIXER_SCHN_LAST];
1374     pa_bool_t mono_used = FALSE;
1375
1376     pa_assert(elem);
1377     pa_assert(channel_map);
1378     pa_assert(mixer_map);
1379
1380     memset(&alsa_channel_used, 0, sizeof(alsa_channel_used));
1381
1382     if (channel_map->channels > 1 &&
1383         ((playback && snd_mixer_selem_has_playback_volume_joined(elem)) ||
1384          (!playback && snd_mixer_selem_has_capture_volume_joined(elem)))) {
1385         pa_log_info("ALSA device lacks independant volume controls for each channel.");
1386         return -1;
1387     }
1388
1389     for (i = 0; i < channel_map->channels; i++) {
1390         snd_mixer_selem_channel_id_t id;
1391         pa_bool_t is_mono;
1392
1393         is_mono = channel_map->map[i] == PA_CHANNEL_POSITION_MONO;
1394         id = alsa_channel_ids[channel_map->map[i]];
1395
1396         if (!is_mono && id == SND_MIXER_SCHN_UNKNOWN) {
1397             pa_log_info("Configured channel map contains channel '%s' that is unknown to the ALSA mixer.", pa_channel_position_to_string(channel_map->map[i]));
1398             return -1;
1399         }
1400
1401         if ((is_mono && mono_used) || (!is_mono && alsa_channel_used[id])) {
1402             pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
1403             return -1;
1404         }
1405
1406         if ((playback && (!snd_mixer_selem_has_playback_channel(elem, id) || (is_mono && !snd_mixer_selem_is_playback_mono(elem)))) ||
1407             (!playback && (!snd_mixer_selem_has_capture_channel(elem, id) || (is_mono && !snd_mixer_selem_is_capture_mono(elem))))) {
1408
1409             pa_log_info("ALSA device lacks separate volumes control for channel '%s'", pa_channel_position_to_string(channel_map->map[i]));
1410             return -1;
1411         }
1412
1413         if (is_mono) {
1414             mixer_map[i] = SND_MIXER_SCHN_MONO;
1415             mono_used = TRUE;
1416         } else {
1417             mixer_map[i] = id;
1418             alsa_channel_used[id] = TRUE;
1419         }
1420     }
1421
1422     pa_log_info("All %u channels can be mapped to mixer channels.", channel_map->channels);
1423
1424     return 0;
1425 }
1426
1427 void pa_alsa_dump(pa_log_level_t level, snd_pcm_t *pcm) {
1428     int err;
1429     snd_output_t *out;
1430
1431     pa_assert(pcm);
1432
1433     pa_assert_se(snd_output_buffer_open(&out) == 0);
1434
1435     if ((err = snd_pcm_dump(pcm, out)) < 0)
1436         pa_logl(level, "snd_pcm_dump(): %s", pa_alsa_strerror(err));
1437     else {
1438         char *s = NULL;
1439         snd_output_buffer_string(out, &s);
1440         pa_logl(level, "snd_pcm_dump():\n%s", pa_strnull(s));
1441     }
1442
1443     pa_assert_se(snd_output_close(out) == 0);
1444 }
1445
1446 void pa_alsa_dump_status(snd_pcm_t *pcm) {
1447     int err;
1448     snd_output_t *out;
1449     snd_pcm_status_t *status;
1450
1451     pa_assert(pcm);
1452
1453     snd_pcm_status_alloca(&status);
1454
1455     pa_assert_se(snd_output_buffer_open(&out) == 0);
1456
1457     pa_assert_se(snd_pcm_status(pcm, status) == 0);
1458
1459     if ((err = snd_pcm_status_dump(status, out)) < 0)
1460         pa_log_debug("snd_pcm_dump(): %s", pa_alsa_strerror(err));
1461     else {
1462         char *s = NULL;
1463         snd_output_buffer_string(out, &s);
1464         pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
1465     }
1466
1467     pa_assert_se(snd_output_close(out) == 0);
1468 }
1469
1470 static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
1471     va_list ap;
1472     char *alsa_file;
1473
1474     alsa_file = pa_sprintf_malloc("(alsa-lib)%s", file);
1475
1476     va_start(ap, fmt);
1477
1478     pa_log_levelv_meta(PA_LOG_INFO, alsa_file, line, function, fmt, ap);
1479
1480     va_end(ap);
1481
1482     pa_xfree(alsa_file);
1483 }
1484
1485 static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
1486
1487 void pa_alsa_redirect_errors_inc(void) {
1488     /* This is not really thread safe, but we do our best */
1489
1490     if (pa_atomic_inc(&n_error_handler_installed) == 0)
1491         snd_lib_error_set_handler(alsa_error_handler);
1492 }
1493
1494 void pa_alsa_redirect_errors_dec(void) {
1495     int r;
1496
1497     pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
1498
1499     if (r == 1)
1500         snd_lib_error_set_handler(NULL);
1501 }
1502
1503 pa_bool_t pa_alsa_init_description(pa_proplist *p) {
1504     const char *s;
1505     pa_assert(p);
1506
1507     if (pa_device_init_description(p))
1508         return TRUE;
1509
1510     if ((s = pa_proplist_gets(p, "alsa.card_name"))) {
1511         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
1512         return TRUE;
1513     }
1514
1515     if ((s = pa_proplist_gets(p, "alsa.name"))) {
1516         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s);
1517         return TRUE;
1518     }
1519
1520     return FALSE;
1521 }
1522
1523 void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) {
1524     char *cn, *lcn, *dn;
1525
1526     pa_assert(p);
1527     pa_assert(card >= 0);
1528
1529     pa_proplist_setf(p, "alsa.card", "%i", card);
1530
1531     if (snd_card_get_name(card, &cn) >= 0) {
1532         pa_proplist_sets(p, "alsa.card_name", cn);
1533         free(cn);
1534     }
1535
1536     if (snd_card_get_longname(card, &lcn) >= 0) {
1537         pa_proplist_sets(p, "alsa.long_card_name", lcn);
1538         free(lcn);
1539     }
1540
1541     if ((dn = pa_alsa_get_driver_name(card))) {
1542         pa_proplist_sets(p, "alsa.driver_name", dn);
1543         pa_xfree(dn);
1544     }
1545
1546 #ifdef HAVE_UDEV
1547     pa_udev_get_info(c, p, card);
1548 #endif
1549
1550 #ifdef HAVE_HAL
1551     pa_hal_get_info(c, p, card);
1552 #endif
1553 }
1554
1555 void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info) {
1556
1557     static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
1558         [SND_PCM_CLASS_GENERIC] = "generic",
1559         [SND_PCM_CLASS_MULTI] = "multi",
1560         [SND_PCM_CLASS_MODEM] = "modem",
1561         [SND_PCM_CLASS_DIGITIZER] = "digitizer"
1562     };
1563     static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
1564         [SND_PCM_CLASS_GENERIC] = "sound",
1565         [SND_PCM_CLASS_MULTI] = NULL,
1566         [SND_PCM_CLASS_MODEM] = "modem",
1567         [SND_PCM_CLASS_DIGITIZER] = NULL
1568     };
1569     static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
1570         [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
1571         [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
1572     };
1573
1574     snd_pcm_class_t class;
1575     snd_pcm_subclass_t subclass;
1576     const char *n, *id, *sdn;
1577     int card;
1578
1579     pa_assert(p);
1580     pa_assert(pcm_info);
1581
1582     pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
1583
1584     class = snd_pcm_info_get_class(pcm_info);
1585     if (class <= SND_PCM_CLASS_LAST) {
1586         if (class_table[class])
1587             pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
1588         if (alsa_class_table[class])
1589             pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
1590     }
1591
1592     subclass = snd_pcm_info_get_subclass(pcm_info);
1593     if (subclass <= SND_PCM_SUBCLASS_LAST)
1594         if (alsa_subclass_table[subclass])
1595             pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
1596
1597     if ((n = snd_pcm_info_get_name(pcm_info)))
1598         pa_proplist_sets(p, "alsa.name", n);
1599
1600     if ((id = snd_pcm_info_get_id(pcm_info)))
1601         pa_proplist_sets(p, "alsa.id", id);
1602
1603     pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
1604     if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
1605         pa_proplist_sets(p, "alsa.subdevice_name", sdn);
1606
1607     pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
1608
1609     if ((card = snd_pcm_info_get_card(pcm_info)) >= 0)
1610         pa_alsa_init_proplist_card(c, p, card);
1611 }
1612
1613 void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm, snd_mixer_elem_t *elem) {
1614     snd_pcm_hw_params_t *hwparams;
1615     snd_pcm_info_t *info;
1616     int bits, err;
1617
1618     snd_pcm_hw_params_alloca(&hwparams);
1619     snd_pcm_info_alloca(&info);
1620
1621     if ((err = snd_pcm_hw_params_current(pcm, hwparams)) < 0)
1622         pa_log_warn("Error fetching hardware parameter info: %s", pa_alsa_strerror(err));
1623     else {
1624
1625         if ((bits = snd_pcm_hw_params_get_sbits(hwparams)) >= 0)
1626             pa_proplist_setf(p, "alsa.resolution_bits", "%i", bits);
1627     }
1628
1629     if (elem)
1630         pa_proplist_sets(p, "alsa.mixer_element", snd_mixer_selem_get_name(elem));
1631
1632     if ((err = snd_pcm_info(pcm, info)) < 0)
1633         pa_log_warn("Error fetching PCM info: %s", pa_alsa_strerror(err));
1634     else
1635         pa_alsa_init_proplist_pcm_info(c, p, info);
1636 }
1637
1638 void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) {
1639     int err;
1640     snd_ctl_t *ctl;
1641     snd_ctl_card_info_t *info;
1642     const char *t;
1643
1644     pa_assert(p);
1645
1646     snd_ctl_card_info_alloca(&info);
1647
1648     if ((err = snd_ctl_open(&ctl, name, 0)) < 0) {
1649         pa_log_warn("Error opening low-level control device '%s'", name);
1650         return;
1651     }
1652
1653     if ((err = snd_ctl_card_info(ctl, info)) < 0) {
1654         pa_log_warn("Control device %s card info: %s", name, snd_strerror(err));
1655         snd_ctl_close(ctl);
1656         return;
1657     }
1658
1659     if ((t = snd_ctl_card_info_get_mixername(info)))
1660         pa_proplist_sets(p, "alsa.mixer_name", t);
1661
1662     if ((t = snd_ctl_card_info_get_components(info)))
1663         pa_proplist_sets(p, "alsa.components", t);
1664
1665     snd_ctl_close(ctl);
1666 }
1667
1668 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
1669     snd_pcm_state_t state;
1670     int err;
1671
1672     pa_assert(pcm);
1673
1674     if (revents & POLLERR)
1675         pa_log_debug("Got POLLERR from ALSA");
1676     if (revents & POLLNVAL)
1677         pa_log_warn("Got POLLNVAL from ALSA");
1678     if (revents & POLLHUP)
1679         pa_log_warn("Got POLLHUP from ALSA");
1680     if (revents & POLLPRI)
1681         pa_log_warn("Got POLLPRI from ALSA");
1682     if (revents & POLLIN)
1683         pa_log_debug("Got POLLIN from ALSA");
1684     if (revents & POLLOUT)
1685         pa_log_debug("Got POLLOUT from ALSA");
1686
1687     state = snd_pcm_state(pcm);
1688     pa_log_debug("PCM state is %s", snd_pcm_state_name(state));
1689
1690     /* Try to recover from this error */
1691
1692     switch (state) {
1693
1694         case SND_PCM_STATE_XRUN:
1695             if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
1696                 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", pa_alsa_strerror(err));
1697                 return -1;
1698             }
1699             break;
1700
1701         case SND_PCM_STATE_SUSPENDED:
1702             if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
1703                 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", pa_alsa_strerror(err));
1704                 return -1;
1705             }
1706             break;
1707
1708         default:
1709
1710             snd_pcm_drop(pcm);
1711
1712             if ((err = snd_pcm_prepare(pcm)) < 0) {
1713                 pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", pa_alsa_strerror(err));
1714                 return -1;
1715             }
1716             break;
1717     }
1718
1719     return 0;
1720 }
1721
1722 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
1723     int n, err;
1724     struct pollfd *pollfd;
1725     pa_rtpoll_item *item;
1726
1727     pa_assert(pcm);
1728
1729     if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
1730         pa_log("snd_pcm_poll_descriptors_count() failed: %s", pa_alsa_strerror(n));
1731         return NULL;
1732     }
1733
1734     item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, (unsigned) n);
1735     pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
1736
1737     if ((err = snd_pcm_poll_descriptors(pcm, pollfd, (unsigned) n)) < 0) {
1738         pa_log("snd_pcm_poll_descriptors() failed: %s", pa_alsa_strerror(err));
1739         pa_rtpoll_item_free(item);
1740         return NULL;
1741     }
1742
1743     return item;
1744 }
1745
1746 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss) {
1747     snd_pcm_sframes_t n;
1748     size_t k;
1749
1750     pa_assert(pcm);
1751     pa_assert(hwbuf_size > 0);
1752     pa_assert(ss);
1753
1754     /* Some ALSA driver expose weird bugs, let's inform the user about
1755      * what is going on */
1756
1757     n = snd_pcm_avail(pcm);
1758
1759     if (n <= 0)
1760         return n;
1761
1762     k = (size_t) n * pa_frame_size(ss);
1763
1764     if (k >= hwbuf_size * 5 ||
1765         k >= pa_bytes_per_second(ss)*10) {
1766
1767         PA_ONCE_BEGIN {
1768             char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1769             pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1770                      "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1771                    (unsigned long) k,
1772                    (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1773                    pa_strnull(dn));
1774             pa_xfree(dn);
1775             pa_alsa_dump(PA_LOG_ERROR, pcm);
1776         } PA_ONCE_END;
1777
1778         /* Mhmm, let's try not to fail completely */
1779         n = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1780     }
1781
1782     return n;
1783 }
1784
1785 int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
1786     ssize_t k;
1787     size_t abs_k;
1788     int r;
1789
1790     pa_assert(pcm);
1791     pa_assert(delay);
1792     pa_assert(hwbuf_size > 0);
1793     pa_assert(ss);
1794
1795     /* Some ALSA driver expose weird bugs, let's inform the user about
1796      * what is going on */
1797
1798     if ((r = snd_pcm_delay(pcm, delay)) < 0)
1799         return r;
1800
1801     k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
1802
1803     abs_k = k >= 0 ? (size_t) k : (size_t) -k;
1804
1805     if (abs_k >= hwbuf_size * 5 ||
1806         abs_k >= pa_bytes_per_second(ss)*10) {
1807
1808         PA_ONCE_BEGIN {
1809             char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1810             pa_log(_("snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
1811                      "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1812                    (signed long) k,
1813                    k < 0 ? "-" : "",
1814                    (unsigned long) (pa_bytes_to_usec(abs_k, ss) / PA_USEC_PER_MSEC),
1815                    pa_strnull(dn));
1816             pa_xfree(dn);
1817             pa_alsa_dump(PA_LOG_ERROR, pcm);
1818         } PA_ONCE_END;
1819
1820         /* Mhmm, let's try not to fail completely */
1821         if (k < 0)
1822             *delay = -(snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1823         else
1824             *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
1825     }
1826
1827     return 0;
1828 }
1829
1830 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) {
1831     int r;
1832     snd_pcm_uframes_t before;
1833     size_t k;
1834
1835     pa_assert(pcm);
1836     pa_assert(areas);
1837     pa_assert(offset);
1838     pa_assert(frames);
1839     pa_assert(hwbuf_size > 0);
1840     pa_assert(ss);
1841
1842     before = *frames;
1843
1844     r = snd_pcm_mmap_begin(pcm, areas, offset, frames);
1845
1846     if (r < 0)
1847         return r;
1848
1849     k = (size_t) *frames * pa_frame_size(ss);
1850
1851     if (*frames > before ||
1852         k >= hwbuf_size * 3 ||
1853         k >= pa_bytes_per_second(ss)*10)
1854
1855         PA_ONCE_BEGIN {
1856             char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
1857             pa_log(_("snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
1858                      "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
1859                    (unsigned long) k,
1860                    (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
1861                    pa_strnull(dn));
1862             pa_xfree(dn);
1863             pa_alsa_dump(PA_LOG_ERROR, pcm);
1864         } PA_ONCE_END;
1865
1866     return r;
1867 }
1868
1869 char *pa_alsa_get_driver_name(int card) {
1870     char *t, *m, *n;
1871
1872     pa_assert(card >= 0);
1873
1874     t = pa_sprintf_malloc("/sys/class/sound/card%i/device/driver/module", card);
1875     m = pa_readlink(t);
1876     pa_xfree(t);
1877
1878     if (!m)
1879         return NULL;
1880
1881     n = pa_xstrdup(pa_path_get_filename(m));
1882     pa_xfree(m);
1883
1884     return n;
1885 }
1886
1887 char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
1888     int card;
1889     snd_pcm_info_t* info;
1890     snd_pcm_info_alloca(&info);
1891
1892     pa_assert(pcm);
1893
1894     if (snd_pcm_info(pcm, info) < 0)
1895         return NULL;
1896
1897     if ((card = snd_pcm_info_get_card(info)) < 0)
1898         return NULL;
1899
1900     return pa_alsa_get_driver_name(card);
1901 }
1902
1903 char *pa_alsa_get_reserve_name(const char *device) {
1904     const char *t;
1905     int i;
1906
1907     pa_assert(device);
1908
1909     if ((t = strchr(device, ':')))
1910         device = t+1;
1911
1912     if ((i = snd_card_get_index(device)) < 0) {
1913         int32_t k;
1914
1915         if (pa_atoi(device, &k) < 0)
1916             return NULL;
1917
1918         i = (int) k;
1919     }
1920
1921     return pa_sprintf_malloc("Audio%i", i);
1922 }
1923
1924 pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
1925     snd_pcm_info_t* info;
1926     snd_pcm_info_alloca(&info);
1927
1928     pa_assert(pcm);
1929
1930     if (snd_pcm_info(pcm, info) < 0)
1931         return FALSE;
1932
1933     return snd_pcm_info_get_card(info) >= 0;
1934 }
1935
1936 pa_bool_t pa_alsa_pcm_is_modem(snd_pcm_t *pcm) {
1937     snd_pcm_info_t* info;
1938     snd_pcm_info_alloca(&info);
1939
1940     pa_assert(pcm);
1941
1942     if (snd_pcm_info(pcm, info) < 0)
1943         return FALSE;
1944
1945     return snd_pcm_info_get_class(info) == SND_PCM_CLASS_MODEM;
1946 }
1947
1948 PA_STATIC_TLS_DECLARE(cstrerror, pa_xfree);
1949
1950 const char* pa_alsa_strerror(int errnum) {
1951     const char *original = NULL;
1952     char *translated, *t;
1953     char errbuf[128];
1954
1955     if ((t = PA_STATIC_TLS_GET(cstrerror)))
1956         pa_xfree(t);
1957
1958     original = snd_strerror(errnum);
1959
1960     if (!original) {
1961         pa_snprintf(errbuf, sizeof(errbuf), "Unknown error %i", errnum);
1962         original = errbuf;
1963     }
1964
1965     if (!(translated = pa_locale_to_utf8(original))) {
1966         pa_log_warn("Unable to convert error string to locale, filtering.");
1967         translated = pa_utf8_filter(original);
1968     }
1969
1970     PA_STATIC_TLS_SET(cstrerror, translated);
1971
1972     return translated;
1973 }