Statistics
| Branch: | Revision:

root / audio / alsaaudio.c @ 23fb600b

History | View | Annotate | Download (23.9 kB)

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 "qemu-common.h"
26
#include "audio.h"
27

    
28
#define AUDIO_CAP "alsa"
29
#include "audio_int.h"
30

    
31
typedef struct ALSAVoiceOut {
32
    HWVoiceOut hw;
33
    void *pcm_buf;
34
    snd_pcm_t *handle;
35
} ALSAVoiceOut;
36

    
37
typedef struct ALSAVoiceIn {
38
    HWVoiceIn hw;
39
    snd_pcm_t *handle;
40
    void *pcm_buf;
41
} ALSAVoiceIn;
42

    
43
static struct {
44
    int size_in_usec_in;
45
    int size_in_usec_out;
46
    const char *pcm_name_in;
47
    const char *pcm_name_out;
48
    unsigned int buffer_size_in;
49
    unsigned int period_size_in;
50
    unsigned int buffer_size_out;
51
    unsigned int period_size_out;
52
    unsigned int threshold;
53

    
54
    int buffer_size_in_overridden;
55
    int period_size_in_overridden;
56

    
57
    int buffer_size_out_overridden;
58
    int period_size_out_overridden;
59
    int verbose;
60
} conf = {
61
    .pcm_name_out = "default",
62
    .pcm_name_in = "default",
63
};
64

    
65
struct alsa_params_req {
66
    int freq;
67
    snd_pcm_format_t fmt;
68
    int nchannels;
69
    int size_in_usec;
70
    unsigned int buffer_size;
71
    unsigned int period_size;
72
};
73

    
74
struct alsa_params_obt {
75
    int freq;
76
    audfmt_e fmt;
77
    int endianness;
78
    int nchannels;
79
    snd_pcm_uframes_t samples;
80
};
81

    
82
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
83
{
84
    va_list ap;
85

    
86
    va_start (ap, fmt);
87
    AUD_vlog (AUDIO_CAP, fmt, ap);
88
    va_end (ap);
89

    
90
    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
91
}
92

    
93
static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
94
    int err,
95
    const char *typ,
96
    const char *fmt,
97
    ...
98
    )
99
{
100
    va_list ap;
101

    
102
    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
103

    
104
    va_start (ap, fmt);
105
    AUD_vlog (AUDIO_CAP, fmt, ap);
106
    va_end (ap);
107

    
108
    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
109
}
110

    
111
static void alsa_anal_close (snd_pcm_t **handlep)
112
{
113
    int err = snd_pcm_close (*handlep);
114
    if (err) {
115
        alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
116
    }
117
    *handlep = NULL;
118
}
119

    
120
static int alsa_write (SWVoiceOut *sw, void *buf, int len)
121
{
122
    return audio_pcm_sw_write (sw, buf, len);
123
}
124

    
125
static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
126
{
127
    switch (fmt) {
128
    case AUD_FMT_S8:
129
        return SND_PCM_FORMAT_S8;
130

    
131
    case AUD_FMT_U8:
132
        return SND_PCM_FORMAT_U8;
133

    
134
    case AUD_FMT_S16:
135
        return SND_PCM_FORMAT_S16_LE;
136

    
137
    case AUD_FMT_U16:
138
        return SND_PCM_FORMAT_U16_LE;
139

    
140
    case AUD_FMT_S32:
141
        return SND_PCM_FORMAT_S32_LE;
142

    
143
    case AUD_FMT_U32:
144
        return SND_PCM_FORMAT_U32_LE;
145

    
146
    default:
147
        dolog ("Internal logic error: Bad audio format %d\n", fmt);
148
#ifdef DEBUG_AUDIO
149
        abort ();
150
#endif
151
        return SND_PCM_FORMAT_U8;
152
    }
153
}
154

    
155
static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt,
156
                           int *endianness)
157
{
158
    switch (alsafmt) {
159
    case SND_PCM_FORMAT_S8:
160
        *endianness = 0;
161
        *fmt = AUD_FMT_S8;
162
        break;
163

    
164
    case SND_PCM_FORMAT_U8:
165
        *endianness = 0;
166
        *fmt = AUD_FMT_U8;
167
        break;
168

    
169
    case SND_PCM_FORMAT_S16_LE:
170
        *endianness = 0;
171
        *fmt = AUD_FMT_S16;
172
        break;
173

    
174
    case SND_PCM_FORMAT_U16_LE:
175
        *endianness = 0;
176
        *fmt = AUD_FMT_U16;
177
        break;
178

    
179
    case SND_PCM_FORMAT_S16_BE:
180
        *endianness = 1;
181
        *fmt = AUD_FMT_S16;
182
        break;
183

    
184
    case SND_PCM_FORMAT_U16_BE:
185
        *endianness = 1;
186
        *fmt = AUD_FMT_U16;
187
        break;
188

    
189
    case SND_PCM_FORMAT_S32_LE:
190
        *endianness = 0;
191
        *fmt = AUD_FMT_S32;
192
        break;
193

    
194
    case SND_PCM_FORMAT_U32_LE:
195
        *endianness = 0;
196
        *fmt = AUD_FMT_U32;
197
        break;
198

    
199
    case SND_PCM_FORMAT_S32_BE:
200
        *endianness = 1;
201
        *fmt = AUD_FMT_S32;
202
        break;
203

    
204
    case SND_PCM_FORMAT_U32_BE:
205
        *endianness = 1;
206
        *fmt = AUD_FMT_U32;
207
        break;
208

    
209
    default:
210
        dolog ("Unrecognized audio format %d\n", alsafmt);
211
        return -1;
212
    }
213

    
214
    return 0;
215
}
216

    
217
static void alsa_dump_info (struct alsa_params_req *req,
218
                            struct alsa_params_obt *obt)
219
{
220
    dolog ("parameter | requested value | obtained value\n");
221
    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
222
    dolog ("channels  |      %10d |     %10d\n",
223
           req->nchannels, obt->nchannels);
224
    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
225
    dolog ("============================================\n");
226
    dolog ("requested: buffer size %d period size %d\n",
227
           req->buffer_size, req->period_size);
228
    dolog ("obtained: samples %ld\n", obt->samples);
229
}
230

    
231
static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
232
{
233
    int err;
234
    snd_pcm_sw_params_t *sw_params;
235

    
236
    snd_pcm_sw_params_alloca (&sw_params);
237

    
238
    err = snd_pcm_sw_params_current (handle, sw_params);
239
    if (err < 0) {
240
        dolog ("Could not fully initialize DAC\n");
241
        alsa_logerr (err, "Failed to get current software parameters\n");
242
        return;
243
    }
244

    
245
    err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
246
    if (err < 0) {
247
        dolog ("Could not fully initialize DAC\n");
248
        alsa_logerr (err, "Failed to set software threshold to %ld\n",
249
                     threshold);
250
        return;
251
    }
252

    
253
    err = snd_pcm_sw_params (handle, sw_params);
254
    if (err < 0) {
255
        dolog ("Could not fully initialize DAC\n");
256
        alsa_logerr (err, "Failed to set software parameters\n");
257
        return;
258
    }
259
}
260

    
261
static int alsa_open (int in, struct alsa_params_req *req,
262
                      struct alsa_params_obt *obt, snd_pcm_t **handlep)
263
{
264
    snd_pcm_t *handle;
265
    snd_pcm_hw_params_t *hw_params;
266
    int err;
267
    int size_in_usec;
268
    unsigned int freq, nchannels;
269
    const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
270
    snd_pcm_uframes_t obt_buffer_size;
271
    const char *typ = in ? "ADC" : "DAC";
272
    snd_pcm_format_t obtfmt;
273

    
274
    freq = req->freq;
275
    nchannels = req->nchannels;
276
    size_in_usec = req->size_in_usec;
277

    
278
    snd_pcm_hw_params_alloca (&hw_params);
279

    
280
    err = snd_pcm_open (
281
        &handle,
282
        pcm_name,
283
        in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
284
        SND_PCM_NONBLOCK
285
        );
286
    if (err < 0) {
287
        alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
288
        return -1;
289
    }
290

    
291
    err = snd_pcm_hw_params_any (handle, hw_params);
292
    if (err < 0) {
293
        alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
294
        goto err;
295
    }
296

    
297
    err = snd_pcm_hw_params_set_access (
298
        handle,
299
        hw_params,
300
        SND_PCM_ACCESS_RW_INTERLEAVED
301
        );
302
    if (err < 0) {
303
        alsa_logerr2 (err, typ, "Failed to set access type\n");
304
        goto err;
305
    }
306

    
307
    err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
308
    if (err < 0 && conf.verbose) {
309
        alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
310
    }
311

    
312
    err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
313
    if (err < 0) {
314
        alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
315
        goto err;
316
    }
317

    
318
    err = snd_pcm_hw_params_set_channels_near (
319
        handle,
320
        hw_params,
321
        &nchannels
322
        );
323
    if (err < 0) {
324
        alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
325
                      req->nchannels);
326
        goto err;
327
    }
328

    
329
    if (nchannels != 1 && nchannels != 2) {
330
        alsa_logerr2 (err, typ,
331
                      "Can not handle obtained number of channels %d\n",
332
                      nchannels);
333
        goto err;
334
    }
335

    
336
    if (req->buffer_size) {
337
        unsigned long obt;
338

    
339
        if (size_in_usec) {
340
            int dir = 0;
341
            unsigned int btime = req->buffer_size;
342

    
343
            err = snd_pcm_hw_params_set_buffer_time_near (
344
                handle,
345
                hw_params,
346
                &btime,
347
                &dir
348
                );
349
            obt = btime;
350
        }
351
        else {
352
            snd_pcm_uframes_t bsize = req->buffer_size;
353

    
354
            err = snd_pcm_hw_params_set_buffer_size_near (
355
                handle,
356
                hw_params,
357
                &bsize
358
                );
359
            obt = bsize;
360
        }
361
        if (err < 0) {
362
            alsa_logerr2 (err, typ, "Failed to set buffer %s to %d\n",
363
                          size_in_usec ? "time" : "size", req->buffer_size);
364
            goto err;
365
        }
366

    
367
        if (obt - req->buffer_size)
368
            dolog ("Requested buffer %s %u was rejected, using %lu\n",
369
                   size_in_usec ? "time" : "size", req->buffer_size, obt);
370
    }
371

    
372
    if (req->period_size) {
373
        unsigned long obt;
374

    
375
        if (size_in_usec) {
376
            int dir = 0;
377
            unsigned int ptime = req->period_size;
378

    
379
            err = snd_pcm_hw_params_set_period_time_near (
380
                handle,
381
                hw_params,
382
                &ptime,
383
                &dir
384
                );
385
            obt = ptime;
386
        }
387
        else {
388
            snd_pcm_uframes_t psize = req->period_size;
389

    
390
            err = snd_pcm_hw_params_set_buffer_size_near (
391
                handle,
392
                hw_params,
393
                &psize
394
                );
395
            obt = psize;
396
        }
397

    
398
        if (err < 0) {
399
            alsa_logerr2 (err, typ, "Failed to set period %s to %d\n",
400
                          size_in_usec ? "time" : "size", req->period_size);
401
            goto err;
402
        }
403

    
404
        if (obt - req->period_size)
405
            dolog ("Requested period %s %u was rejected, using %lu\n",
406
                   size_in_usec ? "time" : "size", req->period_size, obt);
407
    }
408

    
409
    err = snd_pcm_hw_params (handle, hw_params);
410
    if (err < 0) {
411
        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
412
        goto err;
413
    }
414

    
415
    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
416
    if (err < 0) {
417
        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
418
        goto err;
419
    }
420

    
421
    err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
422
    if (err < 0) {
423
        alsa_logerr2 (err, typ, "Failed to get format\n");
424
        goto err;
425
    }
426

    
427
    if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
428
        dolog ("Invalid format was returned %d\n", obtfmt);
429
        goto err;
430
    }
431

    
432
    err = snd_pcm_prepare (handle);
433
    if (err < 0) {
434
        alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
435
        goto err;
436
    }
437

    
438
    if (!in && conf.threshold) {
439
        snd_pcm_uframes_t threshold;
440
        int bytes_per_sec;
441

    
442
        bytes_per_sec = freq << (nchannels == 2);
443

    
444
        switch (obt->fmt) {
445
        case AUD_FMT_S8:
446
        case AUD_FMT_U8:
447
            break;
448

    
449
        case AUD_FMT_S16:
450
        case AUD_FMT_U16:
451
            bytes_per_sec <<= 1;
452
            break;
453

    
454
        case AUD_FMT_S32:
455
        case AUD_FMT_U32:
456
            bytes_per_sec <<= 2;
457
            break;
458
        }
459

    
460
        threshold = (conf.threshold * bytes_per_sec) / 1000;
461
        alsa_set_threshold (handle, threshold);
462
    }
463

    
464
    obt->nchannels = nchannels;
465
    obt->freq = freq;
466
    obt->samples = obt_buffer_size;
467

    
468
    *handlep = handle;
469

    
470
    if (conf.verbose &&
471
        (obt->fmt != req->fmt ||
472
         obt->nchannels != req->nchannels ||
473
         obt->freq != req->freq)) {
474
        dolog ("Audio paramters for %s\n", typ);
475
        alsa_dump_info (req, obt);
476
    }
477

    
478
#ifdef DEBUG
479
    alsa_dump_info (req, obt);
480
#endif
481
    return 0;
482

    
483
 err:
484
    alsa_anal_close (&handle);
485
    return -1;
486
}
487

    
488
static int alsa_recover (snd_pcm_t *handle)
489
{
490
    int err = snd_pcm_prepare (handle);
491
    if (err < 0) {
492
        alsa_logerr (err, "Failed to prepare handle %p\n", handle);
493
        return -1;
494
    }
495
    return 0;
496
}
497

    
498
static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
499
{
500
    snd_pcm_sframes_t avail;
501

    
502
    avail = snd_pcm_avail_update (handle);
503
    if (avail < 0) {
504
        if (avail == -EPIPE) {
505
            if (!alsa_recover (handle)) {
506
                avail = snd_pcm_avail_update (handle);
507
            }
508
        }
509

    
510
        if (avail < 0) {
511
            alsa_logerr (avail,
512
                         "Could not obtain number of available frames\n");
513
            return -1;
514
        }
515
    }
516

    
517
    return avail;
518
}
519

    
520
static int alsa_run_out (HWVoiceOut *hw)
521
{
522
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
523
    int rpos, live, decr;
524
    int samples;
525
    uint8_t *dst;
526
    st_sample_t *src;
527
    snd_pcm_sframes_t avail;
528

    
529
    live = audio_pcm_hw_get_live_out (hw);
530
    if (!live) {
531
        return 0;
532
    }
533

    
534
    avail = alsa_get_avail (alsa->handle);
535
    if (avail < 0) {
536
        dolog ("Could not get number of available playback frames\n");
537
        return 0;
538
    }
539

    
540
    decr = audio_MIN (live, avail);
541
    samples = decr;
542
    rpos = hw->rpos;
543
    while (samples) {
544
        int left_till_end_samples = hw->samples - rpos;
545
        int len = audio_MIN (samples, left_till_end_samples);
546
        snd_pcm_sframes_t written;
547

    
548
        src = hw->mix_buf + rpos;
549
        dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
550

    
551
        hw->clip (dst, src, len);
552

    
553
        while (len) {
554
            written = snd_pcm_writei (alsa->handle, dst, len);
555

    
556
            if (written <= 0) {
557
                switch (written) {
558
                case 0:
559
                    if (conf.verbose) {
560
                        dolog ("Failed to write %d frames (wrote zero)\n", len);
561
                    }
562
                    goto exit;
563

    
564
                case -EPIPE:
565
                    if (alsa_recover (alsa->handle)) {
566
                        alsa_logerr (written, "Failed to write %d frames\n",
567
                                     len);
568
                        goto exit;
569
                    }
570
                    if (conf.verbose) {
571
                        dolog ("Recovering from playback xrun\n");
572
                    }
573
                    continue;
574

    
575
                case -EAGAIN:
576
                    goto exit;
577

    
578
                default:
579
                    alsa_logerr (written, "Failed to write %d frames to %p\n",
580
                                 len, dst);
581
                    goto exit;
582
                }
583
            }
584

    
585
            rpos = (rpos + written) % hw->samples;
586
            samples -= written;
587
            len -= written;
588
            dst = advance (dst, written << hw->info.shift);
589
            src += written;
590
        }
591
    }
592

    
593
 exit:
594
    hw->rpos = rpos;
595
    return decr;
596
}
597

    
598
static void alsa_fini_out (HWVoiceOut *hw)
599
{
600
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
601

    
602
    ldebug ("alsa_fini\n");
603
    alsa_anal_close (&alsa->handle);
604

    
605
    if (alsa->pcm_buf) {
606
        qemu_free (alsa->pcm_buf);
607
        alsa->pcm_buf = NULL;
608
    }
609
}
610

    
611
static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
612
{
613
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
614
    struct alsa_params_req req;
615
    struct alsa_params_obt obt;
616
    snd_pcm_t *handle;
617
    audsettings_t obt_as;
618

    
619
    req.fmt = aud_to_alsafmt (as->fmt);
620
    req.freq = as->freq;
621
    req.nchannels = as->nchannels;
622
    req.period_size = conf.period_size_out;
623
    req.buffer_size = conf.buffer_size_out;
624
    req.size_in_usec = conf.size_in_usec_out;
625

    
626
    if (alsa_open (0, &req, &obt, &handle)) {
627
        return -1;
628
    }
629

    
630
    obt_as.freq = obt.freq;
631
    obt_as.nchannels = obt.nchannels;
632
    obt_as.fmt = obt.fmt;
633
    obt_as.endianness = obt.endianness;
634

    
635
    audio_pcm_init_info (&hw->info, &obt_as);
636
    hw->samples = obt.samples;
637

    
638
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
639
    if (!alsa->pcm_buf) {
640
        dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n",
641
               hw->samples, 1 << hw->info.shift);
642
        alsa_anal_close (&handle);
643
        return -1;
644
    }
645

    
646
    alsa->handle = handle;
647
    return 0;
648
}
649

    
650
static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
651
{
652
    int err;
653

    
654
    if (pause) {
655
        err = snd_pcm_drop (handle);
656
        if (err < 0) {
657
            alsa_logerr (err, "Could not stop %s\n", typ);
658
            return -1;
659
        }
660
    }
661
    else {
662
        err = snd_pcm_prepare (handle);
663
        if (err < 0) {
664
            alsa_logerr (err, "Could not prepare handle for %s\n", typ);
665
            return -1;
666
        }
667
    }
668

    
669
    return 0;
670
}
671

    
672
static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
673
{
674
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
675

    
676
    switch (cmd) {
677
    case VOICE_ENABLE:
678
        ldebug ("enabling voice\n");
679
        return alsa_voice_ctl (alsa->handle, "playback", 0);
680

    
681
    case VOICE_DISABLE:
682
        ldebug ("disabling voice\n");
683
        return alsa_voice_ctl (alsa->handle, "playback", 1);
684
    }
685

    
686
    return -1;
687
}
688

    
689
static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
690
{
691
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
692
    struct alsa_params_req req;
693
    struct alsa_params_obt obt;
694
    snd_pcm_t *handle;
695
    audsettings_t obt_as;
696

    
697
    req.fmt = aud_to_alsafmt (as->fmt);
698
    req.freq = as->freq;
699
    req.nchannels = as->nchannels;
700
    req.period_size = conf.period_size_in;
701
    req.buffer_size = conf.buffer_size_in;
702
    req.size_in_usec = conf.size_in_usec_in;
703

    
704
    if (alsa_open (1, &req, &obt, &handle)) {
705
        return -1;
706
    }
707

    
708
    obt_as.freq = obt.freq;
709
    obt_as.nchannels = obt.nchannels;
710
    obt_as.fmt = obt.fmt;
711
    obt_as.endianness = obt.endianness;
712

    
713
    audio_pcm_init_info (&hw->info, &obt_as);
714
    hw->samples = obt.samples;
715

    
716
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
717
    if (!alsa->pcm_buf) {
718
        dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
719
               hw->samples, 1 << hw->info.shift);
720
        alsa_anal_close (&handle);
721
        return -1;
722
    }
723

    
724
    alsa->handle = handle;
725
    return 0;
726
}
727

    
728
static void alsa_fini_in (HWVoiceIn *hw)
729
{
730
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
731

    
732
    alsa_anal_close (&alsa->handle);
733

    
734
    if (alsa->pcm_buf) {
735
        qemu_free (alsa->pcm_buf);
736
        alsa->pcm_buf = NULL;
737
    }
738
}
739

    
740
static int alsa_run_in (HWVoiceIn *hw)
741
{
742
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
743
    int hwshift = hw->info.shift;
744
    int i;
745
    int live = audio_pcm_hw_get_live_in (hw);
746
    int dead = hw->samples - live;
747
    int decr;
748
    struct {
749
        int add;
750
        int len;
751
    } bufs[2] = {
752
        { hw->wpos, 0 },
753
        { 0, 0 }
754
    };
755
    snd_pcm_sframes_t avail;
756
    snd_pcm_uframes_t read_samples = 0;
757

    
758
    if (!dead) {
759
        return 0;
760
    }
761

    
762
    avail = alsa_get_avail (alsa->handle);
763
    if (avail < 0) {
764
        dolog ("Could not get number of captured frames\n");
765
        return 0;
766
    }
767

    
768
    if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) {
769
        avail = hw->samples;
770
    }
771

    
772
    decr = audio_MIN (dead, avail);
773
    if (!decr) {
774
        return 0;
775
    }
776

    
777
    if (hw->wpos + decr > hw->samples) {
778
        bufs[0].len = (hw->samples - hw->wpos);
779
        bufs[1].len = (decr - (hw->samples - hw->wpos));
780
    }
781
    else {
782
        bufs[0].len = decr;
783
    }
784

    
785
    for (i = 0; i < 2; ++i) {
786
        void *src;
787
        st_sample_t *dst;
788
        snd_pcm_sframes_t nread;
789
        snd_pcm_uframes_t len;
790

    
791
        len = bufs[i].len;
792

    
793
        src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
794
        dst = hw->conv_buf + bufs[i].add;
795

    
796
        while (len) {
797
            nread = snd_pcm_readi (alsa->handle, src, len);
798

    
799
            if (nread <= 0) {
800
                switch (nread) {
801
                case 0:
802
                    if (conf.verbose) {
803
                        dolog ("Failed to read %ld frames (read zero)\n", len);
804
                    }
805
                    goto exit;
806

    
807
                case -EPIPE:
808
                    if (alsa_recover (alsa->handle)) {
809
                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
810
                        goto exit;
811
                    }
812
                    if (conf.verbose) {
813
                        dolog ("Recovering from capture xrun\n");
814
                    }
815
                    continue;
816

    
817
                case -EAGAIN:
818
                    goto exit;
819

    
820
                default:
821
                    alsa_logerr (
822
                        nread,
823
                        "Failed to read %ld frames from %p\n",
824
                        len,
825
                        src
826
                        );
827
                    goto exit;
828
                }
829
            }
830

    
831
            hw->conv (dst, src, nread, &nominal_volume);
832

    
833
            src = advance (src, nread << hwshift);
834
            dst += nread;
835

    
836
            read_samples += nread;
837
            len -= nread;
838
        }
839
    }
840

    
841
 exit:
842
    hw->wpos = (hw->wpos + read_samples) % hw->samples;
843
    return read_samples;
844
}
845

    
846
static int alsa_read (SWVoiceIn *sw, void *buf, int size)
847
{
848
    return audio_pcm_sw_read (sw, buf, size);
849
}
850

    
851
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
852
{
853
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
854

    
855
    switch (cmd) {
856
    case VOICE_ENABLE:
857
        ldebug ("enabling voice\n");
858
        return alsa_voice_ctl (alsa->handle, "capture", 0);
859

    
860
    case VOICE_DISABLE:
861
        ldebug ("disabling voice\n");
862
        return alsa_voice_ctl (alsa->handle, "capture", 1);
863
    }
864

    
865
    return -1;
866
}
867

    
868
static void *alsa_audio_init (void)
869
{
870
    return &conf;
871
}
872

    
873
static void alsa_audio_fini (void *opaque)
874
{
875
    (void) opaque;
876
}
877

    
878
static struct audio_option alsa_options[] = {
879
    {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
880
     "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
881
    {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
882
     "DAC period size (0 to go with system default)",
883
     &conf.period_size_out_overridden, 0},
884
    {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
885
     "DAC buffer size (0 to go with system default)",
886
     &conf.buffer_size_out_overridden, 0},
887

    
888
    {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
889
     "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
890
    {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
891
     "ADC period size (0 to go with system default)",
892
     &conf.period_size_in_overridden, 0},
893
    {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
894
     "ADC buffer size (0 to go with system default)",
895
     &conf.buffer_size_in_overridden, 0},
896

    
897
    {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
898
     "(undocumented)", NULL, 0},
899

    
900
    {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
901
     "DAC device name (for instance dmix)", NULL, 0},
902

    
903
    {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
904
     "ADC device name", NULL, 0},
905

    
906
    {"VERBOSE", AUD_OPT_BOOL, &conf.verbose,
907
     "Behave in a more verbose way", NULL, 0},
908

    
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
};