Statistics
| Branch: | Revision:

root / audio / esdaudio.c @ cf2c1839

History | View | Annotate | Download (13.5 kB)

1 ca9cc28c balrog
/*
2 ca9cc28c balrog
 * QEMU ESD audio driver
3 ca9cc28c balrog
 *
4 ca9cc28c balrog
 * Copyright (c) 2006 Frederick Reeve (brushed up by malc)
5 ca9cc28c balrog
 *
6 ca9cc28c balrog
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 ca9cc28c balrog
 * of this software and associated documentation files (the "Software"), to deal
8 ca9cc28c balrog
 * in the Software without restriction, including without limitation the rights
9 ca9cc28c balrog
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ca9cc28c balrog
 * copies of the Software, and to permit persons to whom the Software is
11 ca9cc28c balrog
 * furnished to do so, subject to the following conditions:
12 ca9cc28c balrog
 *
13 ca9cc28c balrog
 * The above copyright notice and this permission notice shall be included in
14 ca9cc28c balrog
 * all copies or substantial portions of the Software.
15 ca9cc28c balrog
 *
16 ca9cc28c balrog
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 ca9cc28c balrog
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 ca9cc28c balrog
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 ca9cc28c balrog
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 ca9cc28c balrog
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 ca9cc28c balrog
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 ca9cc28c balrog
 * THE SOFTWARE.
23 ca9cc28c balrog
 */
24 ca9cc28c balrog
#include <esd.h>
25 ca9cc28c balrog
#include "qemu-common.h"
26 ca9cc28c balrog
#include "audio.h"
27 ca9cc28c balrog
28 ca9cc28c balrog
#define AUDIO_CAP "esd"
29 ca9cc28c balrog
#include "audio_int.h"
30 ca9cc28c balrog
#include "audio_pt_int.h"
31 ca9cc28c balrog
32 ca9cc28c balrog
typedef struct {
33 ca9cc28c balrog
    HWVoiceOut hw;
34 ca9cc28c balrog
    int done;
35 ca9cc28c balrog
    int live;
36 ca9cc28c balrog
    int decr;
37 ca9cc28c balrog
    int rpos;
38 ca9cc28c balrog
    void *pcm_buf;
39 ca9cc28c balrog
    int fd;
40 ca9cc28c balrog
    struct audio_pt pt;
41 ca9cc28c balrog
} ESDVoiceOut;
42 ca9cc28c balrog
43 ca9cc28c balrog
typedef struct {
44 ca9cc28c balrog
    HWVoiceIn hw;
45 ca9cc28c balrog
    int done;
46 ca9cc28c balrog
    int dead;
47 ca9cc28c balrog
    int incr;
48 ca9cc28c balrog
    int wpos;
49 ca9cc28c balrog
    void *pcm_buf;
50 ca9cc28c balrog
    int fd;
51 ca9cc28c balrog
    struct audio_pt pt;
52 ca9cc28c balrog
} ESDVoiceIn;
53 ca9cc28c balrog
54 ca9cc28c balrog
static struct {
55 ca9cc28c balrog
    int samples;
56 ca9cc28c balrog
    int divisor;
57 ca9cc28c balrog
    char *dac_host;
58 ca9cc28c balrog
    char *adc_host;
59 ca9cc28c balrog
} conf = {
60 1a40d5e2 Juan Quintela
    .samples = 1024,
61 1a40d5e2 Juan Quintela
    .divisor = 2,
62 ca9cc28c balrog
};
63 ca9cc28c balrog
64 ca9cc28c balrog
static void GCC_FMT_ATTR (2, 3) qesd_logerr (int err, const char *fmt, ...)
65 ca9cc28c balrog
{
66 ca9cc28c balrog
    va_list ap;
67 ca9cc28c balrog
68 ca9cc28c balrog
    va_start (ap, fmt);
69 ca9cc28c balrog
    AUD_vlog (AUDIO_CAP, fmt, ap);
70 ca9cc28c balrog
    va_end (ap);
71 ca9cc28c balrog
72 ca9cc28c balrog
    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
73 ca9cc28c balrog
}
74 ca9cc28c balrog
75 ca9cc28c balrog
/* playback */
76 ca9cc28c balrog
static void *qesd_thread_out (void *arg)
77 ca9cc28c balrog
{
78 ca9cc28c balrog
    ESDVoiceOut *esd = arg;
79 ca9cc28c balrog
    HWVoiceOut *hw = &esd->hw;
80 ca9cc28c balrog
    int threshold;
81 ca9cc28c balrog
82 ca9cc28c balrog
    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
83 ca9cc28c balrog
84 deb9d2ee balrog
    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
85 deb9d2ee balrog
        return NULL;
86 deb9d2ee balrog
    }
87 deb9d2ee balrog
88 ca9cc28c balrog
    for (;;) {
89 ca9cc28c balrog
        int decr, to_mix, rpos;
90 ca9cc28c balrog
91 ca9cc28c balrog
        for (;;) {
92 ca9cc28c balrog
            if (esd->done) {
93 ca9cc28c balrog
                goto exit;
94 ca9cc28c balrog
            }
95 ca9cc28c balrog
96 ca9cc28c balrog
            if (esd->live > threshold) {
97 ca9cc28c balrog
                break;
98 ca9cc28c balrog
            }
99 ca9cc28c balrog
100 ca9cc28c balrog
            if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
101 ca9cc28c balrog
                goto exit;
102 ca9cc28c balrog
            }
103 ca9cc28c balrog
        }
104 ca9cc28c balrog
105 ca9cc28c balrog
        decr = to_mix = esd->live;
106 ca9cc28c balrog
        rpos = hw->rpos;
107 ca9cc28c balrog
108 ca9cc28c balrog
        if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
109 ca9cc28c balrog
            return NULL;
110 ca9cc28c balrog
        }
111 ca9cc28c balrog
112 ca9cc28c balrog
        while (to_mix) {
113 ca9cc28c balrog
            ssize_t written;
114 ca9cc28c balrog
            int chunk = audio_MIN (to_mix, hw->samples - rpos);
115 1ea879e5 malc
            struct st_sample *src = hw->mix_buf + rpos;
116 ca9cc28c balrog
117 ca9cc28c balrog
            hw->clip (esd->pcm_buf, src, chunk);
118 ca9cc28c balrog
119 ca9cc28c balrog
        again:
120 ca9cc28c balrog
            written = write (esd->fd, esd->pcm_buf, chunk << hw->info.shift);
121 ca9cc28c balrog
            if (written == -1) {
122 ca9cc28c balrog
                if (errno == EINTR || errno == EAGAIN) {
123 ca9cc28c balrog
                    goto again;
124 ca9cc28c balrog
                }
125 ca9cc28c balrog
                qesd_logerr (errno, "write failed\n");
126 ca9cc28c balrog
                return NULL;
127 ca9cc28c balrog
            }
128 ca9cc28c balrog
129 ca9cc28c balrog
            if (written != chunk << hw->info.shift) {
130 ca9cc28c balrog
                int wsamples = written >> hw->info.shift;
131 ca9cc28c balrog
                int wbytes = wsamples << hw->info.shift;
132 ca9cc28c balrog
                if (wbytes != written) {
133 f9c7b77c Kirill A. Shutemov
                    dolog ("warning: Misaligned write %d (requested %zd), "
134 ca9cc28c balrog
                           "alignment %d\n",
135 ca9cc28c balrog
                           wbytes, written, hw->info.align + 1);
136 ca9cc28c balrog
                }
137 ca9cc28c balrog
                to_mix -= wsamples;
138 ca9cc28c balrog
                rpos = (rpos + wsamples) % hw->samples;
139 ca9cc28c balrog
                break;
140 ca9cc28c balrog
            }
141 ca9cc28c balrog
142 ca9cc28c balrog
            rpos = (rpos + chunk) % hw->samples;
143 ca9cc28c balrog
            to_mix -= chunk;
144 ca9cc28c balrog
        }
145 ca9cc28c balrog
146 ca9cc28c balrog
        if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
147 ca9cc28c balrog
            return NULL;
148 ca9cc28c balrog
        }
149 ca9cc28c balrog
150 ca9cc28c balrog
        esd->rpos = rpos;
151 ca9cc28c balrog
        esd->live -= decr;
152 ca9cc28c balrog
        esd->decr += decr;
153 ca9cc28c balrog
    }
154 ca9cc28c balrog
155 ca9cc28c balrog
 exit:
156 ca9cc28c balrog
    audio_pt_unlock (&esd->pt, AUDIO_FUNC);
157 ca9cc28c balrog
    return NULL;
158 ca9cc28c balrog
}
159 ca9cc28c balrog
160 bdff253c malc
static int qesd_run_out (HWVoiceOut *hw, int live)
161 ca9cc28c balrog
{
162 bdff253c malc
    int decr;
163 ca9cc28c balrog
    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
164 ca9cc28c balrog
165 ca9cc28c balrog
    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
166 ca9cc28c balrog
        return 0;
167 ca9cc28c balrog
    }
168 ca9cc28c balrog
169 ca9cc28c balrog
    decr = audio_MIN (live, esd->decr);
170 ca9cc28c balrog
    esd->decr -= decr;
171 ca9cc28c balrog
    esd->live = live - decr;
172 ca9cc28c balrog
    hw->rpos = esd->rpos;
173 ca9cc28c balrog
    if (esd->live > 0) {
174 ca9cc28c balrog
        audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
175 ca9cc28c balrog
    }
176 ca9cc28c balrog
    else {
177 ca9cc28c balrog
        audio_pt_unlock (&esd->pt, AUDIO_FUNC);
178 ca9cc28c balrog
    }
179 ca9cc28c balrog
    return decr;
180 ca9cc28c balrog
}
181 ca9cc28c balrog
182 ca9cc28c balrog
static int qesd_write (SWVoiceOut *sw, void *buf, int len)
183 ca9cc28c balrog
{
184 ca9cc28c balrog
    return audio_pcm_sw_write (sw, buf, len);
185 ca9cc28c balrog
}
186 ca9cc28c balrog
187 1ea879e5 malc
static int qesd_init_out (HWVoiceOut *hw, struct audsettings *as)
188 ca9cc28c balrog
{
189 ca9cc28c balrog
    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
190 1ea879e5 malc
    struct audsettings obt_as = *as;
191 ca9cc28c balrog
    int esdfmt = ESD_STREAM | ESD_PLAY;
192 ca9cc28c balrog
193 ca9cc28c balrog
    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
194 ca9cc28c balrog
    switch (as->fmt) {
195 ca9cc28c balrog
    case AUD_FMT_S8:
196 ca9cc28c balrog
    case AUD_FMT_U8:
197 ca9cc28c balrog
        esdfmt |= ESD_BITS8;
198 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_U8;
199 ca9cc28c balrog
        break;
200 ca9cc28c balrog
201 ca9cc28c balrog
    case AUD_FMT_S32:
202 ca9cc28c balrog
    case AUD_FMT_U32:
203 ca9cc28c balrog
        dolog ("Will use 16 instead of 32 bit samples\n");
204 ca9cc28c balrog
205 ca9cc28c balrog
    case AUD_FMT_S16:
206 ca9cc28c balrog
    case AUD_FMT_U16:
207 ca9cc28c balrog
    deffmt:
208 ca9cc28c balrog
        esdfmt |= ESD_BITS16;
209 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_S16;
210 ca9cc28c balrog
        break;
211 ca9cc28c balrog
212 ca9cc28c balrog
    default:
213 ca9cc28c balrog
        dolog ("Internal logic error: Bad audio format %d\n", as->fmt);
214 ca9cc28c balrog
        goto deffmt;
215 ca9cc28c balrog
216 ca9cc28c balrog
    }
217 deb9d2ee balrog
    obt_as.endianness = AUDIO_HOST_ENDIANNESS;
218 ca9cc28c balrog
219 ca9cc28c balrog
    audio_pcm_init_info (&hw->info, &obt_as);
220 ca9cc28c balrog
221 ca9cc28c balrog
    hw->samples = conf.samples;
222 ca9cc28c balrog
    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
223 ca9cc28c balrog
    if (!esd->pcm_buf) {
224 ca9cc28c balrog
        dolog ("Could not allocate buffer (%d bytes)\n",
225 ca9cc28c balrog
               hw->samples << hw->info.shift);
226 ca9cc28c balrog
        return -1;
227 ca9cc28c balrog
    }
228 ca9cc28c balrog
229 ca9cc28c balrog
    esd->fd = esd_play_stream (esdfmt, as->freq, conf.dac_host, NULL);
230 ca9cc28c balrog
    if (esd->fd < 0) {
231 ca9cc28c balrog
        qesd_logerr (errno, "esd_play_stream failed\n");
232 4b7c0418 malc
        goto fail1;
233 ca9cc28c balrog
    }
234 ca9cc28c balrog
235 ca9cc28c balrog
    if (audio_pt_init (&esd->pt, qesd_thread_out, esd, AUDIO_CAP, AUDIO_FUNC)) {
236 4b7c0418 malc
        goto fail2;
237 ca9cc28c balrog
    }
238 ca9cc28c balrog
239 ca9cc28c balrog
    return 0;
240 ca9cc28c balrog
241 4b7c0418 malc
 fail2:
242 ca9cc28c balrog
    if (close (esd->fd)) {
243 ca9cc28c balrog
        qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
244 ca9cc28c balrog
                     AUDIO_FUNC, esd->fd);
245 ca9cc28c balrog
    }
246 ca9cc28c balrog
    esd->fd = -1;
247 ca9cc28c balrog
248 ca9cc28c balrog
 fail1:
249 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
250 ca9cc28c balrog
    esd->pcm_buf = NULL;
251 ca9cc28c balrog
    return -1;
252 ca9cc28c balrog
}
253 ca9cc28c balrog
254 ca9cc28c balrog
static void qesd_fini_out (HWVoiceOut *hw)
255 ca9cc28c balrog
{
256 ca9cc28c balrog
    void *ret;
257 ca9cc28c balrog
    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
258 ca9cc28c balrog
259 ca9cc28c balrog
    audio_pt_lock (&esd->pt, AUDIO_FUNC);
260 ca9cc28c balrog
    esd->done = 1;
261 ca9cc28c balrog
    audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
262 ca9cc28c balrog
    audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
263 ca9cc28c balrog
264 ca9cc28c balrog
    if (esd->fd >= 0) {
265 ca9cc28c balrog
        if (close (esd->fd)) {
266 ca9cc28c balrog
            qesd_logerr (errno, "failed to close esd socket\n");
267 ca9cc28c balrog
        }
268 ca9cc28c balrog
        esd->fd = -1;
269 ca9cc28c balrog
    }
270 ca9cc28c balrog
271 ca9cc28c balrog
    audio_pt_fini (&esd->pt, AUDIO_FUNC);
272 ca9cc28c balrog
273 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
274 ca9cc28c balrog
    esd->pcm_buf = NULL;
275 ca9cc28c balrog
}
276 ca9cc28c balrog
277 ca9cc28c balrog
static int qesd_ctl_out (HWVoiceOut *hw, int cmd, ...)
278 ca9cc28c balrog
{
279 ca9cc28c balrog
    (void) hw;
280 ca9cc28c balrog
    (void) cmd;
281 ca9cc28c balrog
    return 0;
282 ca9cc28c balrog
}
283 ca9cc28c balrog
284 ca9cc28c balrog
/* capture */
285 ca9cc28c balrog
static void *qesd_thread_in (void *arg)
286 ca9cc28c balrog
{
287 ca9cc28c balrog
    ESDVoiceIn *esd = arg;
288 ca9cc28c balrog
    HWVoiceIn *hw = &esd->hw;
289 ca9cc28c balrog
    int threshold;
290 ca9cc28c balrog
291 ca9cc28c balrog
    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
292 ca9cc28c balrog
293 deb9d2ee balrog
    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
294 deb9d2ee balrog
        return NULL;
295 deb9d2ee balrog
    }
296 deb9d2ee balrog
297 ca9cc28c balrog
    for (;;) {
298 ca9cc28c balrog
        int incr, to_grab, wpos;
299 ca9cc28c balrog
300 ca9cc28c balrog
        for (;;) {
301 ca9cc28c balrog
            if (esd->done) {
302 ca9cc28c balrog
                goto exit;
303 ca9cc28c balrog
            }
304 ca9cc28c balrog
305 ca9cc28c balrog
            if (esd->dead > threshold) {
306 ca9cc28c balrog
                break;
307 ca9cc28c balrog
            }
308 ca9cc28c balrog
309 ca9cc28c balrog
            if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
310 ca9cc28c balrog
                goto exit;
311 ca9cc28c balrog
            }
312 ca9cc28c balrog
        }
313 ca9cc28c balrog
314 ca9cc28c balrog
        incr = to_grab = esd->dead;
315 ca9cc28c balrog
        wpos = hw->wpos;
316 ca9cc28c balrog
317 ca9cc28c balrog
        if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
318 ca9cc28c balrog
            return NULL;
319 ca9cc28c balrog
        }
320 ca9cc28c balrog
321 ca9cc28c balrog
        while (to_grab) {
322 ca9cc28c balrog
            ssize_t nread;
323 ca9cc28c balrog
            int chunk = audio_MIN (to_grab, hw->samples - wpos);
324 ca9cc28c balrog
            void *buf = advance (esd->pcm_buf, wpos);
325 ca9cc28c balrog
326 ca9cc28c balrog
        again:
327 ca9cc28c balrog
            nread = read (esd->fd, buf, chunk << hw->info.shift);
328 ca9cc28c balrog
            if (nread == -1) {
329 ca9cc28c balrog
                if (errno == EINTR || errno == EAGAIN) {
330 ca9cc28c balrog
                    goto again;
331 ca9cc28c balrog
                }
332 ca9cc28c balrog
                qesd_logerr (errno, "read failed\n");
333 ca9cc28c balrog
                return NULL;
334 ca9cc28c balrog
            }
335 ca9cc28c balrog
336 ca9cc28c balrog
            if (nread != chunk << hw->info.shift) {
337 ca9cc28c balrog
                int rsamples = nread >> hw->info.shift;
338 ca9cc28c balrog
                int rbytes = rsamples << hw->info.shift;
339 ca9cc28c balrog
                if (rbytes != nread) {
340 f9c7b77c Kirill A. Shutemov
                    dolog ("warning: Misaligned write %d (requested %zd), "
341 ca9cc28c balrog
                           "alignment %d\n",
342 ca9cc28c balrog
                           rbytes, nread, hw->info.align + 1);
343 ca9cc28c balrog
                }
344 ca9cc28c balrog
                to_grab -= rsamples;
345 ca9cc28c balrog
                wpos = (wpos + rsamples) % hw->samples;
346 ca9cc28c balrog
                break;
347 ca9cc28c balrog
            }
348 ca9cc28c balrog
349 ca9cc28c balrog
            hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift,
350 ca9cc28c balrog
                      &nominal_volume);
351 ca9cc28c balrog
            wpos = (wpos + chunk) % hw->samples;
352 ca9cc28c balrog
            to_grab -= chunk;
353 ca9cc28c balrog
        }
354 ca9cc28c balrog
355 ca9cc28c balrog
        if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
356 ca9cc28c balrog
            return NULL;
357 ca9cc28c balrog
        }
358 ca9cc28c balrog
359 ca9cc28c balrog
        esd->wpos = wpos;
360 ca9cc28c balrog
        esd->dead -= incr;
361 ca9cc28c balrog
        esd->incr += incr;
362 ca9cc28c balrog
    }
363 ca9cc28c balrog
364 ca9cc28c balrog
 exit:
365 ca9cc28c balrog
    audio_pt_unlock (&esd->pt, AUDIO_FUNC);
366 ca9cc28c balrog
    return NULL;
367 ca9cc28c balrog
}
368 ca9cc28c balrog
369 ca9cc28c balrog
static int qesd_run_in (HWVoiceIn *hw)
370 ca9cc28c balrog
{
371 ca9cc28c balrog
    int live, incr, dead;
372 ca9cc28c balrog
    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
373 ca9cc28c balrog
374 ca9cc28c balrog
    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
375 ca9cc28c balrog
        return 0;
376 ca9cc28c balrog
    }
377 ca9cc28c balrog
378 ca9cc28c balrog
    live = audio_pcm_hw_get_live_in (hw);
379 ca9cc28c balrog
    dead = hw->samples - live;
380 ca9cc28c balrog
    incr = audio_MIN (dead, esd->incr);
381 ca9cc28c balrog
    esd->incr -= incr;
382 ca9cc28c balrog
    esd->dead = dead - incr;
383 ca9cc28c balrog
    hw->wpos = esd->wpos;
384 ca9cc28c balrog
    if (esd->dead > 0) {
385 ca9cc28c balrog
        audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
386 ca9cc28c balrog
    }
387 ca9cc28c balrog
    else {
388 ca9cc28c balrog
        audio_pt_unlock (&esd->pt, AUDIO_FUNC);
389 ca9cc28c balrog
    }
390 ca9cc28c balrog
    return incr;
391 ca9cc28c balrog
}
392 ca9cc28c balrog
393 ca9cc28c balrog
static int qesd_read (SWVoiceIn *sw, void *buf, int len)
394 ca9cc28c balrog
{
395 ca9cc28c balrog
    return audio_pcm_sw_read (sw, buf, len);
396 ca9cc28c balrog
}
397 ca9cc28c balrog
398 1ea879e5 malc
static int qesd_init_in (HWVoiceIn *hw, struct audsettings *as)
399 ca9cc28c balrog
{
400 ca9cc28c balrog
    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
401 1ea879e5 malc
    struct audsettings obt_as = *as;
402 ca9cc28c balrog
    int esdfmt = ESD_STREAM | ESD_RECORD;
403 ca9cc28c balrog
404 ca9cc28c balrog
    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
405 ca9cc28c balrog
    switch (as->fmt) {
406 ca9cc28c balrog
    case AUD_FMT_S8:
407 ca9cc28c balrog
    case AUD_FMT_U8:
408 ca9cc28c balrog
        esdfmt |= ESD_BITS8;
409 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_U8;
410 ca9cc28c balrog
        break;
411 ca9cc28c balrog
412 ca9cc28c balrog
    case AUD_FMT_S16:
413 ca9cc28c balrog
    case AUD_FMT_U16:
414 ca9cc28c balrog
        esdfmt |= ESD_BITS16;
415 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_S16;
416 ca9cc28c balrog
        break;
417 ca9cc28c balrog
418 ca9cc28c balrog
    case AUD_FMT_S32:
419 ca9cc28c balrog
    case AUD_FMT_U32:
420 ca9cc28c balrog
        dolog ("Will use 16 instead of 32 bit samples\n");
421 ca9cc28c balrog
        esdfmt |= ESD_BITS16;
422 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_S16;
423 ca9cc28c balrog
        break;
424 ca9cc28c balrog
    }
425 deb9d2ee balrog
    obt_as.endianness = AUDIO_HOST_ENDIANNESS;
426 ca9cc28c balrog
427 ca9cc28c balrog
    audio_pcm_init_info (&hw->info, &obt_as);
428 ca9cc28c balrog
429 ca9cc28c balrog
    hw->samples = conf.samples;
430 ca9cc28c balrog
    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
431 ca9cc28c balrog
    if (!esd->pcm_buf) {
432 ca9cc28c balrog
        dolog ("Could not allocate buffer (%d bytes)\n",
433 ca9cc28c balrog
               hw->samples << hw->info.shift);
434 ca9cc28c balrog
        return -1;
435 ca9cc28c balrog
    }
436 ca9cc28c balrog
437 ca9cc28c balrog
    esd->fd = esd_record_stream (esdfmt, as->freq, conf.adc_host, NULL);
438 ca9cc28c balrog
    if (esd->fd < 0) {
439 ca9cc28c balrog
        qesd_logerr (errno, "esd_record_stream failed\n");
440 4b7c0418 malc
        goto fail1;
441 ca9cc28c balrog
    }
442 ca9cc28c balrog
443 ca9cc28c balrog
    if (audio_pt_init (&esd->pt, qesd_thread_in, esd, AUDIO_CAP, AUDIO_FUNC)) {
444 4b7c0418 malc
        goto fail2;
445 ca9cc28c balrog
    }
446 ca9cc28c balrog
447 ca9cc28c balrog
    return 0;
448 ca9cc28c balrog
449 4b7c0418 malc
 fail2:
450 ca9cc28c balrog
    if (close (esd->fd)) {
451 ca9cc28c balrog
        qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
452 ca9cc28c balrog
                     AUDIO_FUNC, esd->fd);
453 ca9cc28c balrog
    }
454 ca9cc28c balrog
    esd->fd = -1;
455 ca9cc28c balrog
456 ca9cc28c balrog
 fail1:
457 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
458 ca9cc28c balrog
    esd->pcm_buf = NULL;
459 ca9cc28c balrog
    return -1;
460 ca9cc28c balrog
}
461 ca9cc28c balrog
462 ca9cc28c balrog
static void qesd_fini_in (HWVoiceIn *hw)
463 ca9cc28c balrog
{
464 ca9cc28c balrog
    void *ret;
465 ca9cc28c balrog
    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
466 ca9cc28c balrog
467 ca9cc28c balrog
    audio_pt_lock (&esd->pt, AUDIO_FUNC);
468 ca9cc28c balrog
    esd->done = 1;
469 ca9cc28c balrog
    audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
470 ca9cc28c balrog
    audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
471 ca9cc28c balrog
472 ca9cc28c balrog
    if (esd->fd >= 0) {
473 ca9cc28c balrog
        if (close (esd->fd)) {
474 ca9cc28c balrog
            qesd_logerr (errno, "failed to close esd socket\n");
475 ca9cc28c balrog
        }
476 ca9cc28c balrog
        esd->fd = -1;
477 ca9cc28c balrog
    }
478 ca9cc28c balrog
479 ca9cc28c balrog
    audio_pt_fini (&esd->pt, AUDIO_FUNC);
480 ca9cc28c balrog
481 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
482 ca9cc28c balrog
    esd->pcm_buf = NULL;
483 ca9cc28c balrog
}
484 ca9cc28c balrog
485 ca9cc28c balrog
static int qesd_ctl_in (HWVoiceIn *hw, int cmd, ...)
486 ca9cc28c balrog
{
487 ca9cc28c balrog
    (void) hw;
488 ca9cc28c balrog
    (void) cmd;
489 ca9cc28c balrog
    return 0;
490 ca9cc28c balrog
}
491 ca9cc28c balrog
492 ca9cc28c balrog
/* common */
493 ca9cc28c balrog
static void *qesd_audio_init (void)
494 ca9cc28c balrog
{
495 ca9cc28c balrog
    return &conf;
496 ca9cc28c balrog
}
497 ca9cc28c balrog
498 ca9cc28c balrog
static void qesd_audio_fini (void *opaque)
499 ca9cc28c balrog
{
500 ca9cc28c balrog
    (void) opaque;
501 ca9cc28c balrog
    ldebug ("esd_fini");
502 ca9cc28c balrog
}
503 ca9cc28c balrog
504 ca9cc28c balrog
struct audio_option qesd_options[] = {
505 98f9f48c malc
    {
506 98f9f48c malc
        .name  = "SAMPLES",
507 98f9f48c malc
        .tag   = AUD_OPT_INT,
508 98f9f48c malc
        .valp  = &conf.samples,
509 98f9f48c malc
        .descr = "buffer size in samples"
510 98f9f48c malc
    },
511 98f9f48c malc
    {
512 98f9f48c malc
        .name  = "DIVISOR",
513 98f9f48c malc
        .tag   = AUD_OPT_INT,
514 98f9f48c malc
        .valp  = &conf.divisor,
515 98f9f48c malc
        .descr = "threshold divisor"
516 98f9f48c malc
    },
517 98f9f48c malc
    {
518 98f9f48c malc
        .name  = "DAC_HOST",
519 98f9f48c malc
        .tag   = AUD_OPT_STR,
520 98f9f48c malc
        .valp  = &conf.dac_host,
521 98f9f48c malc
        .descr = "playback host"
522 98f9f48c malc
    },
523 98f9f48c malc
    {
524 98f9f48c malc
        .name  = "ADC_HOST",
525 98f9f48c malc
        .tag   = AUD_OPT_STR,
526 98f9f48c malc
        .valp  = &conf.adc_host,
527 98f9f48c malc
        .descr = "capture host"
528 98f9f48c malc
    },
529 2700efa3 Juan Quintela
    { /* End of list */ }
530 ca9cc28c balrog
};
531 ca9cc28c balrog
532 35f4b58c blueswir1
static struct audio_pcm_ops qesd_pcm_ops = {
533 1dd3e4d1 Juan Quintela
    .init_out = qesd_init_out,
534 1dd3e4d1 Juan Quintela
    .fini_out = qesd_fini_out,
535 1dd3e4d1 Juan Quintela
    .run_out  = qesd_run_out,
536 1dd3e4d1 Juan Quintela
    .write    = qesd_write,
537 1dd3e4d1 Juan Quintela
    .ctl_out  = qesd_ctl_out,
538 1dd3e4d1 Juan Quintela
539 1dd3e4d1 Juan Quintela
    .init_in  = qesd_init_in,
540 1dd3e4d1 Juan Quintela
    .fini_in  = qesd_fini_in,
541 1dd3e4d1 Juan Quintela
    .run_in   = qesd_run_in,
542 1dd3e4d1 Juan Quintela
    .read     = qesd_read,
543 1dd3e4d1 Juan Quintela
    .ctl_in   = qesd_ctl_in,
544 ca9cc28c balrog
};
545 ca9cc28c balrog
546 ca9cc28c balrog
struct audio_driver esd_audio_driver = {
547 bee37f32 Juan Quintela
    .name           = "esd",
548 bee37f32 Juan Quintela
    .descr          = "http://en.wikipedia.org/wiki/Esound",
549 bee37f32 Juan Quintela
    .options        = qesd_options,
550 bee37f32 Juan Quintela
    .init           = qesd_audio_init,
551 bee37f32 Juan Quintela
    .fini           = qesd_audio_fini,
552 bee37f32 Juan Quintela
    .pcm_ops        = &qesd_pcm_ops,
553 bee37f32 Juan Quintela
    .can_be_default = 0,
554 bee37f32 Juan Quintela
    .max_voices_out = INT_MAX,
555 bee37f32 Juan Quintela
    .max_voices_in  = INT_MAX,
556 bee37f32 Juan Quintela
    .voice_size_out = sizeof (ESDVoiceOut),
557 bee37f32 Juan Quintela
    .voice_size_in  = sizeof (ESDVoiceIn)
558 ca9cc28c balrog
};