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