Statistics
| Branch: | Revision:

root / audio / esdaudio.c @ 49a945a3

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