Statistics
| Branch: | Revision:

root / audio / alsaaudio.c @ da3d9c5b

History | View | Annotate | Download (24.2 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
    st_sample_t *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, audsettings_t *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
    audsettings_t 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 = !!conf.period_size_out_overridden
630
        | (!!conf.buffer_size_out_overridden << 1);
631

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

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

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

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

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

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

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

    
675
    return 0;
676
}
677

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

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

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

    
692
    return -1;
693
}
694

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

    
703
    req.fmt = aud_to_alsafmt (as->fmt);
704
    req.freq = as->freq;
705
    req.nchannels = as->nchannels;
706
    req.period_size = conf.period_size_in;
707
    req.buffer_size = conf.buffer_size_in;
708
    req.size_in_usec = conf.size_in_usec_in;
709
    req.override_mask = !!conf.period_size_in_overridden
710
        | (!!conf.buffer_size_in_overridden << 1);
711

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

    
716
    obt_as.freq = obt.freq;
717
    obt_as.nchannels = obt.nchannels;
718
    obt_as.fmt = obt.fmt;
719
    obt_as.endianness = obt.endianness;
720

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

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

    
732
    alsa->handle = handle;
733
    return 0;
734
}
735

    
736
static void alsa_fini_in (HWVoiceIn *hw)
737
{
738
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
739

    
740
    alsa_anal_close (&alsa->handle);
741

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

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

    
766
    if (!dead) {
767
        return 0;
768
    }
769

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

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

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

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

    
793
    for (i = 0; i < 2; ++i) {
794
        void *src;
795
        st_sample_t *dst;
796
        snd_pcm_sframes_t nread;
797
        snd_pcm_uframes_t len;
798

    
799
        len = bufs[i].len;
800

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

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

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

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

    
825
                case -EAGAIN:
826
                    goto exit;
827

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

    
839
            hw->conv (dst, src, nread, &nominal_volume);
840

    
841
            src = advance (src, nread << hwshift);
842
            dst += nread;
843

    
844
            read_samples += nread;
845
            len -= nread;
846
        }
847
    }
848

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

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

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

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

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

    
873
    return -1;
874
}
875

    
876
static void *alsa_audio_init (void)
877
{
878
    return &conf;
879
}
880

    
881
static void alsa_audio_fini (void *opaque)
882
{
883
    (void) opaque;
884
}
885

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

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

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

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

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

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

    
917
    {NULL, 0, NULL, NULL, NULL, 0}
918
};
919

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

    
927
    alsa_init_in,
928
    alsa_fini_in,
929
    alsa_run_in,
930
    alsa_read,
931
    alsa_ctl_in
932
};
933

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