Statistics
| Branch: | Revision:

root / audio / esdaudio.c @ 197bc219

History | View | Annotate | Download (14.6 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 ca9cc28c balrog
                    dolog ("warning: Misaligned write %d (requested %d), "
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 ca9cc28c balrog
static int qesd_run_out (HWVoiceOut *hw)
162 ca9cc28c balrog
{
163 ca9cc28c balrog
    int live, 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
    live = audio_pcm_hw_get_live_out (hw);
171 ca9cc28c balrog
    decr = audio_MIN (live, esd->decr);
172 ca9cc28c balrog
    esd->decr -= decr;
173 ca9cc28c balrog
    esd->live = live - decr;
174 ca9cc28c balrog
    hw->rpos = esd->rpos;
175 ca9cc28c balrog
    if (esd->live > 0) {
176 ca9cc28c balrog
        audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
177 ca9cc28c balrog
    }
178 ca9cc28c balrog
    else {
179 ca9cc28c balrog
        audio_pt_unlock (&esd->pt, AUDIO_FUNC);
180 ca9cc28c balrog
    }
181 ca9cc28c balrog
    return decr;
182 ca9cc28c balrog
}
183 ca9cc28c balrog
184 ca9cc28c balrog
static int qesd_write (SWVoiceOut *sw, void *buf, int len)
185 ca9cc28c balrog
{
186 ca9cc28c balrog
    return audio_pcm_sw_write (sw, buf, len);
187 ca9cc28c balrog
}
188 ca9cc28c balrog
189 1ea879e5 malc
static int qesd_init_out (HWVoiceOut *hw, struct audsettings *as)
190 ca9cc28c balrog
{
191 ca9cc28c balrog
    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
192 1ea879e5 malc
    struct audsettings obt_as = *as;
193 ca9cc28c balrog
    int esdfmt = ESD_STREAM | ESD_PLAY;
194 ca9cc28c balrog
    int err;
195 ca9cc28c balrog
    sigset_t set, old_set;
196 ca9cc28c balrog
197 ca9cc28c balrog
    sigfillset (&set);
198 ca9cc28c balrog
199 ca9cc28c balrog
    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
200 ca9cc28c balrog
    switch (as->fmt) {
201 ca9cc28c balrog
    case AUD_FMT_S8:
202 ca9cc28c balrog
    case AUD_FMT_U8:
203 ca9cc28c balrog
        esdfmt |= ESD_BITS8;
204 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_U8;
205 ca9cc28c balrog
        break;
206 ca9cc28c balrog
207 ca9cc28c balrog
    case AUD_FMT_S32:
208 ca9cc28c balrog
    case AUD_FMT_U32:
209 ca9cc28c balrog
        dolog ("Will use 16 instead of 32 bit samples\n");
210 ca9cc28c balrog
211 ca9cc28c balrog
    case AUD_FMT_S16:
212 ca9cc28c balrog
    case AUD_FMT_U16:
213 ca9cc28c balrog
    deffmt:
214 ca9cc28c balrog
        esdfmt |= ESD_BITS16;
215 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_S16;
216 ca9cc28c balrog
        break;
217 ca9cc28c balrog
218 ca9cc28c balrog
    default:
219 ca9cc28c balrog
        dolog ("Internal logic error: Bad audio format %d\n", as->fmt);
220 ca9cc28c balrog
        goto deffmt;
221 ca9cc28c balrog
222 ca9cc28c balrog
    }
223 deb9d2ee balrog
    obt_as.endianness = AUDIO_HOST_ENDIANNESS;
224 ca9cc28c balrog
225 ca9cc28c balrog
    audio_pcm_init_info (&hw->info, &obt_as);
226 ca9cc28c balrog
227 ca9cc28c balrog
    hw->samples = conf.samples;
228 ca9cc28c balrog
    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
229 ca9cc28c balrog
    if (!esd->pcm_buf) {
230 ca9cc28c balrog
        dolog ("Could not allocate buffer (%d bytes)\n",
231 ca9cc28c balrog
               hw->samples << hw->info.shift);
232 ca9cc28c balrog
        return -1;
233 ca9cc28c balrog
    }
234 ca9cc28c balrog
235 ca9cc28c balrog
    esd->fd = -1;
236 ca9cc28c balrog
    err = pthread_sigmask (SIG_BLOCK, &set, &old_set);
237 ca9cc28c balrog
    if (err) {
238 ca9cc28c balrog
        qesd_logerr (err, "pthread_sigmask failed\n");
239 ca9cc28c balrog
        goto fail1;
240 ca9cc28c balrog
    }
241 ca9cc28c balrog
242 ca9cc28c balrog
    esd->fd = esd_play_stream (esdfmt, as->freq, conf.dac_host, NULL);
243 ca9cc28c balrog
    if (esd->fd < 0) {
244 ca9cc28c balrog
        qesd_logerr (errno, "esd_play_stream failed\n");
245 ca9cc28c balrog
        goto fail2;
246 ca9cc28c balrog
    }
247 ca9cc28c balrog
248 ca9cc28c balrog
    if (audio_pt_init (&esd->pt, qesd_thread_out, esd, AUDIO_CAP, AUDIO_FUNC)) {
249 ca9cc28c balrog
        goto fail3;
250 ca9cc28c balrog
    }
251 ca9cc28c balrog
252 ca9cc28c balrog
    err = pthread_sigmask (SIG_SETMASK, &old_set, NULL);
253 ca9cc28c balrog
    if (err) {
254 ca9cc28c balrog
        qesd_logerr (err, "pthread_sigmask(restore) failed\n");
255 ca9cc28c balrog
    }
256 ca9cc28c balrog
257 ca9cc28c balrog
    return 0;
258 ca9cc28c balrog
259 ca9cc28c balrog
 fail3:
260 ca9cc28c balrog
    if (close (esd->fd)) {
261 ca9cc28c balrog
        qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
262 ca9cc28c balrog
                     AUDIO_FUNC, esd->fd);
263 ca9cc28c balrog
    }
264 ca9cc28c balrog
    esd->fd = -1;
265 ca9cc28c balrog
266 ca9cc28c balrog
 fail2:
267 ca9cc28c balrog
    err = pthread_sigmask (SIG_SETMASK, &old_set, NULL);
268 ca9cc28c balrog
    if (err) {
269 ca9cc28c balrog
        qesd_logerr (err, "pthread_sigmask(restore) failed\n");
270 ca9cc28c balrog
    }
271 ca9cc28c balrog
272 ca9cc28c balrog
 fail1:
273 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
274 ca9cc28c balrog
    esd->pcm_buf = NULL;
275 ca9cc28c balrog
    return -1;
276 ca9cc28c balrog
}
277 ca9cc28c balrog
278 ca9cc28c balrog
static void qesd_fini_out (HWVoiceOut *hw)
279 ca9cc28c balrog
{
280 ca9cc28c balrog
    void *ret;
281 ca9cc28c balrog
    ESDVoiceOut *esd = (ESDVoiceOut *) hw;
282 ca9cc28c balrog
283 ca9cc28c balrog
    audio_pt_lock (&esd->pt, AUDIO_FUNC);
284 ca9cc28c balrog
    esd->done = 1;
285 ca9cc28c balrog
    audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
286 ca9cc28c balrog
    audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
287 ca9cc28c balrog
288 ca9cc28c balrog
    if (esd->fd >= 0) {
289 ca9cc28c balrog
        if (close (esd->fd)) {
290 ca9cc28c balrog
            qesd_logerr (errno, "failed to close esd socket\n");
291 ca9cc28c balrog
        }
292 ca9cc28c balrog
        esd->fd = -1;
293 ca9cc28c balrog
    }
294 ca9cc28c balrog
295 ca9cc28c balrog
    audio_pt_fini (&esd->pt, AUDIO_FUNC);
296 ca9cc28c balrog
297 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
298 ca9cc28c balrog
    esd->pcm_buf = NULL;
299 ca9cc28c balrog
}
300 ca9cc28c balrog
301 ca9cc28c balrog
static int qesd_ctl_out (HWVoiceOut *hw, int cmd, ...)
302 ca9cc28c balrog
{
303 ca9cc28c balrog
    (void) hw;
304 ca9cc28c balrog
    (void) cmd;
305 ca9cc28c balrog
    return 0;
306 ca9cc28c balrog
}
307 ca9cc28c balrog
308 ca9cc28c balrog
/* capture */
309 ca9cc28c balrog
static void *qesd_thread_in (void *arg)
310 ca9cc28c balrog
{
311 ca9cc28c balrog
    ESDVoiceIn *esd = arg;
312 ca9cc28c balrog
    HWVoiceIn *hw = &esd->hw;
313 ca9cc28c balrog
    int threshold;
314 ca9cc28c balrog
315 ca9cc28c balrog
    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
316 ca9cc28c balrog
317 deb9d2ee balrog
    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
318 deb9d2ee balrog
        return NULL;
319 deb9d2ee balrog
    }
320 deb9d2ee balrog
321 ca9cc28c balrog
    for (;;) {
322 ca9cc28c balrog
        int incr, to_grab, wpos;
323 ca9cc28c balrog
324 ca9cc28c balrog
        for (;;) {
325 ca9cc28c balrog
            if (esd->done) {
326 ca9cc28c balrog
                goto exit;
327 ca9cc28c balrog
            }
328 ca9cc28c balrog
329 ca9cc28c balrog
            if (esd->dead > threshold) {
330 ca9cc28c balrog
                break;
331 ca9cc28c balrog
            }
332 ca9cc28c balrog
333 ca9cc28c balrog
            if (audio_pt_wait (&esd->pt, AUDIO_FUNC)) {
334 ca9cc28c balrog
                goto exit;
335 ca9cc28c balrog
            }
336 ca9cc28c balrog
        }
337 ca9cc28c balrog
338 ca9cc28c balrog
        incr = to_grab = esd->dead;
339 ca9cc28c balrog
        wpos = hw->wpos;
340 ca9cc28c balrog
341 ca9cc28c balrog
        if (audio_pt_unlock (&esd->pt, AUDIO_FUNC)) {
342 ca9cc28c balrog
            return NULL;
343 ca9cc28c balrog
        }
344 ca9cc28c balrog
345 ca9cc28c balrog
        while (to_grab) {
346 ca9cc28c balrog
            ssize_t nread;
347 ca9cc28c balrog
            int chunk = audio_MIN (to_grab, hw->samples - wpos);
348 ca9cc28c balrog
            void *buf = advance (esd->pcm_buf, wpos);
349 ca9cc28c balrog
350 ca9cc28c balrog
        again:
351 ca9cc28c balrog
            nread = read (esd->fd, buf, chunk << hw->info.shift);
352 ca9cc28c balrog
            if (nread == -1) {
353 ca9cc28c balrog
                if (errno == EINTR || errno == EAGAIN) {
354 ca9cc28c balrog
                    goto again;
355 ca9cc28c balrog
                }
356 ca9cc28c balrog
                qesd_logerr (errno, "read failed\n");
357 ca9cc28c balrog
                return NULL;
358 ca9cc28c balrog
            }
359 ca9cc28c balrog
360 ca9cc28c balrog
            if (nread != chunk << hw->info.shift) {
361 ca9cc28c balrog
                int rsamples = nread >> hw->info.shift;
362 ca9cc28c balrog
                int rbytes = rsamples << hw->info.shift;
363 ca9cc28c balrog
                if (rbytes != nread) {
364 ca9cc28c balrog
                    dolog ("warning: Misaligned write %d (requested %d), "
365 ca9cc28c balrog
                           "alignment %d\n",
366 ca9cc28c balrog
                           rbytes, nread, hw->info.align + 1);
367 ca9cc28c balrog
                }
368 ca9cc28c balrog
                to_grab -= rsamples;
369 ca9cc28c balrog
                wpos = (wpos + rsamples) % hw->samples;
370 ca9cc28c balrog
                break;
371 ca9cc28c balrog
            }
372 ca9cc28c balrog
373 ca9cc28c balrog
            hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift,
374 ca9cc28c balrog
                      &nominal_volume);
375 ca9cc28c balrog
            wpos = (wpos + chunk) % hw->samples;
376 ca9cc28c balrog
            to_grab -= chunk;
377 ca9cc28c balrog
        }
378 ca9cc28c balrog
379 ca9cc28c balrog
        if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
380 ca9cc28c balrog
            return NULL;
381 ca9cc28c balrog
        }
382 ca9cc28c balrog
383 ca9cc28c balrog
        esd->wpos = wpos;
384 ca9cc28c balrog
        esd->dead -= incr;
385 ca9cc28c balrog
        esd->incr += incr;
386 ca9cc28c balrog
    }
387 ca9cc28c balrog
388 ca9cc28c balrog
 exit:
389 ca9cc28c balrog
    audio_pt_unlock (&esd->pt, AUDIO_FUNC);
390 ca9cc28c balrog
    return NULL;
391 ca9cc28c balrog
}
392 ca9cc28c balrog
393 ca9cc28c balrog
static int qesd_run_in (HWVoiceIn *hw)
394 ca9cc28c balrog
{
395 ca9cc28c balrog
    int live, incr, dead;
396 ca9cc28c balrog
    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
397 ca9cc28c balrog
398 ca9cc28c balrog
    if (audio_pt_lock (&esd->pt, AUDIO_FUNC)) {
399 ca9cc28c balrog
        return 0;
400 ca9cc28c balrog
    }
401 ca9cc28c balrog
402 ca9cc28c balrog
    live = audio_pcm_hw_get_live_in (hw);
403 ca9cc28c balrog
    dead = hw->samples - live;
404 ca9cc28c balrog
    incr = audio_MIN (dead, esd->incr);
405 ca9cc28c balrog
    esd->incr -= incr;
406 ca9cc28c balrog
    esd->dead = dead - incr;
407 ca9cc28c balrog
    hw->wpos = esd->wpos;
408 ca9cc28c balrog
    if (esd->dead > 0) {
409 ca9cc28c balrog
        audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
410 ca9cc28c balrog
    }
411 ca9cc28c balrog
    else {
412 ca9cc28c balrog
        audio_pt_unlock (&esd->pt, AUDIO_FUNC);
413 ca9cc28c balrog
    }
414 ca9cc28c balrog
    return incr;
415 ca9cc28c balrog
}
416 ca9cc28c balrog
417 ca9cc28c balrog
static int qesd_read (SWVoiceIn *sw, void *buf, int len)
418 ca9cc28c balrog
{
419 ca9cc28c balrog
    return audio_pcm_sw_read (sw, buf, len);
420 ca9cc28c balrog
}
421 ca9cc28c balrog
422 1ea879e5 malc
static int qesd_init_in (HWVoiceIn *hw, struct audsettings *as)
423 ca9cc28c balrog
{
424 ca9cc28c balrog
    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
425 1ea879e5 malc
    struct audsettings obt_as = *as;
426 ca9cc28c balrog
    int esdfmt = ESD_STREAM | ESD_RECORD;
427 ca9cc28c balrog
    int err;
428 ca9cc28c balrog
    sigset_t set, old_set;
429 ca9cc28c balrog
430 ca9cc28c balrog
    sigfillset (&set);
431 ca9cc28c balrog
432 ca9cc28c balrog
    esdfmt |= (as->nchannels == 2) ? ESD_STEREO : ESD_MONO;
433 ca9cc28c balrog
    switch (as->fmt) {
434 ca9cc28c balrog
    case AUD_FMT_S8:
435 ca9cc28c balrog
    case AUD_FMT_U8:
436 ca9cc28c balrog
        esdfmt |= ESD_BITS8;
437 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_U8;
438 ca9cc28c balrog
        break;
439 ca9cc28c balrog
440 ca9cc28c balrog
    case AUD_FMT_S16:
441 ca9cc28c balrog
    case AUD_FMT_U16:
442 ca9cc28c balrog
        esdfmt |= ESD_BITS16;
443 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_S16;
444 ca9cc28c balrog
        break;
445 ca9cc28c balrog
446 ca9cc28c balrog
    case AUD_FMT_S32:
447 ca9cc28c balrog
    case AUD_FMT_U32:
448 ca9cc28c balrog
        dolog ("Will use 16 instead of 32 bit samples\n");
449 ca9cc28c balrog
        esdfmt |= ESD_BITS16;
450 ca9cc28c balrog
        obt_as.fmt = AUD_FMT_S16;
451 ca9cc28c balrog
        break;
452 ca9cc28c balrog
    }
453 deb9d2ee balrog
    obt_as.endianness = AUDIO_HOST_ENDIANNESS;
454 ca9cc28c balrog
455 ca9cc28c balrog
    audio_pcm_init_info (&hw->info, &obt_as);
456 ca9cc28c balrog
457 ca9cc28c balrog
    hw->samples = conf.samples;
458 ca9cc28c balrog
    esd->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
459 ca9cc28c balrog
    if (!esd->pcm_buf) {
460 ca9cc28c balrog
        dolog ("Could not allocate buffer (%d bytes)\n",
461 ca9cc28c balrog
               hw->samples << hw->info.shift);
462 ca9cc28c balrog
        return -1;
463 ca9cc28c balrog
    }
464 ca9cc28c balrog
465 ca9cc28c balrog
    esd->fd = -1;
466 ca9cc28c balrog
467 ca9cc28c balrog
    err = pthread_sigmask (SIG_BLOCK, &set, &old_set);
468 ca9cc28c balrog
    if (err) {
469 ca9cc28c balrog
        qesd_logerr (err, "pthread_sigmask failed\n");
470 ca9cc28c balrog
        goto fail1;
471 ca9cc28c balrog
    }
472 ca9cc28c balrog
473 ca9cc28c balrog
    esd->fd = esd_record_stream (esdfmt, as->freq, conf.adc_host, NULL);
474 ca9cc28c balrog
    if (esd->fd < 0) {
475 ca9cc28c balrog
        qesd_logerr (errno, "esd_record_stream failed\n");
476 ca9cc28c balrog
        goto fail2;
477 ca9cc28c balrog
    }
478 ca9cc28c balrog
479 ca9cc28c balrog
    if (audio_pt_init (&esd->pt, qesd_thread_in, esd, AUDIO_CAP, AUDIO_FUNC)) {
480 ca9cc28c balrog
        goto fail3;
481 ca9cc28c balrog
    }
482 ca9cc28c balrog
483 ca9cc28c balrog
    err = pthread_sigmask (SIG_SETMASK, &old_set, NULL);
484 ca9cc28c balrog
    if (err) {
485 ca9cc28c balrog
        qesd_logerr (err, "pthread_sigmask(restore) failed\n");
486 ca9cc28c balrog
    }
487 ca9cc28c balrog
488 ca9cc28c balrog
    return 0;
489 ca9cc28c balrog
490 ca9cc28c balrog
 fail3:
491 ca9cc28c balrog
    if (close (esd->fd)) {
492 ca9cc28c balrog
        qesd_logerr (errno, "%s: close on esd socket(%d) failed\n",
493 ca9cc28c balrog
                     AUDIO_FUNC, esd->fd);
494 ca9cc28c balrog
    }
495 ca9cc28c balrog
    esd->fd = -1;
496 ca9cc28c balrog
497 ca9cc28c balrog
 fail2:
498 ca9cc28c balrog
    err = pthread_sigmask (SIG_SETMASK, &old_set, NULL);
499 ca9cc28c balrog
    if (err) {
500 ca9cc28c balrog
        qesd_logerr (err, "pthread_sigmask(restore) failed\n");
501 ca9cc28c balrog
    }
502 ca9cc28c balrog
503 ca9cc28c balrog
 fail1:
504 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
505 ca9cc28c balrog
    esd->pcm_buf = NULL;
506 ca9cc28c balrog
    return -1;
507 ca9cc28c balrog
}
508 ca9cc28c balrog
509 ca9cc28c balrog
static void qesd_fini_in (HWVoiceIn *hw)
510 ca9cc28c balrog
{
511 ca9cc28c balrog
    void *ret;
512 ca9cc28c balrog
    ESDVoiceIn *esd = (ESDVoiceIn *) hw;
513 ca9cc28c balrog
514 ca9cc28c balrog
    audio_pt_lock (&esd->pt, AUDIO_FUNC);
515 ca9cc28c balrog
    esd->done = 1;
516 ca9cc28c balrog
    audio_pt_unlock_and_signal (&esd->pt, AUDIO_FUNC);
517 ca9cc28c balrog
    audio_pt_join (&esd->pt, &ret, AUDIO_FUNC);
518 ca9cc28c balrog
519 ca9cc28c balrog
    if (esd->fd >= 0) {
520 ca9cc28c balrog
        if (close (esd->fd)) {
521 ca9cc28c balrog
            qesd_logerr (errno, "failed to close esd socket\n");
522 ca9cc28c balrog
        }
523 ca9cc28c balrog
        esd->fd = -1;
524 ca9cc28c balrog
    }
525 ca9cc28c balrog
526 ca9cc28c balrog
    audio_pt_fini (&esd->pt, AUDIO_FUNC);
527 ca9cc28c balrog
528 ca9cc28c balrog
    qemu_free (esd->pcm_buf);
529 ca9cc28c balrog
    esd->pcm_buf = NULL;
530 ca9cc28c balrog
}
531 ca9cc28c balrog
532 ca9cc28c balrog
static int qesd_ctl_in (HWVoiceIn *hw, int cmd, ...)
533 ca9cc28c balrog
{
534 ca9cc28c balrog
    (void) hw;
535 ca9cc28c balrog
    (void) cmd;
536 ca9cc28c balrog
    return 0;
537 ca9cc28c balrog
}
538 ca9cc28c balrog
539 ca9cc28c balrog
/* common */
540 ca9cc28c balrog
static void *qesd_audio_init (void)
541 ca9cc28c balrog
{
542 ca9cc28c balrog
    return &conf;
543 ca9cc28c balrog
}
544 ca9cc28c balrog
545 ca9cc28c balrog
static void qesd_audio_fini (void *opaque)
546 ca9cc28c balrog
{
547 ca9cc28c balrog
    (void) opaque;
548 ca9cc28c balrog
    ldebug ("esd_fini");
549 ca9cc28c balrog
}
550 ca9cc28c balrog
551 ca9cc28c balrog
struct audio_option qesd_options[] = {
552 98f9f48c malc
    {
553 98f9f48c malc
        .name  = "SAMPLES",
554 98f9f48c malc
        .tag   = AUD_OPT_INT,
555 98f9f48c malc
        .valp  = &conf.samples,
556 98f9f48c malc
        .descr = "buffer size in samples"
557 98f9f48c malc
    },
558 98f9f48c malc
    {
559 98f9f48c malc
        .name  = "DIVISOR",
560 98f9f48c malc
        .tag   = AUD_OPT_INT,
561 98f9f48c malc
        .valp  = &conf.divisor,
562 98f9f48c malc
        .descr = "threshold divisor"
563 98f9f48c malc
    },
564 98f9f48c malc
    {
565 98f9f48c malc
        .name  = "DAC_HOST",
566 98f9f48c malc
        .tag   = AUD_OPT_STR,
567 98f9f48c malc
        .valp  = &conf.dac_host,
568 98f9f48c malc
        .descr = "playback host"
569 98f9f48c malc
    },
570 98f9f48c malc
    {
571 98f9f48c malc
        .name  = "ADC_HOST",
572 98f9f48c malc
        .tag   = AUD_OPT_STR,
573 98f9f48c malc
        .valp  = &conf.adc_host,
574 98f9f48c malc
        .descr = "capture host"
575 98f9f48c malc
    },
576 2700efa3 Juan Quintela
    { /* End of list */ }
577 ca9cc28c balrog
};
578 ca9cc28c balrog
579 35f4b58c blueswir1
static struct audio_pcm_ops qesd_pcm_ops = {
580 1dd3e4d1 Juan Quintela
    .init_out = qesd_init_out,
581 1dd3e4d1 Juan Quintela
    .fini_out = qesd_fini_out,
582 1dd3e4d1 Juan Quintela
    .run_out  = qesd_run_out,
583 1dd3e4d1 Juan Quintela
    .write    = qesd_write,
584 1dd3e4d1 Juan Quintela
    .ctl_out  = qesd_ctl_out,
585 1dd3e4d1 Juan Quintela
586 1dd3e4d1 Juan Quintela
    .init_in  = qesd_init_in,
587 1dd3e4d1 Juan Quintela
    .fini_in  = qesd_fini_in,
588 1dd3e4d1 Juan Quintela
    .run_in   = qesd_run_in,
589 1dd3e4d1 Juan Quintela
    .read     = qesd_read,
590 1dd3e4d1 Juan Quintela
    .ctl_in   = qesd_ctl_in,
591 ca9cc28c balrog
};
592 ca9cc28c balrog
593 ca9cc28c balrog
struct audio_driver esd_audio_driver = {
594 bee37f32 Juan Quintela
    .name           = "esd",
595 bee37f32 Juan Quintela
    .descr          = "http://en.wikipedia.org/wiki/Esound",
596 bee37f32 Juan Quintela
    .options        = qesd_options,
597 bee37f32 Juan Quintela
    .init           = qesd_audio_init,
598 bee37f32 Juan Quintela
    .fini           = qesd_audio_fini,
599 bee37f32 Juan Quintela
    .pcm_ops        = &qesd_pcm_ops,
600 bee37f32 Juan Quintela
    .can_be_default = 0,
601 bee37f32 Juan Quintela
    .max_voices_out = INT_MAX,
602 bee37f32 Juan Quintela
    .max_voices_in  = INT_MAX,
603 bee37f32 Juan Quintela
    .voice_size_out = sizeof (ESDVoiceOut),
604 bee37f32 Juan Quintela
    .voice_size_in  = sizeof (ESDVoiceIn)
605 ca9cc28c balrog
};