VM state change support (malc)
[qemu] / audio / alsaaudio.c
1 /*
2  * QEMU ALSA audio driver
3  *
4  * Copyright (c) 2005 Vassili Karpov (malc)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include <alsa/asoundlib.h>
25 #include "vl.h"
26
27 #define AUDIO_CAP "alsa"
28 #include "audio_int.h"
29
30 typedef struct ALSAVoiceOut {
31     HWVoiceOut hw;
32     void *pcm_buf;
33     snd_pcm_t *handle;
34     int can_pause;
35     int was_enabled;
36 } ALSAVoiceOut;
37
38 typedef struct ALSAVoiceIn {
39     HWVoiceIn hw;
40     snd_pcm_t *handle;
41     void *pcm_buf;
42     int can_pause;
43 } ALSAVoiceIn;
44
45 static struct {
46     int size_in_usec_in;
47     int size_in_usec_out;
48     const char *pcm_name_in;
49     const char *pcm_name_out;
50     unsigned int buffer_size_in;
51     unsigned int period_size_in;
52     unsigned int buffer_size_out;
53     unsigned int period_size_out;
54     unsigned int threshold;
55
56     int buffer_size_in_overriden;
57     int period_size_in_overriden;
58
59     int buffer_size_out_overriden;
60     int period_size_out_overriden;
61 } conf = {
62 #ifdef HIGH_LATENCY
63     .size_in_usec_in = 1,
64     .size_in_usec_out = 1,
65 #endif
66     .pcm_name_out = "hw:0,0",
67     .pcm_name_in = "hw:0,0",
68 #ifdef HIGH_LATENCY
69     .buffer_size_in = 400000,
70     .period_size_in = 400000 / 4,
71     .buffer_size_out = 400000,
72     .period_size_out = 400000 / 4,
73 #else
74 #define DEFAULT_BUFFER_SIZE 1024
75 #define DEFAULT_PERIOD_SIZE 256
76     .buffer_size_in = DEFAULT_BUFFER_SIZE,
77     .period_size_in = DEFAULT_PERIOD_SIZE,
78     .buffer_size_out = DEFAULT_BUFFER_SIZE,
79     .period_size_out = DEFAULT_PERIOD_SIZE,
80     .buffer_size_in_overriden = 0,
81     .buffer_size_out_overriden = 0,
82     .period_size_in_overriden = 0,
83     .period_size_out_overriden = 0,
84 #endif
85     .threshold = 0
86 };
87
88 struct alsa_params_req {
89     int freq;
90     audfmt_e fmt;
91     int nchannels;
92     unsigned int buffer_size;
93     unsigned int period_size;
94 };
95
96 struct alsa_params_obt {
97     int freq;
98     audfmt_e fmt;
99     int nchannels;
100     int can_pause;
101     snd_pcm_uframes_t samples;
102 };
103
104 static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
105 {
106     va_list ap;
107
108     va_start (ap, fmt);
109     AUD_vlog (AUDIO_CAP, fmt, ap);
110     va_end (ap);
111
112     AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
113 }
114
115 static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
116     int err,
117     const char *typ,
118     const char *fmt,
119     ...
120     )
121 {
122     va_list ap;
123
124     AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
125
126     va_start (ap, fmt);
127     AUD_vlog (AUDIO_CAP, fmt, ap);
128     va_end (ap);
129
130     AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
131 }
132
133 static void alsa_anal_close (snd_pcm_t **handlep)
134 {
135     int err = snd_pcm_close (*handlep);
136     if (err) {
137         alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
138     }
139     *handlep = NULL;
140 }
141
142 static int alsa_write (SWVoiceOut *sw, void *buf, int len)
143 {
144     return audio_pcm_sw_write (sw, buf, len);
145 }
146
147 static int aud_to_alsafmt (audfmt_e fmt)
148 {
149     switch (fmt) {
150     case AUD_FMT_S8:
151         return SND_PCM_FORMAT_S8;
152
153     case AUD_FMT_U8:
154         return SND_PCM_FORMAT_U8;
155
156     case AUD_FMT_S16:
157         return SND_PCM_FORMAT_S16_LE;
158
159     case AUD_FMT_U16:
160         return SND_PCM_FORMAT_U16_LE;
161
162     default:
163         dolog ("Internal logic error: Bad audio format %d\n", fmt);
164 #ifdef DEBUG_AUDIO
165         abort ();
166 #endif
167         return SND_PCM_FORMAT_U8;
168     }
169 }
170
171 static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
172 {
173     switch (alsafmt) {
174     case SND_PCM_FORMAT_S8:
175         *endianness = 0;
176         *fmt = AUD_FMT_S8;
177         break;
178
179     case SND_PCM_FORMAT_U8:
180         *endianness = 0;
181         *fmt = AUD_FMT_U8;
182         break;
183
184     case SND_PCM_FORMAT_S16_LE:
185         *endianness = 0;
186         *fmt = AUD_FMT_S16;
187         break;
188
189     case SND_PCM_FORMAT_U16_LE:
190         *endianness = 0;
191         *fmt = AUD_FMT_U16;
192         break;
193
194     case SND_PCM_FORMAT_S16_BE:
195         *endianness = 1;
196         *fmt = AUD_FMT_S16;
197         break;
198
199     case SND_PCM_FORMAT_U16_BE:
200         *endianness = 1;
201         *fmt = AUD_FMT_U16;
202         break;
203
204     default:
205         dolog ("Unrecognized audio format %d\n", alsafmt);
206         return -1;
207     }
208
209     return 0;
210 }
211
212 #if defined DEBUG_MISMATCHES || defined DEBUG
213 static void alsa_dump_info (struct alsa_params_req *req,
214                             struct alsa_params_obt *obt)
215 {
216     dolog ("parameter | requested value | obtained value\n");
217     dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
218     dolog ("channels  |      %10d |     %10d\n",
219            req->nchannels, obt->nchannels);
220     dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
221     dolog ("============================================\n");
222     dolog ("requested: buffer size %d period size %d\n",
223            req->buffer_size, req->period_size);
224     dolog ("obtained: samples %ld\n", obt->samples);
225 }
226 #endif
227
228 static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
229 {
230     int err;
231     snd_pcm_sw_params_t *sw_params;
232
233     snd_pcm_sw_params_alloca (&sw_params);
234
235     err = snd_pcm_sw_params_current (handle, sw_params);
236     if (err < 0) {
237         dolog ("Could not fully initialize DAC\n");
238         alsa_logerr (err, "Failed to get current software parameters\n");
239         return;
240     }
241
242     err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
243     if (err < 0) {
244         dolog ("Could not fully initialize DAC\n");
245         alsa_logerr (err, "Failed to set software threshold to %ld\n",
246                      threshold);
247         return;
248     }
249
250     err = snd_pcm_sw_params (handle, sw_params);
251     if (err < 0) {
252         dolog ("Could not fully initialize DAC\n");
253         alsa_logerr (err, "Failed to set software parameters\n");
254         return;
255     }
256 }
257
258 static int alsa_open (int in, struct alsa_params_req *req,
259                       struct alsa_params_obt *obt, snd_pcm_t **handlep)
260 {
261     snd_pcm_t *handle;
262     snd_pcm_hw_params_t *hw_params;
263     int err, freq, nchannels;
264     const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
265     unsigned int period_size, buffer_size;
266     snd_pcm_uframes_t obt_buffer_size;
267     const char *typ = in ? "ADC" : "DAC";
268
269     freq = req->freq;
270     period_size = req->period_size;
271     buffer_size = req->buffer_size;
272     nchannels = req->nchannels;
273
274     snd_pcm_hw_params_alloca (&hw_params);
275
276     err = snd_pcm_open (
277         &handle,
278         pcm_name,
279         in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
280         SND_PCM_NONBLOCK
281         );
282     if (err < 0) {
283         alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
284         return -1;
285     }
286
287     err = snd_pcm_hw_params_any (handle, hw_params);
288     if (err < 0) {
289         alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
290         goto err;
291     }
292
293     err = snd_pcm_hw_params_set_access (
294         handle,
295         hw_params,
296         SND_PCM_ACCESS_RW_INTERLEAVED
297         );
298     if (err < 0) {
299         alsa_logerr2 (err, typ, "Failed to set access type\n");
300         goto err;
301     }
302
303     err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
304     if (err < 0) {
305         alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
306         goto err;
307     }
308
309     err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
310     if (err < 0) {
311         alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
312         goto err;
313     }
314
315     err = snd_pcm_hw_params_set_channels_near (
316         handle,
317         hw_params,
318         &nchannels
319         );
320     if (err < 0) {
321         alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
322                       req->nchannels);
323         goto err;
324     }
325
326     if (nchannels != 1 && nchannels != 2) {
327         alsa_logerr2 (err, typ,
328                       "Can not handle obtained number of channels %d\n",
329                       nchannels);
330         goto err;
331     }
332
333     if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) {
334         if (!buffer_size) {
335             buffer_size = DEFAULT_BUFFER_SIZE;
336             period_size= DEFAULT_PERIOD_SIZE;
337         }
338     }
339
340     if (buffer_size) {
341         if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) {
342             if (period_size) {
343                 err = snd_pcm_hw_params_set_period_time_near (
344                     handle,
345                     hw_params,
346                     &period_size,
347                     0
348                     );
349                 if (err < 0) {
350                     alsa_logerr2 (err, typ,
351                                   "Failed to set period time %d\n",
352                                   req->period_size);
353                     goto err;
354                 }
355             }
356
357             err = snd_pcm_hw_params_set_buffer_time_near (
358                 handle,
359                 hw_params,
360                 &buffer_size,
361                 0
362                 );
363
364             if (err < 0) {
365                 alsa_logerr2 (err, typ,
366                               "Failed to set buffer time %d\n",
367                               req->buffer_size);
368                 goto err;
369             }
370         }
371         else {
372             int dir;
373             snd_pcm_uframes_t minval;
374
375             if (period_size) {
376                 minval = period_size;
377                 dir = 0;
378
379                 err = snd_pcm_hw_params_get_period_size_min (
380                     hw_params,
381                     &minval,
382                     &dir
383                     );
384                 if (err < 0) {
385                     alsa_logerr (
386                         err,
387                         "Could not get minmal period size for %s\n",
388                         typ
389                         );
390                 }
391                 else {
392                     if (period_size < minval) {
393                         if ((in && conf.period_size_in_overriden)
394                             || (!in && conf.period_size_out_overriden)) {
395                             dolog ("%s period size(%d) is less "
396                                    "than minmal period size(%ld)\n",
397                                    typ,
398                                    period_size,
399                                    minval);
400                         }
401                         period_size = minval;
402                     }
403                 }
404
405                 err = snd_pcm_hw_params_set_period_size (
406                     handle,
407                     hw_params,
408                     period_size,
409                     0
410                     );
411                 if (err < 0) {
412                     alsa_logerr2 (err, typ, "Failed to set period size %d\n",
413                                   req->period_size);
414                     goto err;
415                 }
416             }
417
418             minval = buffer_size;
419             err = snd_pcm_hw_params_get_buffer_size_min (
420                 hw_params,
421                 &minval
422                 );
423             if (err < 0) {
424                 alsa_logerr (err, "Could not get minmal buffer size for %s\n",
425                              typ);
426             }
427             else {
428                 if (buffer_size < minval) {
429                     if ((in && conf.buffer_size_in_overriden)
430                         || (!in && conf.buffer_size_out_overriden)) {
431                         dolog (
432                             "%s buffer size(%d) is less "
433                             "than minimal buffer size(%ld)\n",
434                             typ,
435                             buffer_size,
436                             minval
437                             );
438                     }
439                     buffer_size = minval;
440                 }
441             }
442
443             err = snd_pcm_hw_params_set_buffer_size (
444                 handle,
445                 hw_params,
446                 buffer_size
447                 );
448             if (err < 0) {
449                 alsa_logerr2 (err, typ, "Failed to set buffer size %d\n",
450                               req->buffer_size);
451                 goto err;
452             }
453         }
454     }
455     else {
456         dolog ("warning: Buffer size is not set\n");
457     }
458
459     err = snd_pcm_hw_params (handle, hw_params);
460     if (err < 0) {
461         alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
462         goto err;
463     }
464
465     err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
466     if (err < 0) {
467         alsa_logerr2 (err, typ, "Failed to get buffer size\n");
468         goto err;
469     }
470
471     err = snd_pcm_prepare (handle);
472     if (err < 0) {
473         alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
474         goto err;
475     }
476
477     obt->can_pause = snd_pcm_hw_params_can_pause (hw_params);
478     if (obt->can_pause < 0) {
479         alsa_logerr (err, "Could not get pause capability for %s\n", typ);
480         obt->can_pause = 0;
481     }
482
483     if (!in && conf.threshold) {
484         snd_pcm_uframes_t threshold;
485         int bytes_per_sec;
486
487         bytes_per_sec = freq
488             << (nchannels == 2)
489             << (req->fmt == AUD_FMT_S16 || req->fmt == AUD_FMT_U16);
490
491         threshold = (conf.threshold * bytes_per_sec) / 1000;
492         alsa_set_threshold (handle, threshold);
493     }
494
495     obt->fmt = req->fmt;
496     obt->nchannels = nchannels;
497     obt->freq = freq;
498     obt->samples = obt_buffer_size;
499     *handlep = handle;
500
501 #if defined DEBUG_MISMATCHES || defined DEBUG
502     if (obt->fmt != req->fmt ||
503         obt->nchannels != req->nchannels ||
504         obt->freq != req->freq) {
505         dolog ("Audio paramters mismatch for %s\n", typ);
506         alsa_dump_info (req, obt);
507     }
508 #endif
509
510 #ifdef DEBUG
511     alsa_dump_info (req, obt);
512 #endif
513     return 0;
514
515  err:
516     alsa_anal_close (&handle);
517     return -1;
518 }
519
520 static int alsa_recover (snd_pcm_t *handle)
521 {
522     int err = snd_pcm_prepare (handle);
523     if (err < 0) {
524         alsa_logerr (err, "Failed to prepare handle %p\n", handle);
525         return -1;
526     }
527     return 0;
528 }
529
530 static int alsa_run_out (HWVoiceOut *hw)
531 {
532     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
533     int rpos, live, decr;
534     int samples;
535     uint8_t *dst;
536     st_sample_t *src;
537     snd_pcm_sframes_t avail;
538
539     live = audio_pcm_hw_get_live_out (hw);
540     if (!live) {
541         return 0;
542     }
543
544     avail = snd_pcm_avail_update (alsa->handle);
545     if (avail < 0) {
546         if (avail == -EPIPE) {
547             if (!alsa_recover (alsa->handle)) {
548                 avail = snd_pcm_avail_update (alsa->handle);
549                 if (avail >= 0) {
550                     goto ok;
551                 }
552             }
553         }
554
555         alsa_logerr (avail, "Could not get amount free space\n");
556         return 0;
557     }
558
559  ok:
560     decr = audio_MIN (live, avail);
561     samples = decr;
562     rpos = hw->rpos;
563     while (samples) {
564         int left_till_end_samples = hw->samples - rpos;
565         int convert_samples = audio_MIN (samples, left_till_end_samples);
566         snd_pcm_sframes_t written;
567
568         src = hw->mix_buf + rpos;
569         dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
570
571         hw->clip (dst, src, convert_samples);
572
573     again:
574         written = snd_pcm_writei (alsa->handle, dst, convert_samples);
575
576         if (written < 0) {
577             switch (written) {
578             case -EPIPE:
579                 if (!alsa_recover (alsa->handle)) {
580                     goto again;
581                 }
582                 dolog (
583                     "Failed to write %d frames to %p, handle %p not prepared\n",
584                     convert_samples,
585                     dst,
586                     alsa->handle
587                     );
588                 goto exit;
589
590             case -EAGAIN:
591                 goto again;
592
593             default:
594                 alsa_logerr (written, "Failed to write %d frames to %p\n",
595                              convert_samples, dst);
596                 goto exit;
597             }
598         }
599
600         mixeng_clear (src, written);
601         rpos = (rpos + written) % hw->samples;
602         samples -= written;
603     }
604
605  exit:
606     hw->rpos = rpos;
607     return decr;
608 }
609
610 static void alsa_fini_out (HWVoiceOut *hw)
611 {
612     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
613
614     ldebug ("alsa_fini\n");
615     alsa_anal_close (&alsa->handle);
616
617     if (alsa->pcm_buf) {
618         qemu_free (alsa->pcm_buf);
619         alsa->pcm_buf = NULL;
620     }
621 }
622
623 static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
624 {
625     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
626     struct alsa_params_req req;
627     struct alsa_params_obt obt;
628     audfmt_e effective_fmt;
629     int endianness;
630     int err;
631     snd_pcm_t *handle;
632     audsettings_t obt_as;
633
634     req.fmt = aud_to_alsafmt (as->fmt);
635     req.freq = as->freq;
636     req.nchannels = as->nchannels;
637     req.period_size = conf.period_size_out;
638     req.buffer_size = conf.buffer_size_out;
639
640     if (alsa_open (0, &req, &obt, &handle)) {
641         return -1;
642     }
643
644     err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
645     if (err) {
646         alsa_anal_close (&handle);
647         return -1;
648     }
649
650     obt_as.freq = obt.freq;
651     obt_as.nchannels = obt.nchannels;
652     obt_as.fmt = effective_fmt;
653
654     audio_pcm_init_info (
655         &hw->info,
656         &obt_as,
657         audio_need_to_swap_endian (endianness)
658         );
659     alsa->can_pause = obt.can_pause;
660     hw->samples = obt.samples;
661
662     alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
663     if (!alsa->pcm_buf) {
664         dolog ("Could not allocate DAC buffer (%d bytes)\n",
665                hw->samples << hw->info.shift);
666         alsa_anal_close (&handle);
667         return -1;
668     }
669
670     alsa->handle = handle;
671     alsa->was_enabled = 0;
672     return 0;
673 }
674
675 static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
676 {
677     int err;
678     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
679
680     switch (cmd) {
681     case VOICE_ENABLE:
682         ldebug ("enabling voice\n");
683         audio_pcm_info_clear_buf (&hw->info, alsa->pcm_buf, hw->samples);
684         if (alsa->can_pause) {
685             /* Why this was_enabled madness is needed at all?? */
686             if (alsa->was_enabled) {
687                 err = snd_pcm_pause (alsa->handle, 0);
688                 if (err < 0) {
689                     alsa_logerr (err, "Failed to resume playing\n");
690                     /* not fatal really */
691                 }
692             }
693             else {
694                 alsa->was_enabled = 1;
695             }
696         }
697         break;
698
699     case VOICE_DISABLE:
700         ldebug ("disabling voice\n");
701         if (alsa->can_pause) {
702             err = snd_pcm_pause (alsa->handle, 1);
703             if (err < 0) {
704                 alsa_logerr (err, "Failed to stop playing\n");
705                 /* not fatal really */
706             }
707         }
708         break;
709     }
710     return 0;
711 }
712
713 static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
714 {
715     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
716     struct alsa_params_req req;
717     struct alsa_params_obt obt;
718     int endianness;
719     int err;
720     audfmt_e effective_fmt;
721     snd_pcm_t *handle;
722     audsettings_t obt_as;
723
724     req.fmt = aud_to_alsafmt (as->fmt);
725     req.freq = as->freq;
726     req.nchannels = as->nchannels;
727     req.period_size = conf.period_size_in;
728     req.buffer_size = conf.buffer_size_in;
729
730     if (alsa_open (1, &req, &obt, &handle)) {
731         return -1;
732     }
733
734     err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
735     if (err) {
736         alsa_anal_close (&handle);
737         return -1;
738     }
739
740     obt_as.freq = obt.freq;
741     obt_as.nchannels = obt.nchannels;
742     obt_as.fmt = effective_fmt;
743
744     audio_pcm_init_info (
745         &hw->info,
746         &obt_as,
747         audio_need_to_swap_endian (endianness)
748         );
749     alsa->can_pause = obt.can_pause;
750     hw->samples = obt.samples;
751
752     alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
753     if (!alsa->pcm_buf) {
754         dolog ("Could not allocate ADC buffer (%d bytes)\n",
755                hw->samples << hw->info.shift);
756         alsa_anal_close (&handle);
757         return -1;
758     }
759
760     alsa->handle = handle;
761     return 0;
762 }
763
764 static void alsa_fini_in (HWVoiceIn *hw)
765 {
766     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
767
768     alsa_anal_close (&alsa->handle);
769
770     if (alsa->pcm_buf) {
771         qemu_free (alsa->pcm_buf);
772         alsa->pcm_buf = NULL;
773     }
774 }
775
776 static int alsa_run_in (HWVoiceIn *hw)
777 {
778     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
779     int hwshift = hw->info.shift;
780     int i;
781     int live = audio_pcm_hw_get_live_in (hw);
782     int dead = hw->samples - live;
783     struct {
784         int add;
785         int len;
786     } bufs[2] = {
787         { hw->wpos, 0 },
788         { 0, 0 }
789     };
790
791     snd_pcm_uframes_t read_samples = 0;
792
793     if (!dead) {
794         return 0;
795     }
796
797     if (hw->wpos + dead > hw->samples) {
798         bufs[0].len = (hw->samples - hw->wpos);
799         bufs[1].len = (dead - (hw->samples - hw->wpos));
800     }
801     else {
802         bufs[0].len = dead;
803     }
804
805
806     for (i = 0; i < 2; ++i) {
807         void *src;
808         st_sample_t *dst;
809         snd_pcm_sframes_t nread;
810         snd_pcm_uframes_t len;
811
812         len = bufs[i].len;
813
814         src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
815         dst = hw->conv_buf + bufs[i].add;
816
817         while (len) {
818             nread = snd_pcm_readi (alsa->handle, src, len);
819
820             if (nread < 0) {
821                 switch (nread) {
822                 case -EPIPE:
823                     if (!alsa_recover (alsa->handle)) {
824                         continue;
825                     }
826                     dolog (
827                         "Failed to read %ld frames from %p, "
828                         "handle %p not prepared\n",
829                         len,
830                         src,
831                         alsa->handle
832                         );
833                     goto exit;
834
835                 case -EAGAIN:
836                     continue;
837
838                 default:
839                     alsa_logerr (
840                         nread,
841                         "Failed to read %ld frames from %p\n",
842                         len,
843                         src
844                         );
845                     goto exit;
846                 }
847             }
848
849             hw->conv (dst, src, nread, &nominal_volume);
850
851             src = advance (src, nread << hwshift);
852             dst += nread;
853
854             read_samples += nread;
855             len -= nread;
856         }
857     }
858
859  exit:
860     hw->wpos = (hw->wpos + read_samples) % hw->samples;
861     return read_samples;
862 }
863
864 static int alsa_read (SWVoiceIn *sw, void *buf, int size)
865 {
866     return audio_pcm_sw_read (sw, buf, size);
867 }
868
869 static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
870 {
871     (void) hw;
872     (void) cmd;
873     return 0;
874 }
875
876 static void *alsa_audio_init (void)
877 {
878     return &conf;
879 }
880
881 static void alsa_audio_fini (void *opaque)
882 {
883     (void) opaque;
884 }
885
886 static struct audio_option alsa_options[] = {
887     {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
888      "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
889     {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
890      "DAC period size", &conf.period_size_out_overriden, 0},
891     {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
892      "DAC buffer size", &conf.buffer_size_out_overriden, 0},
893
894     {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
895      "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
896     {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
897      "ADC period size", &conf.period_size_in_overriden, 0},
898     {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
899      "ADC buffer size", &conf.buffer_size_in_overriden, 0},
900
901     {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
902      "(undocumented)", NULL, 0},
903
904     {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
905      "DAC device name (for instance dmix)", NULL, 0},
906
907     {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
908      "ADC device name", NULL, 0},
909     {NULL, 0, NULL, NULL, NULL, 0}
910 };
911
912 static struct audio_pcm_ops alsa_pcm_ops = {
913     alsa_init_out,
914     alsa_fini_out,
915     alsa_run_out,
916     alsa_write,
917     alsa_ctl_out,
918
919     alsa_init_in,
920     alsa_fini_in,
921     alsa_run_in,
922     alsa_read,
923     alsa_ctl_in
924 };
925
926 struct audio_driver alsa_audio_driver = {
927     INIT_FIELD (name           = ) "alsa",
928     INIT_FIELD (descr          = ) "ALSA http://www.alsa-project.org",
929     INIT_FIELD (options        = ) alsa_options,
930     INIT_FIELD (init           = ) alsa_audio_init,
931     INIT_FIELD (fini           = ) alsa_audio_fini,
932     INIT_FIELD (pcm_ops        = ) &alsa_pcm_ops,
933     INIT_FIELD (can_be_default = ) 1,
934     INIT_FIELD (max_voices_out = ) INT_MAX,
935     INIT_FIELD (max_voices_in  = ) INT_MAX,
936     INIT_FIELD (voice_size_out = ) sizeof (ALSAVoiceOut),
937     INIT_FIELD (voice_size_in  = ) sizeof (ALSAVoiceIn)
938 };