Statistics
| Branch: | Revision:

root / audio / alsaaudio.c @ 97f155dd

History | View | Annotate | Download (24.3 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
    .buffer_size_out = 1024,
62
    .pcm_name_out = "default",
63
    .pcm_name_in = "default",
64
};
65

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

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

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

    
88
    va_start (ap, fmt);
89
    AUD_vlog (AUDIO_CAP, fmt, ap);
90
    va_end (ap);
91

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

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

    
104
    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
105

    
106
    va_start (ap, fmt);
107
    AUD_vlog (AUDIO_CAP, fmt, ap);
108
    va_end (ap);
109

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

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

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

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

    
133
    case AUD_FMT_U8:
134
        return SND_PCM_FORMAT_U8;
135

    
136
    case AUD_FMT_S16:
137
        return SND_PCM_FORMAT_S16_LE;
138

    
139
    case AUD_FMT_U16:
140
        return SND_PCM_FORMAT_U16_LE;
141

    
142
    case AUD_FMT_S32:
143
        return SND_PCM_FORMAT_S32_LE;
144

    
145
    case AUD_FMT_U32:
146
        return SND_PCM_FORMAT_U32_LE;
147

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

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

    
166
    case SND_PCM_FORMAT_U8:
167
        *endianness = 0;
168
        *fmt = AUD_FMT_U8;
169
        break;
170

    
171
    case SND_PCM_FORMAT_S16_LE:
172
        *endianness = 0;
173
        *fmt = AUD_FMT_S16;
174
        break;
175

    
176
    case SND_PCM_FORMAT_U16_LE:
177
        *endianness = 0;
178
        *fmt = AUD_FMT_U16;
179
        break;
180

    
181
    case SND_PCM_FORMAT_S16_BE:
182
        *endianness = 1;
183
        *fmt = AUD_FMT_S16;
184
        break;
185

    
186
    case SND_PCM_FORMAT_U16_BE:
187
        *endianness = 1;
188
        *fmt = AUD_FMT_U16;
189
        break;
190

    
191
    case SND_PCM_FORMAT_S32_LE:
192
        *endianness = 0;
193
        *fmt = AUD_FMT_S32;
194
        break;
195

    
196
    case SND_PCM_FORMAT_U32_LE:
197
        *endianness = 0;
198
        *fmt = AUD_FMT_U32;
199
        break;
200

    
201
    case SND_PCM_FORMAT_S32_BE:
202
        *endianness = 1;
203
        *fmt = AUD_FMT_S32;
204
        break;
205

    
206
    case SND_PCM_FORMAT_U32_BE:
207
        *endianness = 1;
208
        *fmt = AUD_FMT_U32;
209
        break;
210

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

    
216
    return 0;
217
}
218

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

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

    
238
    snd_pcm_sw_params_alloca (&sw_params);
239

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

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

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

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

    
276
    freq = req->freq;
277
    nchannels = req->nchannels;
278
    size_in_usec = req->size_in_usec;
279

    
280
    snd_pcm_hw_params_alloca (&hw_params);
281

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

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

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

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

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

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

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

    
338
    if (req->buffer_size) {
339
        unsigned long obt;
340

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

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

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

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

    
374
    if (req->period_size) {
375
        unsigned long obt;
376

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

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

    
393
            err = snd_pcm_hw_params_set_period_size_near (
394
                handle,
395
                hw_params,
396
                &psize,
397
                &dir
398
                );
399
            obt = psize;
400
        }
401

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

    
408
        if ((req->override_mask & 1) && (obt - req->period_size))
409
            dolog ("Requested period %s %u was rejected, using %lu\n",
410
                   size_in_usec ? "time" : "size", req->period_size, obt);
411
    }
412

    
413
    err = snd_pcm_hw_params (handle, hw_params);
414
    if (err < 0) {
415
        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
416
        goto err;
417
    }
418

    
419
    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
420
    if (err < 0) {
421
        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
422
        goto err;
423
    }
424

    
425
    err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
426
    if (err < 0) {
427
        alsa_logerr2 (err, typ, "Failed to get format\n");
428
        goto err;
429
    }
430

    
431
    if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
432
        dolog ("Invalid format was returned %d\n", obtfmt);
433
        goto err;
434
    }
435

    
436
    err = snd_pcm_prepare (handle);
437
    if (err < 0) {
438
        alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
439
        goto err;
440
    }
441

    
442
    if (!in && conf.threshold) {
443
        snd_pcm_uframes_t threshold;
444
        int bytes_per_sec;
445

    
446
        bytes_per_sec = freq << (nchannels == 2);
447

    
448
        switch (obt->fmt) {
449
        case AUD_FMT_S8:
450
        case AUD_FMT_U8:
451
            break;
452

    
453
        case AUD_FMT_S16:
454
        case AUD_FMT_U16:
455
            bytes_per_sec <<= 1;
456
            break;
457

    
458
        case AUD_FMT_S32:
459
        case AUD_FMT_U32:
460
            bytes_per_sec <<= 2;
461
            break;
462
        }
463

    
464
        threshold = (conf.threshold * bytes_per_sec) / 1000;
465
        alsa_set_threshold (handle, threshold);
466
    }
467

    
468
    obt->nchannels = nchannels;
469
    obt->freq = freq;
470
    obt->samples = obt_buffer_size;
471

    
472
    *handlep = handle;
473

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

    
482
#ifdef DEBUG
483
    alsa_dump_info (req, obt);
484
#endif
485
    return 0;
486

    
487
 err:
488
    alsa_anal_close (&handle);
489
    return -1;
490
}
491

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

    
502
static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
503
{
504
    snd_pcm_sframes_t avail;
505

    
506
    avail = snd_pcm_avail_update (handle);
507
    if (avail < 0) {
508
        if (avail == -EPIPE) {
509
            if (!alsa_recover (handle)) {
510
                avail = snd_pcm_avail_update (handle);
511
            }
512
        }
513

    
514
        if (avail < 0) {
515
            alsa_logerr (avail,
516
                         "Could not obtain number of available frames\n");
517
            return -1;
518
        }
519
    }
520

    
521
    return avail;
522
}
523

    
524
static int alsa_run_out (HWVoiceOut *hw)
525
{
526
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
527
    int rpos, live, decr;
528
    int samples;
529
    uint8_t *dst;
530
    struct st_sample *src;
531
    snd_pcm_sframes_t avail;
532

    
533
    live = audio_pcm_hw_get_live_out (hw);
534
    if (!live) {
535
        return 0;
536
    }
537

    
538
    avail = alsa_get_avail (alsa->handle);
539
    if (avail < 0) {
540
        dolog ("Could not get number of available playback frames\n");
541
        return 0;
542
    }
543

    
544
    decr = audio_MIN (live, avail);
545
    samples = decr;
546
    rpos = hw->rpos;
547
    while (samples) {
548
        int left_till_end_samples = hw->samples - rpos;
549
        int len = audio_MIN (samples, left_till_end_samples);
550
        snd_pcm_sframes_t written;
551

    
552
        src = hw->mix_buf + rpos;
553
        dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
554

    
555
        hw->clip (dst, src, len);
556

    
557
        while (len) {
558
            written = snd_pcm_writei (alsa->handle, dst, len);
559

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

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

    
579
                case -EAGAIN:
580
                    goto exit;
581

    
582
                default:
583
                    alsa_logerr (written, "Failed to write %d frames to %p\n",
584
                                 len, dst);
585
                    goto exit;
586
                }
587
            }
588

    
589
            rpos = (rpos + written) % hw->samples;
590
            samples -= written;
591
            len -= written;
592
            dst = advance (dst, written << hw->info.shift);
593
            src += written;
594
        }
595
    }
596

    
597
 exit:
598
    hw->rpos = rpos;
599
    return decr;
600
}
601

    
602
static void alsa_fini_out (HWVoiceOut *hw)
603
{
604
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
605

    
606
    ldebug ("alsa_fini\n");
607
    alsa_anal_close (&alsa->handle);
608

    
609
    if (alsa->pcm_buf) {
610
        qemu_free (alsa->pcm_buf);
611
        alsa->pcm_buf = NULL;
612
    }
613
}
614

    
615
static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
616
{
617
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
618
    struct alsa_params_req req;
619
    struct alsa_params_obt obt;
620
    snd_pcm_t *handle;
621
    struct audsettings obt_as;
622

    
623
    req.fmt = aud_to_alsafmt (as->fmt);
624
    req.freq = as->freq;
625
    req.nchannels = as->nchannels;
626
    req.period_size = conf.period_size_out;
627
    req.buffer_size = conf.buffer_size_out;
628
    req.size_in_usec = conf.size_in_usec_out;
629
    req.override_mask =
630
        (conf.period_size_out_overridden ? 1 : 0) |
631
        (conf.buffer_size_out_overridden ? 2 : 0);
632

    
633
    if (alsa_open (0, &req, &obt, &handle)) {
634
        return -1;
635
    }
636

    
637
    obt_as.freq = obt.freq;
638
    obt_as.nchannels = obt.nchannels;
639
    obt_as.fmt = obt.fmt;
640
    obt_as.endianness = obt.endianness;
641

    
642
    audio_pcm_init_info (&hw->info, &obt_as);
643
    hw->samples = obt.samples;
644

    
645
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
646
    if (!alsa->pcm_buf) {
647
        dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n",
648
               hw->samples, 1 << hw->info.shift);
649
        alsa_anal_close (&handle);
650
        return -1;
651
    }
652

    
653
    alsa->handle = handle;
654
    return 0;
655
}
656

    
657
static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
658
{
659
    int err;
660

    
661
    if (pause) {
662
        err = snd_pcm_drop (handle);
663
        if (err < 0) {
664
            alsa_logerr (err, "Could not stop %s\n", typ);
665
            return -1;
666
        }
667
    }
668
    else {
669
        err = snd_pcm_prepare (handle);
670
        if (err < 0) {
671
            alsa_logerr (err, "Could not prepare handle for %s\n", typ);
672
            return -1;
673
        }
674
    }
675

    
676
    return 0;
677
}
678

    
679
static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
680
{
681
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
682

    
683
    switch (cmd) {
684
    case VOICE_ENABLE:
685
        ldebug ("enabling voice\n");
686
        return alsa_voice_ctl (alsa->handle, "playback", 0);
687

    
688
    case VOICE_DISABLE:
689
        ldebug ("disabling voice\n");
690
        return alsa_voice_ctl (alsa->handle, "playback", 1);
691
    }
692

    
693
    return -1;
694
}
695

    
696
static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
697
{
698
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
699
    struct alsa_params_req req;
700
    struct alsa_params_obt obt;
701
    snd_pcm_t *handle;
702
    struct audsettings obt_as;
703

    
704
    req.fmt = aud_to_alsafmt (as->fmt);
705
    req.freq = as->freq;
706
    req.nchannels = as->nchannels;
707
    req.period_size = conf.period_size_in;
708
    req.buffer_size = conf.buffer_size_in;
709
    req.size_in_usec = conf.size_in_usec_in;
710
    req.override_mask =
711
        (conf.period_size_in_overridden ? 1 : 0) |
712
        (conf.buffer_size_in_overridden ? 2 : 0);
713

    
714
    if (alsa_open (1, &req, &obt, &handle)) {
715
        return -1;
716
    }
717

    
718
    obt_as.freq = obt.freq;
719
    obt_as.nchannels = obt.nchannels;
720
    obt_as.fmt = obt.fmt;
721
    obt_as.endianness = obt.endianness;
722

    
723
    audio_pcm_init_info (&hw->info, &obt_as);
724
    hw->samples = obt.samples;
725

    
726
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
727
    if (!alsa->pcm_buf) {
728
        dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
729
               hw->samples, 1 << hw->info.shift);
730
        alsa_anal_close (&handle);
731
        return -1;
732
    }
733

    
734
    alsa->handle = handle;
735
    return 0;
736
}
737

    
738
static void alsa_fini_in (HWVoiceIn *hw)
739
{
740
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
741

    
742
    alsa_anal_close (&alsa->handle);
743

    
744
    if (alsa->pcm_buf) {
745
        qemu_free (alsa->pcm_buf);
746
        alsa->pcm_buf = NULL;
747
    }
748
}
749

    
750
static int alsa_run_in (HWVoiceIn *hw)
751
{
752
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
753
    int hwshift = hw->info.shift;
754
    int i;
755
    int live = audio_pcm_hw_get_live_in (hw);
756
    int dead = hw->samples - live;
757
    int decr;
758
    struct {
759
        int add;
760
        int len;
761
    } bufs[2] = {
762
        { hw->wpos, 0 },
763
        { 0, 0 }
764
    };
765
    snd_pcm_sframes_t avail;
766
    snd_pcm_uframes_t read_samples = 0;
767

    
768
    if (!dead) {
769
        return 0;
770
    }
771

    
772
    avail = alsa_get_avail (alsa->handle);
773
    if (avail < 0) {
774
        dolog ("Could not get number of captured frames\n");
775
        return 0;
776
    }
777

    
778
    if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) {
779
        avail = hw->samples;
780
    }
781

    
782
    decr = audio_MIN (dead, avail);
783
    if (!decr) {
784
        return 0;
785
    }
786

    
787
    if (hw->wpos + decr > hw->samples) {
788
        bufs[0].len = (hw->samples - hw->wpos);
789
        bufs[1].len = (decr - (hw->samples - hw->wpos));
790
    }
791
    else {
792
        bufs[0].len = decr;
793
    }
794

    
795
    for (i = 0; i < 2; ++i) {
796
        void *src;
797
        struct st_sample *dst;
798
        snd_pcm_sframes_t nread;
799
        snd_pcm_uframes_t len;
800

    
801
        len = bufs[i].len;
802

    
803
        src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
804
        dst = hw->conv_buf + bufs[i].add;
805

    
806
        while (len) {
807
            nread = snd_pcm_readi (alsa->handle, src, len);
808

    
809
            if (nread <= 0) {
810
                switch (nread) {
811
                case 0:
812
                    if (conf.verbose) {
813
                        dolog ("Failed to read %ld frames (read zero)\n", len);
814
                    }
815
                    goto exit;
816

    
817
                case -EPIPE:
818
                    if (alsa_recover (alsa->handle)) {
819
                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
820
                        goto exit;
821
                    }
822
                    if (conf.verbose) {
823
                        dolog ("Recovering from capture xrun\n");
824
                    }
825
                    continue;
826

    
827
                case -EAGAIN:
828
                    goto exit;
829

    
830
                default:
831
                    alsa_logerr (
832
                        nread,
833
                        "Failed to read %ld frames from %p\n",
834
                        len,
835
                        src
836
                        );
837
                    goto exit;
838
                }
839
            }
840

    
841
            hw->conv (dst, src, nread, &nominal_volume);
842

    
843
            src = advance (src, nread << hwshift);
844
            dst += nread;
845

    
846
            read_samples += nread;
847
            len -= nread;
848
        }
849
    }
850

    
851
 exit:
852
    hw->wpos = (hw->wpos + read_samples) % hw->samples;
853
    return read_samples;
854
}
855

    
856
static int alsa_read (SWVoiceIn *sw, void *buf, int size)
857
{
858
    return audio_pcm_sw_read (sw, buf, size);
859
}
860

    
861
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
862
{
863
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
864

    
865
    switch (cmd) {
866
    case VOICE_ENABLE:
867
        ldebug ("enabling voice\n");
868
        return alsa_voice_ctl (alsa->handle, "capture", 0);
869

    
870
    case VOICE_DISABLE:
871
        ldebug ("disabling voice\n");
872
        return alsa_voice_ctl (alsa->handle, "capture", 1);
873
    }
874

    
875
    return -1;
876
}
877

    
878
static void *alsa_audio_init (void)
879
{
880
    return &conf;
881
}
882

    
883
static void alsa_audio_fini (void *opaque)
884
{
885
    (void) opaque;
886
}
887

    
888
static struct audio_option alsa_options[] = {
889
    {"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
890
     "DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
891
    {"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
892
     "DAC period size (0 to go with system default)",
893
     &conf.period_size_out_overridden, 0},
894
    {"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
895
     "DAC buffer size (0 to go with system default)",
896
     &conf.buffer_size_out_overridden, 0},
897

    
898
    {"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
899
     "ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
900
    {"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
901
     "ADC period size (0 to go with system default)",
902
     &conf.period_size_in_overridden, 0},
903
    {"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
904
     "ADC buffer size (0 to go with system default)",
905
     &conf.buffer_size_in_overridden, 0},
906

    
907
    {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
908
     "(undocumented)", NULL, 0},
909

    
910
    {"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
911
     "DAC device name (for instance dmix)", NULL, 0},
912

    
913
    {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
914
     "ADC device name", NULL, 0},
915

    
916
    {"VERBOSE", AUD_OPT_BOOL, &conf.verbose,
917
     "Behave in a more verbose way", NULL, 0},
918

    
919
    {NULL, 0, NULL, NULL, NULL, 0}
920
};
921

    
922
static struct audio_pcm_ops alsa_pcm_ops = {
923
    alsa_init_out,
924
    alsa_fini_out,
925
    alsa_run_out,
926
    alsa_write,
927
    alsa_ctl_out,
928

    
929
    alsa_init_in,
930
    alsa_fini_in,
931
    alsa_run_in,
932
    alsa_read,
933
    alsa_ctl_in
934
};
935

    
936
struct audio_driver alsa_audio_driver = {
937
    INIT_FIELD (name           = ) "alsa",
938
    INIT_FIELD (descr          = ) "ALSA http://www.alsa-project.org",
939
    INIT_FIELD (options        = ) alsa_options,
940
    INIT_FIELD (init           = ) alsa_audio_init,
941
    INIT_FIELD (fini           = ) alsa_audio_fini,
942
    INIT_FIELD (pcm_ops        = ) &alsa_pcm_ops,
943
    INIT_FIELD (can_be_default = ) 1,
944
    INIT_FIELD (max_voices_out = ) INT_MAX,
945
    INIT_FIELD (max_voices_in  = ) INT_MAX,
946
    INIT_FIELD (voice_size_out = ) sizeof (ALSAVoiceOut),
947
    INIT_FIELD (voice_size_in  = ) sizeof (ALSAVoiceIn)
948
};