Statistics
| Branch: | Revision:

root / audio / alsaaudio.c @ 7a39fe58

History | View | Annotate | Download (32.5 kB)

1 1d14ffa9 bellard
/*
2 1d14ffa9 bellard
 * QEMU ALSA audio driver
3 1d14ffa9 bellard
 *
4 1d14ffa9 bellard
 * Copyright (c) 2005 Vassili Karpov (malc)
5 1d14ffa9 bellard
 *
6 1d14ffa9 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 1d14ffa9 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 1d14ffa9 bellard
 * in the Software without restriction, including without limitation the rights
9 1d14ffa9 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 1d14ffa9 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 1d14ffa9 bellard
 * furnished to do so, subject to the following conditions:
12 1d14ffa9 bellard
 *
13 1d14ffa9 bellard
 * The above copyright notice and this permission notice shall be included in
14 1d14ffa9 bellard
 * all copies or substantial portions of the Software.
15 1d14ffa9 bellard
 *
16 1d14ffa9 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 1d14ffa9 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 1d14ffa9 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 1d14ffa9 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 1d14ffa9 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 1d14ffa9 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 1d14ffa9 bellard
 * THE SOFTWARE.
23 1d14ffa9 bellard
 */
24 1d14ffa9 bellard
#include <alsa/asoundlib.h>
25 749bc4bf pbrook
#include "qemu-common.h"
26 8b438ba3 malc
#include "qemu-char.h"
27 749bc4bf pbrook
#include "audio.h"
28 1d14ffa9 bellard
29 2637872b malc
#if QEMU_GNUC_PREREQ(4, 3)
30 2637872b malc
#pragma GCC diagnostic ignored "-Waddress"
31 2637872b malc
#endif
32 2637872b malc
33 1d14ffa9 bellard
#define AUDIO_CAP "alsa"
34 1d14ffa9 bellard
#include "audio_int.h"
35 1d14ffa9 bellard
36 8b438ba3 malc
struct pollhlp {
37 8b438ba3 malc
    snd_pcm_t *handle;
38 8b438ba3 malc
    struct pollfd *pfds;
39 8b438ba3 malc
    int count;
40 b4f763b8 malc
    int mask;
41 8b438ba3 malc
};
42 8b438ba3 malc
43 1d14ffa9 bellard
typedef struct ALSAVoiceOut {
44 1d14ffa9 bellard
    HWVoiceOut hw;
45 541ba4e7 malc
    int wpos;
46 541ba4e7 malc
    int pending;
47 1d14ffa9 bellard
    void *pcm_buf;
48 1d14ffa9 bellard
    snd_pcm_t *handle;
49 8b438ba3 malc
    struct pollhlp pollhlp;
50 1d14ffa9 bellard
} ALSAVoiceOut;
51 1d14ffa9 bellard
52 1d14ffa9 bellard
typedef struct ALSAVoiceIn {
53 1d14ffa9 bellard
    HWVoiceIn hw;
54 1d14ffa9 bellard
    snd_pcm_t *handle;
55 1d14ffa9 bellard
    void *pcm_buf;
56 8b438ba3 malc
    struct pollhlp pollhlp;
57 1d14ffa9 bellard
} ALSAVoiceIn;
58 1d14ffa9 bellard
59 1d14ffa9 bellard
static struct {
60 1d14ffa9 bellard
    int size_in_usec_in;
61 1d14ffa9 bellard
    int size_in_usec_out;
62 1d14ffa9 bellard
    const char *pcm_name_in;
63 1d14ffa9 bellard
    const char *pcm_name_out;
64 1d14ffa9 bellard
    unsigned int buffer_size_in;
65 1d14ffa9 bellard
    unsigned int period_size_in;
66 1d14ffa9 bellard
    unsigned int buffer_size_out;
67 1d14ffa9 bellard
    unsigned int period_size_out;
68 1d14ffa9 bellard
    unsigned int threshold;
69 1d14ffa9 bellard
70 fe8f096b ths
    int buffer_size_in_overridden;
71 fe8f096b ths
    int period_size_in_overridden;
72 1d14ffa9 bellard
73 fe8f096b ths
    int buffer_size_out_overridden;
74 fe8f096b ths
    int period_size_out_overridden;
75 571ec3d6 bellard
    int verbose;
76 1d14ffa9 bellard
} conf = {
77 de2ca4fb malc
    .buffer_size_out = 4096,
78 de2ca4fb malc
    .period_size_out = 1024,
79 8ead62cf bellard
    .pcm_name_out = "default",
80 8ead62cf bellard
    .pcm_name_in = "default",
81 1d14ffa9 bellard
};
82 1d14ffa9 bellard
83 1d14ffa9 bellard
struct alsa_params_req {
84 ca9cc28c balrog
    int freq;
85 ca9cc28c balrog
    snd_pcm_format_t fmt;
86 ca9cc28c balrog
    int nchannels;
87 7a24c800 malc
    int size_in_usec;
88 64333899 malc
    int override_mask;
89 1d14ffa9 bellard
    unsigned int buffer_size;
90 1d14ffa9 bellard
    unsigned int period_size;
91 1d14ffa9 bellard
};
92 1d14ffa9 bellard
93 1d14ffa9 bellard
struct alsa_params_obt {
94 1d14ffa9 bellard
    int freq;
95 1d14ffa9 bellard
    audfmt_e fmt;
96 ca9cc28c balrog
    int endianness;
97 1d14ffa9 bellard
    int nchannels;
98 c0fe3827 bellard
    snd_pcm_uframes_t samples;
99 1d14ffa9 bellard
};
100 1d14ffa9 bellard
101 1d14ffa9 bellard
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
102 1d14ffa9 bellard
{
103 1d14ffa9 bellard
    va_list ap;
104 1d14ffa9 bellard
105 1d14ffa9 bellard
    va_start (ap, fmt);
106 1d14ffa9 bellard
    AUD_vlog (AUDIO_CAP, fmt, ap);
107 1d14ffa9 bellard
    va_end (ap);
108 1d14ffa9 bellard
109 1d14ffa9 bellard
    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
110 1d14ffa9 bellard
}
111 1d14ffa9 bellard
112 1d14ffa9 bellard
static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
113 1d14ffa9 bellard
    int err,
114 1d14ffa9 bellard
    const char *typ,
115 1d14ffa9 bellard
    const char *fmt,
116 1d14ffa9 bellard
    ...
117 1d14ffa9 bellard
    )
118 1d14ffa9 bellard
{
119 1d14ffa9 bellard
    va_list ap;
120 1d14ffa9 bellard
121 c0fe3827 bellard
    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
122 1d14ffa9 bellard
123 1d14ffa9 bellard
    va_start (ap, fmt);
124 1d14ffa9 bellard
    AUD_vlog (AUDIO_CAP, fmt, ap);
125 1d14ffa9 bellard
    va_end (ap);
126 1d14ffa9 bellard
127 1d14ffa9 bellard
    AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
128 1d14ffa9 bellard
}
129 1d14ffa9 bellard
130 6ebfda13 malc
static void alsa_fini_poll (struct pollhlp *hlp)
131 6ebfda13 malc
{
132 6ebfda13 malc
    int i;
133 6ebfda13 malc
    struct pollfd *pfds = hlp->pfds;
134 6ebfda13 malc
135 6ebfda13 malc
    if (pfds) {
136 6ebfda13 malc
        for (i = 0; i < hlp->count; ++i) {
137 6ebfda13 malc
            qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL);
138 6ebfda13 malc
        }
139 6ebfda13 malc
        qemu_free (pfds);
140 6ebfda13 malc
    }
141 6ebfda13 malc
    hlp->pfds = NULL;
142 6ebfda13 malc
    hlp->count = 0;
143 6ebfda13 malc
    hlp->handle = NULL;
144 6ebfda13 malc
}
145 6ebfda13 malc
146 6ebfda13 malc
static void alsa_anal_close1 (snd_pcm_t **handlep)
147 1d14ffa9 bellard
{
148 1d14ffa9 bellard
    int err = snd_pcm_close (*handlep);
149 1d14ffa9 bellard
    if (err) {
150 1d14ffa9 bellard
        alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
151 1d14ffa9 bellard
    }
152 1d14ffa9 bellard
    *handlep = NULL;
153 1d14ffa9 bellard
}
154 1d14ffa9 bellard
155 6ebfda13 malc
static void alsa_anal_close (snd_pcm_t **handlep, struct pollhlp *hlp)
156 6ebfda13 malc
{
157 6ebfda13 malc
    alsa_fini_poll (hlp);
158 6ebfda13 malc
    alsa_anal_close1 (handlep);
159 6ebfda13 malc
}
160 6ebfda13 malc
161 8b438ba3 malc
static int alsa_recover (snd_pcm_t *handle)
162 8b438ba3 malc
{
163 8b438ba3 malc
    int err = snd_pcm_prepare (handle);
164 8b438ba3 malc
    if (err < 0) {
165 8b438ba3 malc
        alsa_logerr (err, "Failed to prepare handle %p\n", handle);
166 8b438ba3 malc
        return -1;
167 8b438ba3 malc
    }
168 8b438ba3 malc
    return 0;
169 8b438ba3 malc
}
170 8b438ba3 malc
171 8b438ba3 malc
static int alsa_resume (snd_pcm_t *handle)
172 8b438ba3 malc
{
173 8b438ba3 malc
    int err = snd_pcm_resume (handle);
174 8b438ba3 malc
    if (err < 0) {
175 8b438ba3 malc
        alsa_logerr (err, "Failed to resume handle %p\n", handle);
176 8b438ba3 malc
        return -1;
177 8b438ba3 malc
    }
178 8b438ba3 malc
    return 0;
179 8b438ba3 malc
}
180 8b438ba3 malc
181 8b438ba3 malc
static void alsa_poll_handler (void *opaque)
182 8b438ba3 malc
{
183 8b438ba3 malc
    int err, count;
184 8b438ba3 malc
    snd_pcm_state_t state;
185 8b438ba3 malc
    struct pollhlp *hlp = opaque;
186 8b438ba3 malc
    unsigned short revents;
187 8b438ba3 malc
188 8b438ba3 malc
    count = poll (hlp->pfds, hlp->count, 0);
189 8b438ba3 malc
    if (count < 0) {
190 8b438ba3 malc
        dolog ("alsa_poll_handler: poll %s\n", strerror (errno));
191 8b438ba3 malc
        return;
192 8b438ba3 malc
    }
193 8b438ba3 malc
194 8b438ba3 malc
    if (!count) {
195 8b438ba3 malc
        return;
196 8b438ba3 malc
    }
197 8b438ba3 malc
198 8b438ba3 malc
    /* XXX: ALSA example uses initial count, not the one returned by
199 8b438ba3 malc
       poll, correct? */
200 8b438ba3 malc
    err = snd_pcm_poll_descriptors_revents (hlp->handle, hlp->pfds,
201 8b438ba3 malc
                                            hlp->count, &revents);
202 8b438ba3 malc
    if (err < 0) {
203 8b438ba3 malc
        alsa_logerr (err, "snd_pcm_poll_descriptors_revents");
204 8b438ba3 malc
        return;
205 8b438ba3 malc
    }
206 8b438ba3 malc
207 b4f763b8 malc
    if (!(revents & hlp->mask)) {
208 8b438ba3 malc
        if (conf.verbose) {
209 8b438ba3 malc
            dolog ("revents = %d\n", revents);
210 8b438ba3 malc
        }
211 8b438ba3 malc
        return;
212 8b438ba3 malc
    }
213 8b438ba3 malc
214 8b438ba3 malc
    state = snd_pcm_state (hlp->handle);
215 8b438ba3 malc
    switch (state) {
216 d9812b03 malc
    case SND_PCM_STATE_SETUP:
217 d9812b03 malc
        alsa_recover (hlp->handle);
218 d9812b03 malc
        break;
219 d9812b03 malc
220 8b438ba3 malc
    case SND_PCM_STATE_XRUN:
221 8b438ba3 malc
        alsa_recover (hlp->handle);
222 8b438ba3 malc
        break;
223 8b438ba3 malc
224 8b438ba3 malc
    case SND_PCM_STATE_SUSPENDED:
225 8b438ba3 malc
        alsa_resume (hlp->handle);
226 8b438ba3 malc
        break;
227 8b438ba3 malc
228 8b438ba3 malc
    case SND_PCM_STATE_PREPARED:
229 8b438ba3 malc
        audio_run ("alsa run (prepared)");
230 8b438ba3 malc
        break;
231 8b438ba3 malc
232 8b438ba3 malc
    case SND_PCM_STATE_RUNNING:
233 8b438ba3 malc
        audio_run ("alsa run (running)");
234 8b438ba3 malc
        break;
235 8b438ba3 malc
236 8b438ba3 malc
    default:
237 8b438ba3 malc
        dolog ("Unexpected state %d\n", state);
238 8b438ba3 malc
    }
239 8b438ba3 malc
}
240 8b438ba3 malc
241 b4f763b8 malc
static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask)
242 8b438ba3 malc
{
243 8b438ba3 malc
    int i, count, err;
244 8b438ba3 malc
    struct pollfd *pfds;
245 8b438ba3 malc
246 8b438ba3 malc
    count = snd_pcm_poll_descriptors_count (handle);
247 8b438ba3 malc
    if (count <= 0) {
248 8b438ba3 malc
        dolog ("Could not initialize poll mode\n"
249 8b438ba3 malc
               "Invalid number of poll descriptors %d\n", count);
250 8b438ba3 malc
        return -1;
251 8b438ba3 malc
    }
252 8b438ba3 malc
253 8b438ba3 malc
    pfds = audio_calloc ("alsa_poll_helper", count, sizeof (*pfds));
254 8b438ba3 malc
    if (!pfds) {
255 8b438ba3 malc
        dolog ("Could not initialize poll mode\n");
256 8b438ba3 malc
        return -1;
257 8b438ba3 malc
    }
258 8b438ba3 malc
259 8b438ba3 malc
    err = snd_pcm_poll_descriptors (handle, pfds, count);
260 8b438ba3 malc
    if (err < 0) {
261 8b438ba3 malc
        alsa_logerr (err, "Could not initialize poll mode\n"
262 8b438ba3 malc
                     "Could not obtain poll descriptors\n");
263 8b438ba3 malc
        qemu_free (pfds);
264 8b438ba3 malc
        return -1;
265 8b438ba3 malc
    }
266 8b438ba3 malc
267 8b438ba3 malc
    for (i = 0; i < count; ++i) {
268 8b438ba3 malc
        if (pfds[i].events & POLLIN) {
269 8b438ba3 malc
            err = qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler,
270 8b438ba3 malc
                                       NULL, hlp);
271 8b438ba3 malc
        }
272 8b438ba3 malc
        if (pfds[i].events & POLLOUT) {
273 8b438ba3 malc
            if (conf.verbose) {
274 8b438ba3 malc
                dolog ("POLLOUT %d %d\n", i, pfds[i].fd);
275 8b438ba3 malc
            }
276 8b438ba3 malc
            err = qemu_set_fd_handler (pfds[i].fd, NULL,
277 8b438ba3 malc
                                       alsa_poll_handler, hlp);
278 8b438ba3 malc
        }
279 8b438ba3 malc
        if (conf.verbose) {
280 8b438ba3 malc
            dolog ("Set handler events=%#x index=%d fd=%d err=%d\n",
281 8b438ba3 malc
                   pfds[i].events, i, pfds[i].fd, err);
282 8b438ba3 malc
        }
283 8b438ba3 malc
284 8b438ba3 malc
        if (err) {
285 8b438ba3 malc
            dolog ("Failed to set handler events=%#x index=%d fd=%d err=%d\n",
286 8b438ba3 malc
                   pfds[i].events, i, pfds[i].fd, err);
287 8b438ba3 malc
288 8b438ba3 malc
            while (i--) {
289 8b438ba3 malc
                qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL);
290 8b438ba3 malc
            }
291 8b438ba3 malc
            qemu_free (pfds);
292 8b438ba3 malc
            return -1;
293 8b438ba3 malc
        }
294 8b438ba3 malc
    }
295 8b438ba3 malc
    hlp->pfds = pfds;
296 8b438ba3 malc
    hlp->count = count;
297 8b438ba3 malc
    hlp->handle = handle;
298 b4f763b8 malc
    hlp->mask = mask;
299 8b438ba3 malc
    return 0;
300 8b438ba3 malc
}
301 8b438ba3 malc
302 8b438ba3 malc
static int alsa_poll_out (HWVoiceOut *hw)
303 8b438ba3 malc
{
304 8b438ba3 malc
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
305 8b438ba3 malc
306 b4f763b8 malc
    return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLOUT);
307 8b438ba3 malc
}
308 8b438ba3 malc
309 8b438ba3 malc
static int alsa_poll_in (HWVoiceIn *hw)
310 8b438ba3 malc
{
311 8b438ba3 malc
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
312 8b438ba3 malc
313 b4f763b8 malc
    return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN);
314 8b438ba3 malc
}
315 8b438ba3 malc
316 1d14ffa9 bellard
static int alsa_write (SWVoiceOut *sw, void *buf, int len)
317 1d14ffa9 bellard
{
318 1d14ffa9 bellard
    return audio_pcm_sw_write (sw, buf, len);
319 1d14ffa9 bellard
}
320 1d14ffa9 bellard
321 d66bddd7 Michael Walle
static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness)
322 1d14ffa9 bellard
{
323 1d14ffa9 bellard
    switch (fmt) {
324 1d14ffa9 bellard
    case AUD_FMT_S8:
325 1d14ffa9 bellard
        return SND_PCM_FORMAT_S8;
326 1d14ffa9 bellard
327 1d14ffa9 bellard
    case AUD_FMT_U8:
328 1d14ffa9 bellard
        return SND_PCM_FORMAT_U8;
329 1d14ffa9 bellard
330 1d14ffa9 bellard
    case AUD_FMT_S16:
331 d66bddd7 Michael Walle
        if (endianness) {
332 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_S16_BE;
333 d66bddd7 Michael Walle
        }
334 d66bddd7 Michael Walle
        else {
335 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_S16_LE;
336 d66bddd7 Michael Walle
        }
337 1d14ffa9 bellard
338 1d14ffa9 bellard
    case AUD_FMT_U16:
339 d66bddd7 Michael Walle
        if (endianness) {
340 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_U16_BE;
341 d66bddd7 Michael Walle
        }
342 d66bddd7 Michael Walle
        else {
343 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_U16_LE;
344 d66bddd7 Michael Walle
        }
345 1d14ffa9 bellard
346 f941aa25 ths
    case AUD_FMT_S32:
347 d66bddd7 Michael Walle
        if (endianness) {
348 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_S32_BE;
349 d66bddd7 Michael Walle
        }
350 d66bddd7 Michael Walle
        else {
351 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_S32_LE;
352 d66bddd7 Michael Walle
        }
353 f941aa25 ths
354 f941aa25 ths
    case AUD_FMT_U32:
355 d66bddd7 Michael Walle
        if (endianness) {
356 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_U32_BE;
357 d66bddd7 Michael Walle
        }
358 d66bddd7 Michael Walle
        else {
359 d66bddd7 Michael Walle
            return SND_PCM_FORMAT_U32_LE;
360 d66bddd7 Michael Walle
        }
361 f941aa25 ths
362 1d14ffa9 bellard
    default:
363 1d14ffa9 bellard
        dolog ("Internal logic error: Bad audio format %d\n", fmt);
364 1d14ffa9 bellard
#ifdef DEBUG_AUDIO
365 1d14ffa9 bellard
        abort ();
366 1d14ffa9 bellard
#endif
367 1d14ffa9 bellard
        return SND_PCM_FORMAT_U8;
368 1d14ffa9 bellard
    }
369 1d14ffa9 bellard
}
370 1d14ffa9 bellard
371 ca9cc28c balrog
static int alsa_to_audfmt (snd_pcm_format_t alsafmt, audfmt_e *fmt,
372 ca9cc28c balrog
                           int *endianness)
373 1d14ffa9 bellard
{
374 1d14ffa9 bellard
    switch (alsafmt) {
375 1d14ffa9 bellard
    case SND_PCM_FORMAT_S8:
376 1d14ffa9 bellard
        *endianness = 0;
377 1d14ffa9 bellard
        *fmt = AUD_FMT_S8;
378 1d14ffa9 bellard
        break;
379 1d14ffa9 bellard
380 1d14ffa9 bellard
    case SND_PCM_FORMAT_U8:
381 1d14ffa9 bellard
        *endianness = 0;
382 1d14ffa9 bellard
        *fmt = AUD_FMT_U8;
383 1d14ffa9 bellard
        break;
384 1d14ffa9 bellard
385 1d14ffa9 bellard
    case SND_PCM_FORMAT_S16_LE:
386 1d14ffa9 bellard
        *endianness = 0;
387 1d14ffa9 bellard
        *fmt = AUD_FMT_S16;
388 1d14ffa9 bellard
        break;
389 1d14ffa9 bellard
390 1d14ffa9 bellard
    case SND_PCM_FORMAT_U16_LE:
391 1d14ffa9 bellard
        *endianness = 0;
392 1d14ffa9 bellard
        *fmt = AUD_FMT_U16;
393 1d14ffa9 bellard
        break;
394 1d14ffa9 bellard
395 1d14ffa9 bellard
    case SND_PCM_FORMAT_S16_BE:
396 1d14ffa9 bellard
        *endianness = 1;
397 1d14ffa9 bellard
        *fmt = AUD_FMT_S16;
398 1d14ffa9 bellard
        break;
399 1d14ffa9 bellard
400 1d14ffa9 bellard
    case SND_PCM_FORMAT_U16_BE:
401 1d14ffa9 bellard
        *endianness = 1;
402 1d14ffa9 bellard
        *fmt = AUD_FMT_U16;
403 1d14ffa9 bellard
        break;
404 1d14ffa9 bellard
405 f941aa25 ths
    case SND_PCM_FORMAT_S32_LE:
406 f941aa25 ths
        *endianness = 0;
407 f941aa25 ths
        *fmt = AUD_FMT_S32;
408 f941aa25 ths
        break;
409 f941aa25 ths
410 f941aa25 ths
    case SND_PCM_FORMAT_U32_LE:
411 f941aa25 ths
        *endianness = 0;
412 f941aa25 ths
        *fmt = AUD_FMT_U32;
413 f941aa25 ths
        break;
414 f941aa25 ths
415 f941aa25 ths
    case SND_PCM_FORMAT_S32_BE:
416 f941aa25 ths
        *endianness = 1;
417 f941aa25 ths
        *fmt = AUD_FMT_S32;
418 f941aa25 ths
        break;
419 f941aa25 ths
420 f941aa25 ths
    case SND_PCM_FORMAT_U32_BE:
421 f941aa25 ths
        *endianness = 1;
422 f941aa25 ths
        *fmt = AUD_FMT_U32;
423 f941aa25 ths
        break;
424 f941aa25 ths
425 1d14ffa9 bellard
    default:
426 1d14ffa9 bellard
        dolog ("Unrecognized audio format %d\n", alsafmt);
427 1d14ffa9 bellard
        return -1;
428 1d14ffa9 bellard
    }
429 1d14ffa9 bellard
430 1d14ffa9 bellard
    return 0;
431 1d14ffa9 bellard
}
432 1d14ffa9 bellard
433 1d14ffa9 bellard
static void alsa_dump_info (struct alsa_params_req *req,
434 8bb414d2 malc
                            struct alsa_params_obt *obt,
435 8bb414d2 malc
                            snd_pcm_format_t obtfmt)
436 1d14ffa9 bellard
{
437 1d14ffa9 bellard
    dolog ("parameter | requested value | obtained value\n");
438 8bb414d2 malc
    dolog ("format    |      %10d |     %10d\n", req->fmt, obtfmt);
439 1d14ffa9 bellard
    dolog ("channels  |      %10d |     %10d\n",
440 1d14ffa9 bellard
           req->nchannels, obt->nchannels);
441 1d14ffa9 bellard
    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
442 1d14ffa9 bellard
    dolog ("============================================\n");
443 1d14ffa9 bellard
    dolog ("requested: buffer size %d period size %d\n",
444 1d14ffa9 bellard
           req->buffer_size, req->period_size);
445 c0fe3827 bellard
    dolog ("obtained: samples %ld\n", obt->samples);
446 1d14ffa9 bellard
}
447 1d14ffa9 bellard
448 1d14ffa9 bellard
static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
449 1d14ffa9 bellard
{
450 1d14ffa9 bellard
    int err;
451 1d14ffa9 bellard
    snd_pcm_sw_params_t *sw_params;
452 1d14ffa9 bellard
453 1d14ffa9 bellard
    snd_pcm_sw_params_alloca (&sw_params);
454 1d14ffa9 bellard
455 1d14ffa9 bellard
    err = snd_pcm_sw_params_current (handle, sw_params);
456 1d14ffa9 bellard
    if (err < 0) {
457 c0fe3827 bellard
        dolog ("Could not fully initialize DAC\n");
458 1d14ffa9 bellard
        alsa_logerr (err, "Failed to get current software parameters\n");
459 1d14ffa9 bellard
        return;
460 1d14ffa9 bellard
    }
461 1d14ffa9 bellard
462 1d14ffa9 bellard
    err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
463 1d14ffa9 bellard
    if (err < 0) {
464 c0fe3827 bellard
        dolog ("Could not fully initialize DAC\n");
465 1d14ffa9 bellard
        alsa_logerr (err, "Failed to set software threshold to %ld\n",
466 1d14ffa9 bellard
                     threshold);
467 1d14ffa9 bellard
        return;
468 1d14ffa9 bellard
    }
469 1d14ffa9 bellard
470 1d14ffa9 bellard
    err = snd_pcm_sw_params (handle, sw_params);
471 1d14ffa9 bellard
    if (err < 0) {
472 c0fe3827 bellard
        dolog ("Could not fully initialize DAC\n");
473 1d14ffa9 bellard
        alsa_logerr (err, "Failed to set software parameters\n");
474 1d14ffa9 bellard
        return;
475 1d14ffa9 bellard
    }
476 1d14ffa9 bellard
}
477 1d14ffa9 bellard
478 1d14ffa9 bellard
static int alsa_open (int in, struct alsa_params_req *req,
479 1d14ffa9 bellard
                      struct alsa_params_obt *obt, snd_pcm_t **handlep)
480 1d14ffa9 bellard
{
481 1d14ffa9 bellard
    snd_pcm_t *handle;
482 1d14ffa9 bellard
    snd_pcm_hw_params_t *hw_params;
483 60fe76f3 ths
    int err;
484 7a24c800 malc
    int size_in_usec;
485 60fe76f3 ths
    unsigned int freq, nchannels;
486 1d14ffa9 bellard
    const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
487 1d14ffa9 bellard
    snd_pcm_uframes_t obt_buffer_size;
488 1d14ffa9 bellard
    const char *typ = in ? "ADC" : "DAC";
489 ca9cc28c balrog
    snd_pcm_format_t obtfmt;
490 1d14ffa9 bellard
491 1d14ffa9 bellard
    freq = req->freq;
492 1d14ffa9 bellard
    nchannels = req->nchannels;
493 7a24c800 malc
    size_in_usec = req->size_in_usec;
494 1d14ffa9 bellard
495 1d14ffa9 bellard
    snd_pcm_hw_params_alloca (&hw_params);
496 1d14ffa9 bellard
497 1d14ffa9 bellard
    err = snd_pcm_open (
498 1d14ffa9 bellard
        &handle,
499 1d14ffa9 bellard
        pcm_name,
500 1d14ffa9 bellard
        in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
501 1d14ffa9 bellard
        SND_PCM_NONBLOCK
502 1d14ffa9 bellard
        );
503 1d14ffa9 bellard
    if (err < 0) {
504 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
505 1d14ffa9 bellard
        return -1;
506 1d14ffa9 bellard
    }
507 1d14ffa9 bellard
508 1d14ffa9 bellard
    err = snd_pcm_hw_params_any (handle, hw_params);
509 1d14ffa9 bellard
    if (err < 0) {
510 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
511 1d14ffa9 bellard
        goto err;
512 1d14ffa9 bellard
    }
513 1d14ffa9 bellard
514 1d14ffa9 bellard
    err = snd_pcm_hw_params_set_access (
515 1d14ffa9 bellard
        handle,
516 1d14ffa9 bellard
        hw_params,
517 1d14ffa9 bellard
        SND_PCM_ACCESS_RW_INTERLEAVED
518 1d14ffa9 bellard
        );
519 1d14ffa9 bellard
    if (err < 0) {
520 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to set access type\n");
521 1d14ffa9 bellard
        goto err;
522 1d14ffa9 bellard
    }
523 1d14ffa9 bellard
524 1d14ffa9 bellard
    err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
525 ca9cc28c balrog
    if (err < 0 && conf.verbose) {
526 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
527 1d14ffa9 bellard
    }
528 1d14ffa9 bellard
529 1d14ffa9 bellard
    err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
530 1d14ffa9 bellard
    if (err < 0) {
531 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
532 1d14ffa9 bellard
        goto err;
533 1d14ffa9 bellard
    }
534 1d14ffa9 bellard
535 1d14ffa9 bellard
    err = snd_pcm_hw_params_set_channels_near (
536 1d14ffa9 bellard
        handle,
537 1d14ffa9 bellard
        hw_params,
538 1d14ffa9 bellard
        &nchannels
539 1d14ffa9 bellard
        );
540 1d14ffa9 bellard
    if (err < 0) {
541 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
542 1d14ffa9 bellard
                      req->nchannels);
543 1d14ffa9 bellard
        goto err;
544 1d14ffa9 bellard
    }
545 1d14ffa9 bellard
546 1d14ffa9 bellard
    if (nchannels != 1 && nchannels != 2) {
547 1d14ffa9 bellard
        alsa_logerr2 (err, typ,
548 1d14ffa9 bellard
                      "Can not handle obtained number of channels %d\n",
549 1d14ffa9 bellard
                      nchannels);
550 1d14ffa9 bellard
        goto err;
551 1d14ffa9 bellard
    }
552 1d14ffa9 bellard
553 7a24c800 malc
    if (req->buffer_size) {
554 f3b52983 malc
        unsigned long obt;
555 f3b52983 malc
556 7a24c800 malc
        if (size_in_usec) {
557 7a24c800 malc
            int dir = 0;
558 7a24c800 malc
            unsigned int btime = req->buffer_size;
559 1d14ffa9 bellard
560 1d14ffa9 bellard
            err = snd_pcm_hw_params_set_buffer_time_near (
561 1d14ffa9 bellard
                handle,
562 1d14ffa9 bellard
                hw_params,
563 7a24c800 malc
                &btime,
564 7a24c800 malc
                &dir
565 c0fe3827 bellard
                );
566 f3b52983 malc
            obt = btime;
567 1d14ffa9 bellard
        }
568 1d14ffa9 bellard
        else {
569 7a24c800 malc
            snd_pcm_uframes_t bsize = req->buffer_size;
570 1d14ffa9 bellard
571 7a24c800 malc
            err = snd_pcm_hw_params_set_buffer_size_near (
572 7a24c800 malc
                handle,
573 7a24c800 malc
                hw_params,
574 7a24c800 malc
                &bsize
575 7a24c800 malc
                );
576 f3b52983 malc
            obt = bsize;
577 7a24c800 malc
        }
578 7a24c800 malc
        if (err < 0) {
579 7a24c800 malc
            alsa_logerr2 (err, typ, "Failed to set buffer %s to %d\n",
580 7a24c800 malc
                          size_in_usec ? "time" : "size", req->buffer_size);
581 7a24c800 malc
            goto err;
582 7a24c800 malc
        }
583 f3b52983 malc
584 64333899 malc
        if ((req->override_mask & 2) && (obt - req->buffer_size))
585 f3b52983 malc
            dolog ("Requested buffer %s %u was rejected, using %lu\n",
586 f3b52983 malc
                   size_in_usec ? "time" : "size", req->buffer_size, obt);
587 7a24c800 malc
    }
588 7a24c800 malc
589 7a24c800 malc
    if (req->period_size) {
590 f3b52983 malc
        unsigned long obt;
591 f3b52983 malc
592 7a24c800 malc
        if (size_in_usec) {
593 7a24c800 malc
            int dir = 0;
594 7a24c800 malc
            unsigned int ptime = req->period_size;
595 1d14ffa9 bellard
596 7a24c800 malc
            err = snd_pcm_hw_params_set_period_time_near (
597 7a24c800 malc
                handle,
598 1d14ffa9 bellard
                hw_params,
599 7a24c800 malc
                &ptime,
600 7a24c800 malc
                &dir
601 1d14ffa9 bellard
                );
602 f3b52983 malc
            obt = ptime;
603 7a24c800 malc
        }
604 7a24c800 malc
        else {
605 a7bb29ba malc
            int dir = 0;
606 7a24c800 malc
            snd_pcm_uframes_t psize = req->period_size;
607 1d14ffa9 bellard
608 a7bb29ba malc
            err = snd_pcm_hw_params_set_period_size_near (
609 1d14ffa9 bellard
                handle,
610 1d14ffa9 bellard
                hw_params,
611 a7bb29ba malc
                &psize,
612 a7bb29ba malc
                &dir
613 1d14ffa9 bellard
                );
614 f3b52983 malc
            obt = psize;
615 1d14ffa9 bellard
        }
616 7a24c800 malc
617 7a24c800 malc
        if (err < 0) {
618 7a24c800 malc
            alsa_logerr2 (err, typ, "Failed to set period %s to %d\n",
619 7a24c800 malc
                          size_in_usec ? "time" : "size", req->period_size);
620 7a24c800 malc
            goto err;
621 7a24c800 malc
        }
622 f3b52983 malc
623 541ba4e7 malc
        if (((req->override_mask & 1) && (obt - req->period_size)))
624 f3b52983 malc
            dolog ("Requested period %s %u was rejected, using %lu\n",
625 f3b52983 malc
                   size_in_usec ? "time" : "size", req->period_size, obt);
626 1d14ffa9 bellard
    }
627 1d14ffa9 bellard
628 1d14ffa9 bellard
    err = snd_pcm_hw_params (handle, hw_params);
629 1d14ffa9 bellard
    if (err < 0) {
630 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
631 1d14ffa9 bellard
        goto err;
632 1d14ffa9 bellard
    }
633 1d14ffa9 bellard
634 1d14ffa9 bellard
    err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
635 1d14ffa9 bellard
    if (err < 0) {
636 1d14ffa9 bellard
        alsa_logerr2 (err, typ, "Failed to get buffer size\n");
637 1d14ffa9 bellard
        goto err;
638 1d14ffa9 bellard
    }
639 1d14ffa9 bellard
640 ca9cc28c balrog
    err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
641 ca9cc28c balrog
    if (err < 0) {
642 ca9cc28c balrog
        alsa_logerr2 (err, typ, "Failed to get format\n");
643 ca9cc28c balrog
        goto err;
644 ca9cc28c balrog
    }
645 ca9cc28c balrog
646 ca9cc28c balrog
    if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
647 ca9cc28c balrog
        dolog ("Invalid format was returned %d\n", obtfmt);
648 ca9cc28c balrog
        goto err;
649 ca9cc28c balrog
    }
650 ca9cc28c balrog
651 1d14ffa9 bellard
    err = snd_pcm_prepare (handle);
652 1d14ffa9 bellard
    if (err < 0) {
653 c0fe3827 bellard
        alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
654 1d14ffa9 bellard
        goto err;
655 1d14ffa9 bellard
    }
656 1d14ffa9 bellard
657 1d14ffa9 bellard
    if (!in && conf.threshold) {
658 1d14ffa9 bellard
        snd_pcm_uframes_t threshold;
659 1d14ffa9 bellard
        int bytes_per_sec;
660 1d14ffa9 bellard
661 ca9cc28c balrog
        bytes_per_sec = freq << (nchannels == 2);
662 ca9cc28c balrog
663 ca9cc28c balrog
        switch (obt->fmt) {
664 ca9cc28c balrog
        case AUD_FMT_S8:
665 ca9cc28c balrog
        case AUD_FMT_U8:
666 ca9cc28c balrog
            break;
667 ca9cc28c balrog
668 ca9cc28c balrog
        case AUD_FMT_S16:
669 ca9cc28c balrog
        case AUD_FMT_U16:
670 ca9cc28c balrog
            bytes_per_sec <<= 1;
671 ca9cc28c balrog
            break;
672 ca9cc28c balrog
673 ca9cc28c balrog
        case AUD_FMT_S32:
674 ca9cc28c balrog
        case AUD_FMT_U32:
675 ca9cc28c balrog
            bytes_per_sec <<= 2;
676 ca9cc28c balrog
            break;
677 ca9cc28c balrog
        }
678 1d14ffa9 bellard
679 1d14ffa9 bellard
        threshold = (conf.threshold * bytes_per_sec) / 1000;
680 1d14ffa9 bellard
        alsa_set_threshold (handle, threshold);
681 1d14ffa9 bellard
    }
682 1d14ffa9 bellard
683 1d14ffa9 bellard
    obt->nchannels = nchannels;
684 1d14ffa9 bellard
    obt->freq = freq;
685 c0fe3827 bellard
    obt->samples = obt_buffer_size;
686 ca9cc28c balrog
687 1d14ffa9 bellard
    *handlep = handle;
688 1d14ffa9 bellard
689 ca9cc28c balrog
    if (conf.verbose &&
690 8bb414d2 malc
        (obtfmt != req->fmt ||
691 ca9cc28c balrog
         obt->nchannels != req->nchannels ||
692 ca9cc28c balrog
         obt->freq != req->freq)) {
693 f093feb7 Vagrant Cascadian
        dolog ("Audio parameters for %s\n", typ);
694 8bb414d2 malc
        alsa_dump_info (req, obt, obtfmt);
695 1d14ffa9 bellard
    }
696 1d14ffa9 bellard
697 1d14ffa9 bellard
#ifdef DEBUG
698 8bb414d2 malc
    alsa_dump_info (req, obt, obtfmt);
699 1d14ffa9 bellard
#endif
700 1d14ffa9 bellard
    return 0;
701 1d14ffa9 bellard
702 1d14ffa9 bellard
 err:
703 6ebfda13 malc
    alsa_anal_close1 (&handle);
704 1d14ffa9 bellard
    return -1;
705 1d14ffa9 bellard
}
706 1d14ffa9 bellard
707 571ec3d6 bellard
static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
708 571ec3d6 bellard
{
709 571ec3d6 bellard
    snd_pcm_sframes_t avail;
710 571ec3d6 bellard
711 571ec3d6 bellard
    avail = snd_pcm_avail_update (handle);
712 571ec3d6 bellard
    if (avail < 0) {
713 571ec3d6 bellard
        if (avail == -EPIPE) {
714 571ec3d6 bellard
            if (!alsa_recover (handle)) {
715 571ec3d6 bellard
                avail = snd_pcm_avail_update (handle);
716 571ec3d6 bellard
            }
717 571ec3d6 bellard
        }
718 571ec3d6 bellard
719 571ec3d6 bellard
        if (avail < 0) {
720 571ec3d6 bellard
            alsa_logerr (avail,
721 571ec3d6 bellard
                         "Could not obtain number of available frames\n");
722 571ec3d6 bellard
            return -1;
723 571ec3d6 bellard
        }
724 571ec3d6 bellard
    }
725 571ec3d6 bellard
726 571ec3d6 bellard
    return avail;
727 571ec3d6 bellard
}
728 571ec3d6 bellard
729 541ba4e7 malc
static void alsa_write_pending (ALSAVoiceOut *alsa)
730 1d14ffa9 bellard
{
731 541ba4e7 malc
    HWVoiceOut *hw = &alsa->hw;
732 1d14ffa9 bellard
733 541ba4e7 malc
    while (alsa->pending) {
734 541ba4e7 malc
        int left_till_end_samples = hw->samples - alsa->wpos;
735 541ba4e7 malc
        int len = audio_MIN (alsa->pending, left_till_end_samples);
736 541ba4e7 malc
        char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift);
737 1d14ffa9 bellard
738 571ec3d6 bellard
        while (len) {
739 541ba4e7 malc
            snd_pcm_sframes_t written;
740 541ba4e7 malc
741 541ba4e7 malc
            written = snd_pcm_writei (alsa->handle, src, len);
742 4787c71d bellard
743 571ec3d6 bellard
            if (written <= 0) {
744 4787c71d bellard
                switch (written) {
745 571ec3d6 bellard
                case 0:
746 571ec3d6 bellard
                    if (conf.verbose) {
747 571ec3d6 bellard
                        dolog ("Failed to write %d frames (wrote zero)\n", len);
748 4787c71d bellard
                    }
749 541ba4e7 malc
                    return;
750 4787c71d bellard
751 571ec3d6 bellard
                case -EPIPE:
752 571ec3d6 bellard
                    if (alsa_recover (alsa->handle)) {
753 571ec3d6 bellard
                        alsa_logerr (written, "Failed to write %d frames\n",
754 571ec3d6 bellard
                                     len);
755 541ba4e7 malc
                        return;
756 571ec3d6 bellard
                    }
757 571ec3d6 bellard
                    if (conf.verbose) {
758 571ec3d6 bellard
                        dolog ("Recovering from playback xrun\n");
759 571ec3d6 bellard
                    }
760 4787c71d bellard
                    continue;
761 4787c71d bellard
762 86635821 Bjรธrn Mork
                case -ESTRPIPE:
763 86635821 Bjรธrn Mork
                    /* stream is suspended and waiting for an
764 86635821 Bjรธrn Mork
                       application recovery */
765 86635821 Bjรธrn Mork
                    if (alsa_resume (alsa->handle)) {
766 86635821 Bjรธrn Mork
                        alsa_logerr (written, "Failed to write %d frames\n",
767 86635821 Bjรธrn Mork
                                     len);
768 541ba4e7 malc
                        return;
769 86635821 Bjรธrn Mork
                    }
770 86635821 Bjรธrn Mork
                    if (conf.verbose) {
771 86635821 Bjรธrn Mork
                        dolog ("Resuming suspended output stream\n");
772 86635821 Bjรธrn Mork
                    }
773 86635821 Bjรธrn Mork
                    continue;
774 86635821 Bjรธrn Mork
775 571ec3d6 bellard
                case -EAGAIN:
776 541ba4e7 malc
                    return;
777 571ec3d6 bellard
778 4787c71d bellard
                default:
779 541ba4e7 malc
                    alsa_logerr (written, "Failed to write %d frames from %p\n",
780 541ba4e7 malc
                                 len, src);
781 541ba4e7 malc
                    return;
782 1d14ffa9 bellard
                }
783 1d14ffa9 bellard
            }
784 1d14ffa9 bellard
785 541ba4e7 malc
            alsa->wpos = (alsa->wpos + written) % hw->samples;
786 541ba4e7 malc
            alsa->pending -= written;
787 571ec3d6 bellard
            len -= written;
788 4787c71d bellard
        }
789 1d14ffa9 bellard
    }
790 541ba4e7 malc
}
791 541ba4e7 malc
792 bdff253c malc
static int alsa_run_out (HWVoiceOut *hw, int live)
793 541ba4e7 malc
{
794 541ba4e7 malc
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
795 bdff253c malc
    int decr;
796 541ba4e7 malc
    snd_pcm_sframes_t avail;
797 541ba4e7 malc
798 541ba4e7 malc
    avail = alsa_get_avail (alsa->handle);
799 541ba4e7 malc
    if (avail < 0) {
800 541ba4e7 malc
        dolog ("Could not get number of available playback frames\n");
801 541ba4e7 malc
        return 0;
802 541ba4e7 malc
    }
803 541ba4e7 malc
804 541ba4e7 malc
    decr = audio_MIN (live, avail);
805 541ba4e7 malc
    decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending);
806 541ba4e7 malc
    alsa->pending += decr;
807 541ba4e7 malc
    alsa_write_pending (alsa);
808 1d14ffa9 bellard
    return decr;
809 1d14ffa9 bellard
}
810 1d14ffa9 bellard
811 1d14ffa9 bellard
static void alsa_fini_out (HWVoiceOut *hw)
812 1d14ffa9 bellard
{
813 1d14ffa9 bellard
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
814 1d14ffa9 bellard
815 1d14ffa9 bellard
    ldebug ("alsa_fini\n");
816 6ebfda13 malc
    alsa_anal_close (&alsa->handle, &alsa->pollhlp);
817 1d14ffa9 bellard
818 1d14ffa9 bellard
    if (alsa->pcm_buf) {
819 1d14ffa9 bellard
        qemu_free (alsa->pcm_buf);
820 1d14ffa9 bellard
        alsa->pcm_buf = NULL;
821 1d14ffa9 bellard
    }
822 1d14ffa9 bellard
}
823 1d14ffa9 bellard
824 1ea879e5 malc
static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
825 1d14ffa9 bellard
{
826 1d14ffa9 bellard
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
827 1d14ffa9 bellard
    struct alsa_params_req req;
828 1d14ffa9 bellard
    struct alsa_params_obt obt;
829 1d14ffa9 bellard
    snd_pcm_t *handle;
830 1ea879e5 malc
    struct audsettings obt_as;
831 1d14ffa9 bellard
832 d66bddd7 Michael Walle
    req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
833 c0fe3827 bellard
    req.freq = as->freq;
834 c0fe3827 bellard
    req.nchannels = as->nchannels;
835 1d14ffa9 bellard
    req.period_size = conf.period_size_out;
836 1d14ffa9 bellard
    req.buffer_size = conf.buffer_size_out;
837 23fb600b malc
    req.size_in_usec = conf.size_in_usec_out;
838 97f155dd Gerd Hoffmann
    req.override_mask =
839 97f155dd Gerd Hoffmann
        (conf.period_size_out_overridden ? 1 : 0) |
840 97f155dd Gerd Hoffmann
        (conf.buffer_size_out_overridden ? 2 : 0);
841 1d14ffa9 bellard
842 1d14ffa9 bellard
    if (alsa_open (0, &req, &obt, &handle)) {
843 1d14ffa9 bellard
        return -1;
844 1d14ffa9 bellard
    }
845 1d14ffa9 bellard
846 c0fe3827 bellard
    obt_as.freq = obt.freq;
847 c0fe3827 bellard
    obt_as.nchannels = obt.nchannels;
848 ca9cc28c balrog
    obt_as.fmt = obt.fmt;
849 ca9cc28c balrog
    obt_as.endianness = obt.endianness;
850 c0fe3827 bellard
851 d929eba5 bellard
    audio_pcm_init_info (&hw->info, &obt_as);
852 c0fe3827 bellard
    hw->samples = obt.samples;
853 1d14ffa9 bellard
854 c0fe3827 bellard
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
855 1d14ffa9 bellard
    if (!alsa->pcm_buf) {
856 4787c71d bellard
        dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n",
857 4787c71d bellard
               hw->samples, 1 << hw->info.shift);
858 6ebfda13 malc
        alsa_anal_close1 (&handle);
859 1d14ffa9 bellard
        return -1;
860 1d14ffa9 bellard
    }
861 1d14ffa9 bellard
862 1d14ffa9 bellard
    alsa->handle = handle;
863 1d14ffa9 bellard
    return 0;
864 1d14ffa9 bellard
}
865 1d14ffa9 bellard
866 38cc9b60 Jindrich Makovicka
#define VOICE_CTL_PAUSE 0
867 38cc9b60 Jindrich Makovicka
#define VOICE_CTL_PREPARE 1
868 38cc9b60 Jindrich Makovicka
#define VOICE_CTL_START 2
869 38cc9b60 Jindrich Makovicka
870 38cc9b60 Jindrich Makovicka
static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl)
871 1d14ffa9 bellard
{
872 1d14ffa9 bellard
    int err;
873 571ec3d6 bellard
874 38cc9b60 Jindrich Makovicka
    if (ctl == VOICE_CTL_PAUSE) {
875 571ec3d6 bellard
        err = snd_pcm_drop (handle);
876 571ec3d6 bellard
        if (err < 0) {
877 32d448c4 bellard
            alsa_logerr (err, "Could not stop %s\n", typ);
878 571ec3d6 bellard
            return -1;
879 571ec3d6 bellard
        }
880 571ec3d6 bellard
    }
881 571ec3d6 bellard
    else {
882 571ec3d6 bellard
        err = snd_pcm_prepare (handle);
883 571ec3d6 bellard
        if (err < 0) {
884 32d448c4 bellard
            alsa_logerr (err, "Could not prepare handle for %s\n", typ);
885 571ec3d6 bellard
            return -1;
886 571ec3d6 bellard
        }
887 38cc9b60 Jindrich Makovicka
        if (ctl == VOICE_CTL_START) {
888 38cc9b60 Jindrich Makovicka
            err = snd_pcm_start(handle);
889 38cc9b60 Jindrich Makovicka
            if (err < 0) {
890 38cc9b60 Jindrich Makovicka
                alsa_logerr (err, "Could not start handle for %s\n", typ);
891 38cc9b60 Jindrich Makovicka
                return -1;
892 38cc9b60 Jindrich Makovicka
            }
893 38cc9b60 Jindrich Makovicka
        }
894 571ec3d6 bellard
    }
895 571ec3d6 bellard
896 571ec3d6 bellard
    return 0;
897 571ec3d6 bellard
}
898 571ec3d6 bellard
899 571ec3d6 bellard
static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
900 571ec3d6 bellard
{
901 1d14ffa9 bellard
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
902 1d14ffa9 bellard
903 1d14ffa9 bellard
    switch (cmd) {
904 1d14ffa9 bellard
    case VOICE_ENABLE:
905 301901b5 malc
        {
906 301901b5 malc
            va_list ap;
907 301901b5 malc
            int poll_mode;
908 301901b5 malc
909 301901b5 malc
            va_start (ap, cmd);
910 301901b5 malc
            poll_mode = va_arg (ap, int);
911 301901b5 malc
            va_end (ap);
912 301901b5 malc
913 301901b5 malc
            ldebug ("enabling voice\n");
914 301901b5 malc
            if (poll_mode && alsa_poll_out (hw)) {
915 301901b5 malc
                poll_mode = 0;
916 301901b5 malc
            }
917 301901b5 malc
            hw->poll_mode = poll_mode;
918 38cc9b60 Jindrich Makovicka
            return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE);
919 8b438ba3 malc
        }
920 1d14ffa9 bellard
921 1d14ffa9 bellard
    case VOICE_DISABLE:
922 1d14ffa9 bellard
        ldebug ("disabling voice\n");
923 22d948a2 Jindrich Makovicka
        if (hw->poll_mode) {
924 22d948a2 Jindrich Makovicka
            hw->poll_mode = 0;
925 22d948a2 Jindrich Makovicka
            alsa_fini_poll (&alsa->pollhlp);
926 22d948a2 Jindrich Makovicka
        }
927 38cc9b60 Jindrich Makovicka
        return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE);
928 1d14ffa9 bellard
    }
929 571ec3d6 bellard
930 571ec3d6 bellard
    return -1;
931 1d14ffa9 bellard
}
932 1d14ffa9 bellard
933 1ea879e5 malc
static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
934 1d14ffa9 bellard
{
935 1d14ffa9 bellard
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
936 1d14ffa9 bellard
    struct alsa_params_req req;
937 1d14ffa9 bellard
    struct alsa_params_obt obt;
938 1d14ffa9 bellard
    snd_pcm_t *handle;
939 1ea879e5 malc
    struct audsettings obt_as;
940 1d14ffa9 bellard
941 d66bddd7 Michael Walle
    req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
942 c0fe3827 bellard
    req.freq = as->freq;
943 c0fe3827 bellard
    req.nchannels = as->nchannels;
944 1d14ffa9 bellard
    req.period_size = conf.period_size_in;
945 1d14ffa9 bellard
    req.buffer_size = conf.buffer_size_in;
946 7a24c800 malc
    req.size_in_usec = conf.size_in_usec_in;
947 97f155dd Gerd Hoffmann
    req.override_mask =
948 97f155dd Gerd Hoffmann
        (conf.period_size_in_overridden ? 1 : 0) |
949 97f155dd Gerd Hoffmann
        (conf.buffer_size_in_overridden ? 2 : 0);
950 1d14ffa9 bellard
951 1d14ffa9 bellard
    if (alsa_open (1, &req, &obt, &handle)) {
952 1d14ffa9 bellard
        return -1;
953 1d14ffa9 bellard
    }
954 1d14ffa9 bellard
955 c0fe3827 bellard
    obt_as.freq = obt.freq;
956 c0fe3827 bellard
    obt_as.nchannels = obt.nchannels;
957 ca9cc28c balrog
    obt_as.fmt = obt.fmt;
958 ca9cc28c balrog
    obt_as.endianness = obt.endianness;
959 c0fe3827 bellard
960 d929eba5 bellard
    audio_pcm_init_info (&hw->info, &obt_as);
961 c0fe3827 bellard
    hw->samples = obt.samples;
962 c0fe3827 bellard
963 c0fe3827 bellard
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
964 1d14ffa9 bellard
    if (!alsa->pcm_buf) {
965 4787c71d bellard
        dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
966 4787c71d bellard
               hw->samples, 1 << hw->info.shift);
967 6ebfda13 malc
        alsa_anal_close1 (&handle);
968 1d14ffa9 bellard
        return -1;
969 1d14ffa9 bellard
    }
970 1d14ffa9 bellard
971 1d14ffa9 bellard
    alsa->handle = handle;
972 1d14ffa9 bellard
    return 0;
973 1d14ffa9 bellard
}
974 1d14ffa9 bellard
975 1d14ffa9 bellard
static void alsa_fini_in (HWVoiceIn *hw)
976 1d14ffa9 bellard
{
977 1d14ffa9 bellard
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
978 1d14ffa9 bellard
979 6ebfda13 malc
    alsa_anal_close (&alsa->handle, &alsa->pollhlp);
980 1d14ffa9 bellard
981 1d14ffa9 bellard
    if (alsa->pcm_buf) {
982 1d14ffa9 bellard
        qemu_free (alsa->pcm_buf);
983 1d14ffa9 bellard
        alsa->pcm_buf = NULL;
984 1d14ffa9 bellard
    }
985 1d14ffa9 bellard
}
986 1d14ffa9 bellard
987 1d14ffa9 bellard
static int alsa_run_in (HWVoiceIn *hw)
988 1d14ffa9 bellard
{
989 1d14ffa9 bellard
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
990 1d14ffa9 bellard
    int hwshift = hw->info.shift;
991 1d14ffa9 bellard
    int i;
992 1d14ffa9 bellard
    int live = audio_pcm_hw_get_live_in (hw);
993 1d14ffa9 bellard
    int dead = hw->samples - live;
994 571ec3d6 bellard
    int decr;
995 1d14ffa9 bellard
    struct {
996 1d14ffa9 bellard
        int add;
997 1d14ffa9 bellard
        int len;
998 1d14ffa9 bellard
    } bufs[2] = {
999 98f9f48c malc
        { .add = hw->wpos, .len = 0 },
1000 98f9f48c malc
        { .add = 0,        .len = 0 }
1001 1d14ffa9 bellard
    };
1002 571ec3d6 bellard
    snd_pcm_sframes_t avail;
1003 1d14ffa9 bellard
    snd_pcm_uframes_t read_samples = 0;
1004 1d14ffa9 bellard
1005 1d14ffa9 bellard
    if (!dead) {
1006 1d14ffa9 bellard
        return 0;
1007 1d14ffa9 bellard
    }
1008 1d14ffa9 bellard
1009 571ec3d6 bellard
    avail = alsa_get_avail (alsa->handle);
1010 571ec3d6 bellard
    if (avail < 0) {
1011 571ec3d6 bellard
        dolog ("Could not get number of captured frames\n");
1012 571ec3d6 bellard
        return 0;
1013 571ec3d6 bellard
    }
1014 571ec3d6 bellard
1015 86635821 Bjรธrn Mork
    if (!avail) {
1016 86635821 Bjรธrn Mork
        snd_pcm_state_t state;
1017 86635821 Bjรธrn Mork
1018 86635821 Bjรธrn Mork
        state = snd_pcm_state (alsa->handle);
1019 86635821 Bjรธrn Mork
        switch (state) {
1020 86635821 Bjรธrn Mork
        case SND_PCM_STATE_PREPARED:
1021 86635821 Bjรธrn Mork
            avail = hw->samples;
1022 86635821 Bjรธrn Mork
            break;
1023 86635821 Bjรธrn Mork
        case SND_PCM_STATE_SUSPENDED:
1024 86635821 Bjรธrn Mork
            /* stream is suspended and waiting for an application recovery */
1025 86635821 Bjรธrn Mork
            if (alsa_resume (alsa->handle)) {
1026 86635821 Bjรธrn Mork
                dolog ("Failed to resume suspended input stream\n");
1027 86635821 Bjรธrn Mork
                return 0;
1028 86635821 Bjรธrn Mork
            }
1029 86635821 Bjรธrn Mork
            if (conf.verbose) {
1030 86635821 Bjรธrn Mork
                dolog ("Resuming suspended input stream\n");
1031 86635821 Bjรธrn Mork
            }
1032 86635821 Bjรธrn Mork
            break;
1033 86635821 Bjรธrn Mork
        default:
1034 86635821 Bjรธrn Mork
            if (conf.verbose) {
1035 86635821 Bjรธrn Mork
                dolog ("No frames available and ALSA state is %d\n", state);
1036 86635821 Bjรธrn Mork
            }
1037 86635821 Bjรธrn Mork
            return 0;
1038 86635821 Bjรธrn Mork
        }
1039 571ec3d6 bellard
    }
1040 571ec3d6 bellard
1041 571ec3d6 bellard
    decr = audio_MIN (dead, avail);
1042 571ec3d6 bellard
    if (!decr) {
1043 571ec3d6 bellard
        return 0;
1044 571ec3d6 bellard
    }
1045 571ec3d6 bellard
1046 571ec3d6 bellard
    if (hw->wpos + decr > hw->samples) {
1047 1d14ffa9 bellard
        bufs[0].len = (hw->samples - hw->wpos);
1048 571ec3d6 bellard
        bufs[1].len = (decr - (hw->samples - hw->wpos));
1049 1d14ffa9 bellard
    }
1050 1d14ffa9 bellard
    else {
1051 571ec3d6 bellard
        bufs[0].len = decr;
1052 1d14ffa9 bellard
    }
1053 1d14ffa9 bellard
1054 1d14ffa9 bellard
    for (i = 0; i < 2; ++i) {
1055 1d14ffa9 bellard
        void *src;
1056 1ea879e5 malc
        struct st_sample *dst;
1057 1d14ffa9 bellard
        snd_pcm_sframes_t nread;
1058 1d14ffa9 bellard
        snd_pcm_uframes_t len;
1059 1d14ffa9 bellard
1060 1d14ffa9 bellard
        len = bufs[i].len;
1061 1d14ffa9 bellard
1062 1d14ffa9 bellard
        src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
1063 1d14ffa9 bellard
        dst = hw->conv_buf + bufs[i].add;
1064 1d14ffa9 bellard
1065 1d14ffa9 bellard
        while (len) {
1066 1d14ffa9 bellard
            nread = snd_pcm_readi (alsa->handle, src, len);
1067 1d14ffa9 bellard
1068 571ec3d6 bellard
            if (nread <= 0) {
1069 1d14ffa9 bellard
                switch (nread) {
1070 571ec3d6 bellard
                case 0:
1071 571ec3d6 bellard
                    if (conf.verbose) {
1072 571ec3d6 bellard
                        dolog ("Failed to read %ld frames (read zero)\n", len);
1073 1d14ffa9 bellard
                    }
1074 1d14ffa9 bellard
                    goto exit;
1075 1d14ffa9 bellard
1076 571ec3d6 bellard
                case -EPIPE:
1077 571ec3d6 bellard
                    if (alsa_recover (alsa->handle)) {
1078 571ec3d6 bellard
                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
1079 571ec3d6 bellard
                        goto exit;
1080 571ec3d6 bellard
                    }
1081 571ec3d6 bellard
                    if (conf.verbose) {
1082 571ec3d6 bellard
                        dolog ("Recovering from capture xrun\n");
1083 571ec3d6 bellard
                    }
1084 1d14ffa9 bellard
                    continue;
1085 1d14ffa9 bellard
1086 571ec3d6 bellard
                case -EAGAIN:
1087 571ec3d6 bellard
                    goto exit;
1088 571ec3d6 bellard
1089 1d14ffa9 bellard
                default:
1090 1d14ffa9 bellard
                    alsa_logerr (
1091 1d14ffa9 bellard
                        nread,
1092 1d14ffa9 bellard
                        "Failed to read %ld frames from %p\n",
1093 1d14ffa9 bellard
                        len,
1094 1d14ffa9 bellard
                        src
1095 1d14ffa9 bellard
                        );
1096 1d14ffa9 bellard
                    goto exit;
1097 1d14ffa9 bellard
                }
1098 1d14ffa9 bellard
            }
1099 1d14ffa9 bellard
1100 00e07679 Michael Walle
            hw->conv (dst, src, nread);
1101 1d14ffa9 bellard
1102 1d14ffa9 bellard
            src = advance (src, nread << hwshift);
1103 1d14ffa9 bellard
            dst += nread;
1104 1d14ffa9 bellard
1105 1d14ffa9 bellard
            read_samples += nread;
1106 1d14ffa9 bellard
            len -= nread;
1107 1d14ffa9 bellard
        }
1108 1d14ffa9 bellard
    }
1109 1d14ffa9 bellard
1110 1d14ffa9 bellard
 exit:
1111 1d14ffa9 bellard
    hw->wpos = (hw->wpos + read_samples) % hw->samples;
1112 1d14ffa9 bellard
    return read_samples;
1113 1d14ffa9 bellard
}
1114 1d14ffa9 bellard
1115 1d14ffa9 bellard
static int alsa_read (SWVoiceIn *sw, void *buf, int size)
1116 1d14ffa9 bellard
{
1117 1d14ffa9 bellard
    return audio_pcm_sw_read (sw, buf, size);
1118 1d14ffa9 bellard
}
1119 1d14ffa9 bellard
1120 1d14ffa9 bellard
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
1121 1d14ffa9 bellard
{
1122 571ec3d6 bellard
    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
1123 571ec3d6 bellard
1124 571ec3d6 bellard
    switch (cmd) {
1125 571ec3d6 bellard
    case VOICE_ENABLE:
1126 a628b869 malc
        {
1127 a628b869 malc
            va_list ap;
1128 a628b869 malc
            int poll_mode;
1129 8b438ba3 malc
1130 a628b869 malc
            va_start (ap, cmd);
1131 a628b869 malc
            poll_mode = va_arg (ap, int);
1132 a628b869 malc
            va_end (ap);
1133 a628b869 malc
1134 a628b869 malc
            ldebug ("enabling voice\n");
1135 a628b869 malc
            if (poll_mode && alsa_poll_in (hw)) {
1136 a628b869 malc
                poll_mode = 0;
1137 a628b869 malc
            }
1138 a628b869 malc
            hw->poll_mode = poll_mode;
1139 a628b869 malc
1140 38cc9b60 Jindrich Makovicka
            return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START);
1141 a628b869 malc
        }
1142 571ec3d6 bellard
1143 571ec3d6 bellard
    case VOICE_DISABLE:
1144 571ec3d6 bellard
        ldebug ("disabling voice\n");
1145 8b438ba3 malc
        if (hw->poll_mode) {
1146 8b438ba3 malc
            hw->poll_mode = 0;
1147 8b438ba3 malc
            alsa_fini_poll (&alsa->pollhlp);
1148 8b438ba3 malc
        }
1149 38cc9b60 Jindrich Makovicka
        return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE);
1150 571ec3d6 bellard
    }
1151 571ec3d6 bellard
1152 571ec3d6 bellard
    return -1;
1153 1d14ffa9 bellard
}
1154 1d14ffa9 bellard
1155 1d14ffa9 bellard
static void *alsa_audio_init (void)
1156 1d14ffa9 bellard
{
1157 1d14ffa9 bellard
    return &conf;
1158 1d14ffa9 bellard
}
1159 1d14ffa9 bellard
1160 1d14ffa9 bellard
static void alsa_audio_fini (void *opaque)
1161 1d14ffa9 bellard
{
1162 1d14ffa9 bellard
    (void) opaque;
1163 1d14ffa9 bellard
}
1164 1d14ffa9 bellard
1165 1d14ffa9 bellard
static struct audio_option alsa_options[] = {
1166 98f9f48c malc
    {
1167 98f9f48c malc
        .name        = "DAC_SIZE_IN_USEC",
1168 98f9f48c malc
        .tag         = AUD_OPT_BOOL,
1169 98f9f48c malc
        .valp        = &conf.size_in_usec_out,
1170 98f9f48c malc
        .descr       = "DAC period/buffer size in microseconds (otherwise in frames)"
1171 98f9f48c malc
    },
1172 98f9f48c malc
    {
1173 98f9f48c malc
        .name        = "DAC_PERIOD_SIZE",
1174 98f9f48c malc
        .tag         = AUD_OPT_INT,
1175 98f9f48c malc
        .valp        = &conf.period_size_out,
1176 98f9f48c malc
        .descr       = "DAC period size (0 to go with system default)",
1177 98f9f48c malc
        .overriddenp = &conf.period_size_out_overridden
1178 98f9f48c malc
    },
1179 98f9f48c malc
    {
1180 98f9f48c malc
        .name        = "DAC_BUFFER_SIZE",
1181 98f9f48c malc
        .tag         = AUD_OPT_INT,
1182 98f9f48c malc
        .valp        = &conf.buffer_size_out,
1183 98f9f48c malc
        .descr       = "DAC buffer size (0 to go with system default)",
1184 98f9f48c malc
        .overriddenp = &conf.buffer_size_out_overridden
1185 98f9f48c malc
    },
1186 98f9f48c malc
    {
1187 98f9f48c malc
        .name        = "ADC_SIZE_IN_USEC",
1188 98f9f48c malc
        .tag         = AUD_OPT_BOOL,
1189 98f9f48c malc
        .valp        = &conf.size_in_usec_in,
1190 98f9f48c malc
        .descr       =
1191 98f9f48c malc
        "ADC period/buffer size in microseconds (otherwise in frames)"
1192 98f9f48c malc
    },
1193 98f9f48c malc
    {
1194 98f9f48c malc
        .name        = "ADC_PERIOD_SIZE",
1195 98f9f48c malc
        .tag         = AUD_OPT_INT,
1196 98f9f48c malc
        .valp        = &conf.period_size_in,
1197 98f9f48c malc
        .descr       = "ADC period size (0 to go with system default)",
1198 98f9f48c malc
        .overriddenp = &conf.period_size_in_overridden
1199 98f9f48c malc
    },
1200 98f9f48c malc
    {
1201 98f9f48c malc
        .name        = "ADC_BUFFER_SIZE",
1202 98f9f48c malc
        .tag         = AUD_OPT_INT,
1203 98f9f48c malc
        .valp        = &conf.buffer_size_in,
1204 98f9f48c malc
        .descr       = "ADC buffer size (0 to go with system default)",
1205 98f9f48c malc
        .overriddenp = &conf.buffer_size_in_overridden
1206 98f9f48c malc
    },
1207 98f9f48c malc
    {
1208 98f9f48c malc
        .name        = "THRESHOLD",
1209 98f9f48c malc
        .tag         = AUD_OPT_INT,
1210 98f9f48c malc
        .valp        = &conf.threshold,
1211 98f9f48c malc
        .descr       = "(undocumented)"
1212 98f9f48c malc
    },
1213 98f9f48c malc
    {
1214 98f9f48c malc
        .name        = "DAC_DEV",
1215 98f9f48c malc
        .tag         = AUD_OPT_STR,
1216 98f9f48c malc
        .valp        = &conf.pcm_name_out,
1217 98f9f48c malc
        .descr       = "DAC device name (for instance dmix)"
1218 98f9f48c malc
    },
1219 98f9f48c malc
    {
1220 98f9f48c malc
        .name        = "ADC_DEV",
1221 98f9f48c malc
        .tag         = AUD_OPT_STR,
1222 98f9f48c malc
        .valp        = &conf.pcm_name_in,
1223 98f9f48c malc
        .descr       = "ADC device name"
1224 98f9f48c malc
    },
1225 98f9f48c malc
    {
1226 98f9f48c malc
        .name        = "VERBOSE",
1227 98f9f48c malc
        .tag         = AUD_OPT_BOOL,
1228 98f9f48c malc
        .valp        = &conf.verbose,
1229 98f9f48c malc
        .descr       = "Behave in a more verbose way"
1230 98f9f48c malc
    },
1231 2700efa3 Juan Quintela
    { /* End of list */ }
1232 1d14ffa9 bellard
};
1233 1d14ffa9 bellard
1234 35f4b58c blueswir1
static struct audio_pcm_ops alsa_pcm_ops = {
1235 1dd3e4d1 Juan Quintela
    .init_out = alsa_init_out,
1236 1dd3e4d1 Juan Quintela
    .fini_out = alsa_fini_out,
1237 1dd3e4d1 Juan Quintela
    .run_out  = alsa_run_out,
1238 1dd3e4d1 Juan Quintela
    .write    = alsa_write,
1239 1dd3e4d1 Juan Quintela
    .ctl_out  = alsa_ctl_out,
1240 1dd3e4d1 Juan Quintela
1241 1dd3e4d1 Juan Quintela
    .init_in  = alsa_init_in,
1242 1dd3e4d1 Juan Quintela
    .fini_in  = alsa_fini_in,
1243 1dd3e4d1 Juan Quintela
    .run_in   = alsa_run_in,
1244 1dd3e4d1 Juan Quintela
    .read     = alsa_read,
1245 8b438ba3 malc
    .ctl_in   = alsa_ctl_in,
1246 1d14ffa9 bellard
};
1247 1d14ffa9 bellard
1248 1d14ffa9 bellard
struct audio_driver alsa_audio_driver = {
1249 bee37f32 Juan Quintela
    .name           = "alsa",
1250 bee37f32 Juan Quintela
    .descr          = "ALSA http://www.alsa-project.org",
1251 bee37f32 Juan Quintela
    .options        = alsa_options,
1252 bee37f32 Juan Quintela
    .init           = alsa_audio_init,
1253 bee37f32 Juan Quintela
    .fini           = alsa_audio_fini,
1254 bee37f32 Juan Quintela
    .pcm_ops        = &alsa_pcm_ops,
1255 bee37f32 Juan Quintela
    .can_be_default = 1,
1256 bee37f32 Juan Quintela
    .max_voices_out = INT_MAX,
1257 bee37f32 Juan Quintela
    .max_voices_in  = INT_MAX,
1258 bee37f32 Juan Quintela
    .voice_size_out = sizeof (ALSAVoiceOut),
1259 bee37f32 Juan Quintela
    .voice_size_in  = sizeof (ALSAVoiceIn)
1260 1d14ffa9 bellard
};