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