Statistics
| Branch: | Revision:

root / oss.c @ c94c8d64

History | View | Annotate | Download (13.5 kB)

1 27503323 bellard
/*
2 27503323 bellard
 * QEMU OSS Audio output driver
3 27503323 bellard
 * 
4 27503323 bellard
 * Copyright (c) 2003 Vassili Karpov (malc)
5 27503323 bellard
 * 
6 27503323 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 27503323 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 27503323 bellard
 * in the Software without restriction, including without limitation the rights
9 27503323 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 27503323 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 27503323 bellard
 * furnished to do so, subject to the following conditions:
12 27503323 bellard
 *
13 27503323 bellard
 * The above copyright notice and this permission notice shall be included in
14 27503323 bellard
 * all copies or substantial portions of the Software.
15 27503323 bellard
 *
16 27503323 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 27503323 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 27503323 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 27503323 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 27503323 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 27503323 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 27503323 bellard
 * THE SOFTWARE.
23 27503323 bellard
 */
24 67b915a5 bellard
#include "vl.h"
25 67b915a5 bellard
26 83fb7adf bellard
#if !defined(_WIN32) && !defined(__APPLE__)
27 d329a6fb bellard
#include <ctype.h>
28 27503323 bellard
#include <fcntl.h>
29 27503323 bellard
#include <errno.h>
30 27503323 bellard
#include <stdio.h>
31 27503323 bellard
#include <unistd.h>
32 27503323 bellard
#include <string.h>
33 27503323 bellard
#include <stdlib.h>
34 27503323 bellard
#include <limits.h>
35 27503323 bellard
#include <inttypes.h>
36 d329a6fb bellard
#include <sys/mman.h>
37 27503323 bellard
#include <sys/types.h>
38 27503323 bellard
#include <sys/ioctl.h>
39 27503323 bellard
#include <sys/soundcard.h>
40 27503323 bellard
41 27503323 bellard
42 27503323 bellard
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
43 27503323 bellard
/* http://www.multi-platforms.com/Tips/PopCount.htm */
44 27503323 bellard
static inline uint32_t popcount (uint32_t u)
45 27503323 bellard
{
46 27503323 bellard
  u = ((u&0x55555555) + ((u>>1)&0x55555555));
47 27503323 bellard
  u = ((u&0x33333333) + ((u>>2)&0x33333333));
48 27503323 bellard
  u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
49 27503323 bellard
  u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
50 27503323 bellard
  u = ( u&0x0000ffff) + (u>>16);
51 27503323 bellard
  return u;
52 27503323 bellard
}
53 27503323 bellard
54 27503323 bellard
static inline uint32_t lsbindex (uint32_t u)
55 27503323 bellard
{
56 27503323 bellard
  return popcount ((u&-u)-1);
57 27503323 bellard
}
58 27503323 bellard
59 27503323 bellard
#define MIN(a, b) ((a)>(b)?(b):(a))
60 27503323 bellard
#define MAX(a, b) ((a)<(b)?(b):(a))
61 27503323 bellard
62 27503323 bellard
#define DEREF(x) (void)x
63 27503323 bellard
#define log(...) fprintf (stderr, "oss: " __VA_ARGS__)
64 27503323 bellard
#define ERRFail(...) do {                                       \
65 27503323 bellard
    int _errno = errno;                                         \
66 27503323 bellard
    fprintf (stderr, "oss: " __VA_ARGS__);                      \
67 27503323 bellard
    fprintf (stderr, "system error: %s\n", strerror (_errno));  \
68 27503323 bellard
    abort ();                                                   \
69 27503323 bellard
} while (0)
70 27503323 bellard
#define Fail(...) do {                          \
71 27503323 bellard
    fprintf (stderr, "oss: " __VA_ARGS__);      \
72 27503323 bellard
    fprintf (stderr, "\n");                     \
73 27503323 bellard
    abort ();                                   \
74 27503323 bellard
} while (0)
75 27503323 bellard
76 27503323 bellard
#ifdef DEBUG_OSS
77 27503323 bellard
#define lwarn(...) fprintf (stderr, "oss: " __VA_ARGS__)
78 27503323 bellard
#define linfo(...) fprintf (stderr, "oss: " __VA_ARGS__)
79 27503323 bellard
#define ldebug(...) fprintf (stderr, "oss: " __VA_ARGS__)
80 27503323 bellard
#else
81 27503323 bellard
#define lwarn(...)
82 27503323 bellard
#define linfo(...)
83 27503323 bellard
#define ldebug(...)
84 27503323 bellard
#endif
85 27503323 bellard
86 27503323 bellard
87 27503323 bellard
#define IOCTL(args) do {                        \
88 27503323 bellard
  int ret = ioctl args;                         \
89 27503323 bellard
  if (-1 == ret) {                              \
90 27503323 bellard
    ERRFail (#args);                            \
91 27503323 bellard
  }                                             \
92 27503323 bellard
  ldebug ("ioctl " #args " = %d\n", ret);       \
93 27503323 bellard
} while (0)
94 27503323 bellard
95 d329a6fb bellard
static struct {
96 d329a6fb bellard
    int fd;
97 d329a6fb bellard
    int freq;
98 d329a6fb bellard
    int bits16;
99 d329a6fb bellard
    int nchannels;
100 d329a6fb bellard
    int rpos;
101 d329a6fb bellard
    int wpos;
102 d329a6fb bellard
    int live;
103 d329a6fb bellard
    int oss_fmt;
104 d329a6fb bellard
    int bytes_per_second;
105 d329a6fb bellard
    int is_mapped;
106 d329a6fb bellard
    void *buf;
107 d329a6fb bellard
    int bufsize;
108 d329a6fb bellard
    int nfrags;
109 d329a6fb bellard
    int fragsize;
110 d329a6fb bellard
    int old_optr;
111 d329a6fb bellard
    int leftover;
112 d329a6fb bellard
    uint64_t old_ticks;
113 d329a6fb bellard
    void (*copy_fn)(void *, void *, int);
114 d329a6fb bellard
} oss = { .fd = -1 };
115 d329a6fb bellard
116 d329a6fb bellard
static struct {
117 d329a6fb bellard
    int try_mmap;
118 d329a6fb bellard
    int nfrags;
119 d329a6fb bellard
    int fragsize;
120 d329a6fb bellard
} conf = {
121 d329a6fb bellard
    .try_mmap = 0,
122 d329a6fb bellard
    .nfrags = 4,
123 d329a6fb bellard
    .fragsize = 4096
124 d329a6fb bellard
};
125 d329a6fb bellard
126 d329a6fb bellard
static enum {DONT, DSP, TID} est = DONT;
127 27503323 bellard
128 27503323 bellard
static void copy_no_conversion (void *dst, void *src, int size)
129 27503323 bellard
{
130 27503323 bellard
    memcpy (dst, src, size);
131 27503323 bellard
}
132 27503323 bellard
133 27503323 bellard
static void copy_u16_to_s16 (void *dst, void *src, int size)
134 27503323 bellard
{
135 27503323 bellard
    int i;
136 27503323 bellard
    uint16_t *out, *in;
137 27503323 bellard
138 27503323 bellard
    out = dst;
139 27503323 bellard
    in = src;
140 27503323 bellard
141 27503323 bellard
    for (i = 0; i < size / 2; i++) {
142 27503323 bellard
        out[i] = in[i] + 0x8000;
143 27503323 bellard
    }
144 27503323 bellard
}
145 27503323 bellard
146 27503323 bellard
static void pab (struct audio_buf_info *abinfo)
147 27503323 bellard
{
148 27503323 bellard
    DEREF (abinfo);
149 27503323 bellard
150 27503323 bellard
    ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
151 27503323 bellard
            "rpos %d, wpos %d, live %d\n",
152 27503323 bellard
            abinfo->fragments,
153 27503323 bellard
            abinfo->fragstotal,
154 27503323 bellard
            abinfo->fragsize,
155 27503323 bellard
            abinfo->bytes,
156 27503323 bellard
            rpos, wpos, live);
157 27503323 bellard
}
158 27503323 bellard
159 d329a6fb bellard
static void do_open ()
160 27503323 bellard
{
161 d329a6fb bellard
    int mmmmssss;
162 d329a6fb bellard
    audio_buf_info abinfo;
163 d329a6fb bellard
    int fmt, freq, nchannels;
164 27503323 bellard
165 d329a6fb bellard
    if (oss.buf) {
166 d329a6fb bellard
        if (-1 == munmap (oss.buf, oss.bufsize)) {
167 d329a6fb bellard
            ERRFail ("failed to unmap audio buffer %p %d",
168 d329a6fb bellard
                     oss.buf, oss.bufsize);
169 d329a6fb bellard
        }
170 d329a6fb bellard
        oss.buf = NULL;
171 27503323 bellard
    }
172 27503323 bellard
173 d329a6fb bellard
    if (-1 != oss.fd)
174 d329a6fb bellard
        close (oss.fd);
175 27503323 bellard
176 d329a6fb bellard
    oss.fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK);
177 d329a6fb bellard
    if (-1 == oss.fd) {
178 d329a6fb bellard
        ERRFail ("can not open /dev/dsp");
179 d329a6fb bellard
    }
180 27503323 bellard
181 d329a6fb bellard
    fmt = oss.oss_fmt;
182 d329a6fb bellard
    freq = oss.freq;
183 d329a6fb bellard
    nchannels = oss.nchannels;
184 d329a6fb bellard
185 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_RESET, 1));
186 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_SAMPLESIZE, &fmt));
187 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_CHANNELS, &nchannels));
188 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_SPEED, &freq));
189 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_NONBLOCK));
190 d329a6fb bellard
191 d329a6fb bellard
    mmmmssss = (conf.nfrags << 16) | conf.fragsize;
192 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
193 d329a6fb bellard
194 d329a6fb bellard
    if ((oss.oss_fmt != fmt)
195 d329a6fb bellard
        || (oss.nchannels != nchannels)
196 d329a6fb bellard
        || (oss.freq != freq)) {
197 d329a6fb bellard
        Fail ("failed to set audio parameters\n"
198 d329a6fb bellard
              "parameter | requested value | obtained value\n"
199 d329a6fb bellard
              "format    |      %10d |     %10d\n"
200 d329a6fb bellard
              "channels  |      %10d |     %10d\n"
201 d329a6fb bellard
              "frequency |      %10d |     %10d\n",
202 d329a6fb bellard
              oss.oss_fmt, fmt,
203 d329a6fb bellard
              oss.nchannels, nchannels,
204 d329a6fb bellard
              oss.freq, freq);
205 d329a6fb bellard
    }
206 27503323 bellard
207 d329a6fb bellard
    IOCTL ((oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo));
208 27503323 bellard
209 d329a6fb bellard
    oss.nfrags = abinfo.fragstotal;
210 d329a6fb bellard
    oss.fragsize = abinfo.fragsize;
211 d329a6fb bellard
    oss.bufsize = oss.nfrags * oss.fragsize;
212 d329a6fb bellard
    oss.old_optr = 0;
213 27503323 bellard
214 d329a6fb bellard
    oss.bytes_per_second = (freq << (nchannels >> 1)) << oss.bits16;
215 d329a6fb bellard
216 d329a6fb bellard
    linfo ("bytes per second %d\n", oss.bytes_per_second);
217 d329a6fb bellard
218 d329a6fb bellard
    linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
219 d329a6fb bellard
           abinfo.fragments,
220 d329a6fb bellard
           abinfo.fragstotal,
221 d329a6fb bellard
           abinfo.fragsize,
222 d329a6fb bellard
           abinfo.bytes,
223 d329a6fb bellard
           oss.bufsize);
224 d329a6fb bellard
225 d329a6fb bellard
    oss.buf = MAP_FAILED;
226 d329a6fb bellard
    oss.is_mapped = 0;
227 d329a6fb bellard
228 d329a6fb bellard
    if (conf.try_mmap) {
229 d329a6fb bellard
        oss.buf = mmap (NULL, oss.bufsize, PROT_WRITE, MAP_SHARED, oss.fd, 0);
230 d329a6fb bellard
        if (MAP_FAILED == oss.buf) {
231 d329a6fb bellard
            int err;
232 d329a6fb bellard
233 d329a6fb bellard
            err = errno;
234 d329a6fb bellard
            log ("failed to mmap audio, size %d, fd %d\n"
235 d329a6fb bellard
                 "syserr: %s\n",
236 d329a6fb bellard
                 oss.bufsize, oss.fd, strerror (err));
237 d329a6fb bellard
        }
238 27503323 bellard
    else {
239 d329a6fb bellard
            est = TID;
240 d329a6fb bellard
            oss.is_mapped = 1;
241 d329a6fb bellard
        }
242 d329a6fb bellard
    }
243 d329a6fb bellard
244 d329a6fb bellard
    if (MAP_FAILED == oss.buf) {
245 d329a6fb bellard
        est = TID;
246 d329a6fb bellard
        oss.buf = mmap (NULL, oss.bufsize, PROT_READ | PROT_WRITE,
247 d329a6fb bellard
                        MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
248 d329a6fb bellard
        if (MAP_FAILED == oss.buf) {
249 d329a6fb bellard
            ERRFail ("mmap audio buf, size %d", oss.bufsize);
250 d329a6fb bellard
        }
251 d329a6fb bellard
    }
252 d329a6fb bellard
253 d329a6fb bellard
    oss.rpos = 0;
254 d329a6fb bellard
    oss.wpos = 0;
255 d329a6fb bellard
    oss.live = 0;
256 d329a6fb bellard
257 d329a6fb bellard
    if (oss.is_mapped) {
258 d329a6fb bellard
        int trig;
259 d329a6fb bellard
260 d329a6fb bellard
        trig = 0;
261 d329a6fb bellard
        IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig));
262 d329a6fb bellard
        trig = PCM_ENABLE_OUTPUT;
263 d329a6fb bellard
        IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig));
264 27503323 bellard
    }
265 27503323 bellard
}
266 27503323 bellard
267 d329a6fb bellard
static void maybe_open (int req_freq, int req_nchannels,
268 d329a6fb bellard
                        audfmt_e req_fmt, int force_open)
269 27503323 bellard
{
270 d329a6fb bellard
    int oss_fmt, bits16;
271 27503323 bellard
272 d329a6fb bellard
    switch (req_fmt) {
273 27503323 bellard
    case AUD_FMT_U8:
274 27503323 bellard
        bits16 = 0;
275 d329a6fb bellard
        oss_fmt = AFMT_U8;
276 d329a6fb bellard
        oss.copy_fn = copy_no_conversion;
277 27503323 bellard
        break;
278 27503323 bellard
279 27503323 bellard
    case AUD_FMT_S8:
280 27503323 bellard
        Fail ("can not play 8bit signed");
281 27503323 bellard
282 27503323 bellard
    case AUD_FMT_S16:
283 27503323 bellard
        bits16 = 1;
284 d329a6fb bellard
        oss_fmt = AFMT_S16_LE;
285 d329a6fb bellard
        oss.copy_fn = copy_no_conversion;
286 27503323 bellard
        break;
287 27503323 bellard
288 27503323 bellard
    case AUD_FMT_U16:
289 27503323 bellard
        bits16 = 1;
290 d329a6fb bellard
        oss_fmt = AFMT_S16_LE;
291 d329a6fb bellard
        oss.copy_fn = copy_u16_to_s16;
292 27503323 bellard
        break;
293 27503323 bellard
294 27503323 bellard
    default:
295 27503323 bellard
        abort ();
296 27503323 bellard
    }
297 27503323 bellard
298 d329a6fb bellard
    if (force_open
299 d329a6fb bellard
        || (-1 == oss.fd)
300 d329a6fb bellard
        || (oss_fmt != oss.oss_fmt)
301 d329a6fb bellard
        || (req_nchannels != oss.nchannels)
302 d329a6fb bellard
        || (req_freq != oss.freq)
303 d329a6fb bellard
        || (bits16 != oss.bits16)) {
304 d329a6fb bellard
        oss.oss_fmt = oss_fmt;
305 d329a6fb bellard
        oss.nchannels = req_nchannels;
306 d329a6fb bellard
        oss.freq = req_freq;
307 d329a6fb bellard
        oss.bits16 = bits16;
308 d329a6fb bellard
        do_open ();
309 27503323 bellard
    }
310 d329a6fb bellard
}
311 27503323 bellard
312 d329a6fb bellard
void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
313 d329a6fb bellard
{
314 d329a6fb bellard
    maybe_open (req_freq, req_nchannels, req_fmt, 0);
315 d329a6fb bellard
}
316 27503323 bellard
317 d329a6fb bellard
void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
318 d329a6fb bellard
{
319 d329a6fb bellard
    maybe_open (req_freq, req_nchannels, req_fmt, 1);
320 27503323 bellard
}
321 27503323 bellard
322 27503323 bellard
int AUD_write (void *in_buf, int size)
323 27503323 bellard
{
324 27503323 bellard
    int to_copy, temp;
325 27503323 bellard
    uint8_t *in, *out;
326 27503323 bellard
327 d329a6fb bellard
    to_copy = MIN (oss.bufsize - oss.live, size);
328 27503323 bellard
329 27503323 bellard
    temp = to_copy;
330 27503323 bellard
331 27503323 bellard
    in = in_buf;
332 d329a6fb bellard
    out = oss.buf;
333 27503323 bellard
334 27503323 bellard
    while (temp) {
335 27503323 bellard
        int copy;
336 27503323 bellard
337 d329a6fb bellard
        copy = MIN (temp, oss.bufsize - oss.wpos);
338 d329a6fb bellard
        oss.copy_fn (out + oss.wpos, in, copy);
339 27503323 bellard
340 d329a6fb bellard
        oss.wpos += copy;
341 d329a6fb bellard
        if (oss.wpos == oss.bufsize) {
342 d329a6fb bellard
            oss.wpos = 0;
343 27503323 bellard
        }
344 27503323 bellard
345 27503323 bellard
        temp -= copy;
346 27503323 bellard
        in += copy;
347 d329a6fb bellard
        oss.live += copy;
348 27503323 bellard
    }
349 27503323 bellard
350 27503323 bellard
    return to_copy;
351 27503323 bellard
}
352 27503323 bellard
353 27503323 bellard
void AUD_run (void)
354 27503323 bellard
{
355 27503323 bellard
    int res;
356 27503323 bellard
    int bytes;
357 27503323 bellard
    struct audio_buf_info abinfo;
358 27503323 bellard
359 d329a6fb bellard
    if (0 == oss.live)
360 27503323 bellard
        return;
361 27503323 bellard
362 d329a6fb bellard
    if (oss.is_mapped) {
363 d329a6fb bellard
        count_info info;
364 d329a6fb bellard
365 d329a6fb bellard
        res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
366 d329a6fb bellard
        if (-1 == res) {
367 d329a6fb bellard
            int err;
368 d329a6fb bellard
369 d329a6fb bellard
            err = errno;
370 d329a6fb bellard
            lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
371 d329a6fb bellard
            return;
372 d329a6fb bellard
        }
373 d329a6fb bellard
374 d329a6fb bellard
        if (info.ptr > oss.old_optr) {
375 d329a6fb bellard
            bytes = info.ptr - oss.old_optr;
376 d329a6fb bellard
        }
377 d329a6fb bellard
        else {
378 d329a6fb bellard
            bytes = oss.bufsize + info.ptr - oss.old_optr;
379 d329a6fb bellard
        }
380 d329a6fb bellard
381 d329a6fb bellard
        oss.old_optr = info.ptr;
382 d329a6fb bellard
        oss.live -= bytes;
383 d329a6fb bellard
        return;
384 d329a6fb bellard
    }
385 d329a6fb bellard
386 d329a6fb bellard
    res = ioctl (oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo);
387 27503323 bellard
388 27503323 bellard
    if (-1 == res) {
389 27503323 bellard
        int err;
390 27503323 bellard
391 27503323 bellard
        err = errno;
392 27503323 bellard
        lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err));
393 27503323 bellard
    }
394 27503323 bellard
395 27503323 bellard
    bytes = abinfo.bytes;
396 d329a6fb bellard
    bytes = MIN (oss.live, bytes);
397 27503323 bellard
#if 0
398 27503323 bellard
    bytes = (bytes / fragsize) * fragsize;
399 27503323 bellard
#endif
400 27503323 bellard
401 27503323 bellard
    while (bytes) {
402 27503323 bellard
        int left, play, written;
403 27503323 bellard
404 d329a6fb bellard
        left = oss.bufsize - oss.rpos;
405 27503323 bellard
        play = MIN (left, bytes);
406 d329a6fb bellard
        written = write (oss.fd, (void *) ((uint32_t) oss.buf + oss.rpos), play);
407 27503323 bellard
408 27503323 bellard
        if (-1 == written) {
409 27503323 bellard
            if (EAGAIN == errno || EINTR == errno) {
410 27503323 bellard
                return;
411 27503323 bellard
            }
412 27503323 bellard
            else {
413 27503323 bellard
                ERRFail ("write audio");
414 27503323 bellard
            }
415 27503323 bellard
        }
416 27503323 bellard
417 27503323 bellard
        play = written;
418 d329a6fb bellard
        oss.live -= play;
419 d329a6fb bellard
        oss.rpos += play;
420 27503323 bellard
        bytes -= play;
421 27503323 bellard
422 d329a6fb bellard
        if (oss.rpos == oss.bufsize) {
423 d329a6fb bellard
            oss.rpos = 0;
424 27503323 bellard
        }
425 27503323 bellard
    }
426 27503323 bellard
}
427 27503323 bellard
428 27503323 bellard
static int get_dsp_bytes (void)
429 27503323 bellard
{
430 27503323 bellard
    int res;
431 27503323 bellard
    struct count_info info;
432 27503323 bellard
433 d329a6fb bellard
    res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
434 27503323 bellard
    if (-1 == res) {
435 27503323 bellard
        int err;
436 27503323 bellard
437 27503323 bellard
        err = errno;
438 27503323 bellard
        lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
439 27503323 bellard
        return -1;
440 27503323 bellard
    }
441 27503323 bellard
    else {
442 27503323 bellard
        ldebug ("bytes %d\n", info.bytes);
443 27503323 bellard
        return info.bytes;
444 27503323 bellard
    }
445 27503323 bellard
}
446 27503323 bellard
447 d329a6fb bellard
void AUD_adjust_estimate (int leftover)
448 27503323 bellard
{
449 d329a6fb bellard
    oss.leftover = leftover;
450 27503323 bellard
}
451 27503323 bellard
452 27503323 bellard
int AUD_get_free (void)
453 27503323 bellard
{
454 27503323 bellard
    int free, elapsed;
455 27503323 bellard
456 d329a6fb bellard
    free = oss.bufsize - oss.live;
457 27503323 bellard
458 27503323 bellard
    if (0 == free)
459 27503323 bellard
        return 0;
460 27503323 bellard
461 27503323 bellard
    elapsed = free;
462 d329a6fb bellard
    switch (est) {
463 27503323 bellard
    case DONT:
464 27503323 bellard
        break;
465 27503323 bellard
466 27503323 bellard
    case DSP:
467 27503323 bellard
        {
468 27503323 bellard
            static int old_bytes;
469 27503323 bellard
            int bytes;
470 27503323 bellard
471 27503323 bellard
            bytes = get_dsp_bytes ();
472 27503323 bellard
            if (bytes <= 0)
473 27503323 bellard
                return free;
474 27503323 bellard
475 27503323 bellard
            elapsed = bytes - old_bytes;
476 27503323 bellard
            old_bytes = bytes;
477 27503323 bellard
            ldebug ("dsp elapsed %d bytes\n", elapsed);
478 27503323 bellard
            break;
479 27503323 bellard
        }
480 27503323 bellard
481 27503323 bellard
    case TID:
482 27503323 bellard
        {
483 27503323 bellard
            uint64_t ticks, delta;
484 27503323 bellard
            uint64_t ua_elapsed;
485 27503323 bellard
            uint64_t al_elapsed;
486 27503323 bellard
487 8a7ddc38 bellard
            ticks = qemu_get_clock(rt_clock);
488 d329a6fb bellard
            delta = ticks - oss.old_ticks;
489 d329a6fb bellard
            oss.old_ticks = ticks;
490 27503323 bellard
491 d329a6fb bellard
            ua_elapsed = (delta * oss.bytes_per_second) / 1000;
492 27503323 bellard
            al_elapsed = ua_elapsed & ~3ULL;
493 27503323 bellard
494 27503323 bellard
            ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
495 27503323 bellard
496 27503323 bellard
            if (al_elapsed > (uint64_t) INT_MAX)
497 27503323 bellard
                elapsed = INT_MAX;
498 27503323 bellard
            else
499 27503323 bellard
                elapsed = al_elapsed;
500 27503323 bellard
501 d329a6fb bellard
            elapsed += oss.leftover;
502 27503323 bellard
        }
503 27503323 bellard
    }
504 27503323 bellard
505 27503323 bellard
    if (elapsed > free) {
506 27503323 bellard
        lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
507 27503323 bellard
        return free;
508 27503323 bellard
    }
509 27503323 bellard
    else {
510 27503323 bellard
        return elapsed;
511 27503323 bellard
    }
512 27503323 bellard
}
513 27503323 bellard
514 27503323 bellard
int AUD_get_live (void)
515 27503323 bellard
{
516 d329a6fb bellard
    return oss.live;
517 27503323 bellard
}
518 27503323 bellard
519 27503323 bellard
int AUD_get_buffer_size (void)
520 27503323 bellard
{
521 d329a6fb bellard
    return oss.bufsize;
522 d329a6fb bellard
}
523 d329a6fb bellard
524 d329a6fb bellard
#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
525 d329a6fb bellard
#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
526 d329a6fb bellard
#define QC_OSS_MMAP "QEMU_OSS_MMAP"
527 d329a6fb bellard
528 d329a6fb bellard
static int get_conf_val (const char *key, int defval)
529 d329a6fb bellard
{
530 d329a6fb bellard
    int val = defval;
531 d329a6fb bellard
    char *strval;
532 d329a6fb bellard
533 d329a6fb bellard
    strval = getenv (key);
534 d329a6fb bellard
    if (strval) {
535 d329a6fb bellard
        val = atoi (strval);
536 d329a6fb bellard
    }
537 d329a6fb bellard
538 d329a6fb bellard
    return val;
539 27503323 bellard
}
540 27503323 bellard
541 27503323 bellard
void AUD_init (void)
542 27503323 bellard
{
543 27503323 bellard
    int fsp;
544 27503323 bellard
545 27503323 bellard
    DEREF (pab);
546 27503323 bellard
547 d329a6fb bellard
    conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize);
548 d329a6fb bellard
    conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags);
549 d329a6fb bellard
    conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap);
550 d329a6fb bellard
551 d329a6fb bellard
    fsp = conf.fragsize;
552 27503323 bellard
    if (0 != (fsp & (fsp - 1))) {
553 27503323 bellard
        Fail ("fragment size %d is not power of 2", fsp);
554 27503323 bellard
    }
555 27503323 bellard
556 d329a6fb bellard
    conf.fragsize = lsbindex (fsp);
557 27503323 bellard
}
558 67b915a5 bellard
559 67b915a5 bellard
#else
560 67b915a5 bellard
561 67b915a5 bellard
void AUD_run (void)
562 67b915a5 bellard
{
563 67b915a5 bellard
}
564 67b915a5 bellard
565 67b915a5 bellard
int AUD_write (void *in_buf, int size)
566 67b915a5 bellard
{
567 67b915a5 bellard
    return 0;
568 67b915a5 bellard
}
569 67b915a5 bellard
570 67b915a5 bellard
void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
571 67b915a5 bellard
{
572 67b915a5 bellard
}
573 67b915a5 bellard
574 67b915a5 bellard
void AUD_adjust_estimate (int _leftover)
575 67b915a5 bellard
{
576 67b915a5 bellard
}
577 67b915a5 bellard
578 67b915a5 bellard
int AUD_get_free (void)
579 67b915a5 bellard
{
580 67b915a5 bellard
    return 0;
581 67b915a5 bellard
}
582 67b915a5 bellard
583 67b915a5 bellard
int AUD_get_live (void)
584 67b915a5 bellard
{
585 67b915a5 bellard
    return 0;
586 67b915a5 bellard
}
587 67b915a5 bellard
588 67b915a5 bellard
int AUD_get_buffer_size (void)
589 67b915a5 bellard
{
590 67b915a5 bellard
    return 0;
591 67b915a5 bellard
}
592 67b915a5 bellard
593 67b915a5 bellard
void AUD_init (void)
594 67b915a5 bellard
{
595 67b915a5 bellard
}
596 67b915a5 bellard
597 67b915a5 bellard
#endif