monitor fixes (Johannes Schindelin)
[qemu] / oss.c
1 /*
2  * QEMU OSS Audio output driver
3  * 
4  * Copyright (c) 2003 Vassili Karpov (malc)
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25
26 #include <stdio.h>
27 #include <limits.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 /* TODO: Graceful error handling */
32
33 #if defined(_WIN32)
34 #define USE_SDL_AUDIO
35 #endif
36
37 #define MIN(a, b) ((a)>(b)?(b):(a))
38 #define MAX(a, b) ((a)<(b)?(b):(a))
39
40 #define DEREF(x) (void)x
41 #define dolog(...) fprintf (stderr, "audio: " __VA_ARGS__)
42 #define ERRFail(...) do {                                               \
43     int _errno = errno;                                                 \
44     fprintf (stderr, "audio: " __VA_ARGS__);                            \
45     fprintf (stderr, "\nsystem error: %s\n", strerror (_errno));        \
46     abort ();                                                           \
47 } while (0)
48 #define Fail(...) do {                          \
49     fprintf (stderr, "audio: " __VA_ARGS__);    \
50     fprintf (stderr, "\n");                     \
51     abort ();                                   \
52 } while (0)
53
54 #ifdef DEBUG_AUDIO
55 #define lwarn(...) fprintf (stderr, "audio: " __VA_ARGS__)
56 #define linfo(...) fprintf (stderr, "audio: " __VA_ARGS__)
57 #define ldebug(...) fprintf (stderr, "audio: " __VA_ARGS__)
58 #else
59 #define lwarn(...)
60 #define linfo(...)
61 #define ldebug(...)
62 #endif
63
64 static int get_conf_val (const char *key, int defval)
65 {
66     int val = defval;
67     char *strval;
68
69     strval = getenv (key);
70     if (strval) {
71         val = atoi (strval);
72     }
73
74     return val;
75 }
76
77 static void copy_no_conversion (void *dst, void *src, int size)
78 {
79     memcpy (dst, src, size);
80 }
81
82 static void copy_u16_to_s16 (void *dst, void *src, int size)
83 {
84     int i;
85     uint16_t *out, *in;
86
87     out = dst;
88     in = src;
89
90     for (i = 0; i < size / 2; i++) {
91         out[i] = in[i] + 0x8000;
92     }
93 }
94
95 #ifdef USE_SDL_AUDIO
96 #include <SDL/SDL.h>
97 #include <SDL/SDL_thread.h>
98
99 static struct {
100     int samples;
101 } conf = {
102     .samples = 4096
103 };
104
105 typedef struct AudioState {
106     int freq;
107     int bits16;
108     int nchannels;
109     int rpos;
110     int wpos;
111     volatile int live;
112     volatile int exit;
113     int bytes_per_second;
114     Uint8 *buf;
115     int bufsize;
116     int leftover;
117     uint64_t old_ticks;
118     SDL_AudioSpec spec;
119     SDL_mutex *mutex;
120     SDL_sem *sem;
121     void (*copy_fn)(void *, void *, int);
122 } AudioState;
123
124 static AudioState sdl_audio;
125
126 void AUD_run (void)
127 {
128 }
129
130 static void own (AudioState *s)
131 {
132     /* SDL_LockAudio (); */
133     if (SDL_mutexP (s->mutex))
134         dolog ("SDL_mutexP: %s\n", SDL_GetError ());
135 }
136
137 static void disown (AudioState *s)
138 {
139     /* SDL_UnlockAudio (); */
140     if (SDL_mutexV (s->mutex))
141         dolog ("SDL_mutexV: %s\n", SDL_GetError ());
142 }
143
144 static void sem_wait (AudioState *s)
145 {
146     if (SDL_SemWait (s->sem))
147         dolog ("SDL_SemWait: %s\n", SDL_GetError ());
148 }
149
150 static void sem_post (AudioState *s)
151 {
152     if (SDL_SemPost (s->sem))
153         dolog ("SDL_SemPost: %s\n", SDL_GetError ());
154 }
155
156 static void audio_callback (void *data, Uint8 *stream, int len)
157 {
158     int to_mix;
159     AudioState *s = data;
160
161     if (s->exit) return;
162     while (len) {
163         sem_wait (s);
164         if (s->exit) return;
165         own (s);
166         to_mix = MIN (len, s->live);
167         len -= to_mix;
168         /* printf ("to_mix=%d len=%d live=%d\n", to_mix, len, s->live); */
169         while (to_mix) {
170             int chunk = MIN (to_mix, s->bufsize - s->rpos);
171             /* SDL_MixAudio (stream, buf, chunk, SDL_MIX_MAXVOLUME); */
172             memcpy (stream, s->buf + s->rpos, chunk);
173
174             s->rpos += chunk;
175             s->live -= chunk;
176
177             stream += chunk;
178             to_mix -= chunk;
179
180             if (s->rpos == s->bufsize) s->rpos = 0;
181         }
182         disown (s);
183     }
184 }
185
186 static void sem_zero (AudioState *s)
187 {
188     int res;
189
190     do {
191         res = SDL_SemTryWait (s->sem);
192         if (res < 0) {
193             dolog ("SDL_SemTryWait: %s\n", SDL_GetError ());
194             return;
195         }
196     } while (res != SDL_MUTEX_TIMEDOUT);
197 }
198
199 static void do_open (AudioState *s)
200 {
201     int status;
202     SDL_AudioSpec obtained;
203
204     SDL_PauseAudio (1);
205     if (s->buf) {
206         s->exit = 1;
207         sem_post (s);
208         SDL_CloseAudio ();
209         s->exit = 0;
210         qemu_free (s->buf);
211         s->buf = NULL;
212         sem_zero (s);
213     }
214
215     s->bytes_per_second = (s->spec.freq << (s->spec.channels >> 1)) << s->bits16;
216     s->spec.samples = conf.samples;
217     s->spec.userdata = s;
218     s->spec.callback = audio_callback;
219
220     status = SDL_OpenAudio (&s->spec, &obtained);
221     if (status < 0) {
222         dolog ("SDL_OpenAudio: %s\n", SDL_GetError ());
223         goto exit;
224     }
225
226     if (obtained.freq != s->spec.freq ||
227         obtained.channels != s->spec.channels ||
228         obtained.format != s->spec.format) {
229         dolog ("Audio spec mismatch requested obtained\n"
230                "freq                %5d    %5d\n"
231                "channels            %5d    %5d\n"
232                "fmt                 %5d    %5d\n",
233                s->spec.freq, obtained.freq,
234                s->spec.channels, obtained.channels,
235                s->spec.format, obtained.format
236             );
237     }
238
239     s->bufsize = obtained.size;
240     s->buf = qemu_mallocz (s->bufsize);
241     if (!s->buf) {
242         dolog ("qemu_mallocz(%d)\n", s->bufsize);
243         goto exit;
244     }
245     SDL_PauseAudio (0);
246
247 exit:
248     s->rpos = 0;
249     s->wpos = 0;
250     s->live = 0;
251 }
252
253 int AUD_write (void *in_buf, int size)
254 {
255     AudioState *s = &sdl_audio;
256     int to_copy, temp;
257     uint8_t *in, *out;
258
259     own (s);
260     to_copy = MIN (s->bufsize - s->live, size);
261
262     temp = to_copy;
263
264     in = in_buf;
265     out = s->buf;
266
267     while (temp) {
268         int copy;
269
270         copy = MIN (temp, s->bufsize - s->wpos);
271         s->copy_fn (out + s->wpos, in, copy);
272
273         s->wpos += copy;
274         if (s->wpos == s->bufsize) {
275             s->wpos = 0;
276         }
277
278         temp -= copy;
279         in += copy;
280         s->live += copy;
281     }
282
283     disown (s);
284     sem_post (s);
285     return to_copy;
286 }
287
288 static void maybe_open (AudioState *s, int req_freq, int req_nchannels,
289                         audfmt_e req_fmt, int force_open)
290 {
291     int sdl_fmt, bits16;
292
293     switch (req_fmt) {
294     case AUD_FMT_U8:
295         bits16 = 0;
296         sdl_fmt = AUDIO_U8;
297         s->copy_fn = copy_no_conversion;
298         break;
299
300     case AUD_FMT_S8:
301         fprintf (stderr, "audio: can not play 8bit signed\n");
302         return;
303
304     case AUD_FMT_S16:
305         bits16 = 1;
306         sdl_fmt = AUDIO_S16;
307         s->copy_fn = copy_no_conversion;
308         break;
309
310     case AUD_FMT_U16:
311         bits16 = 1;
312         sdl_fmt = AUDIO_S16;
313         s->copy_fn = copy_u16_to_s16;
314         break;
315
316     default:
317         abort ();
318     }
319
320     if (force_open
321         || (NULL == s->buf)
322         || (sdl_fmt != s->spec.format)
323         || (req_nchannels != s->spec.channels)
324         || (req_freq != s->spec.freq)
325         || (bits16 != s->bits16)) {
326
327         s->spec.format = sdl_fmt;
328         s->spec.channels = req_nchannels;
329         s->spec.freq = req_freq;
330         s->bits16 = bits16;
331         do_open (s);
332     }
333 }
334
335 void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
336 {
337     AudioState *s = &sdl_audio;
338     own (s);
339     maybe_open (s, req_freq, req_nchannels, req_fmt, 0);
340     disown (s);
341 }
342
343 void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
344 {
345     AudioState *s = &sdl_audio;
346     own (s);
347     maybe_open (s, req_freq, req_nchannels, req_fmt, 1);
348     disown (s);
349 }
350
351 void AUD_adjust_estimate (int leftover)
352 {
353     AudioState *s = &sdl_audio;
354     own (s);
355     s->leftover = leftover;
356     disown (s);
357 }
358
359 int AUD_get_free (void)
360 {
361     int free, elapsed;
362     uint64_t ticks, delta;
363     uint64_t ua_elapsed;
364     uint64_t al_elapsed;
365     AudioState *s = &sdl_audio;
366
367     own (s);
368     free = s->bufsize - s->live;
369
370     if (0 == free) {
371         disown (s);
372         return 0;
373     }
374
375     elapsed = free;
376     ticks = qemu_get_clock(rt_clock);
377     delta = ticks - s->old_ticks;
378     s->old_ticks = ticks;
379
380     ua_elapsed = (delta * s->bytes_per_second) / 1000;
381     al_elapsed = ua_elapsed & ~3ULL;
382
383     ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
384
385     if (al_elapsed > (uint64_t) INT_MAX)
386         elapsed = INT_MAX;
387     else
388         elapsed = al_elapsed;
389
390     elapsed += s->leftover;
391     disown (s);
392
393     if (elapsed > free) {
394         lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
395         return free;
396     }
397     else {
398         return elapsed;
399     }
400 }
401
402 int AUD_get_live (void)
403 {
404     int live;
405     AudioState *s = &sdl_audio;
406
407     own (s);
408     live = s->live;
409     disown (s);
410     return live;
411 }
412
413 int AUD_get_buffer_size (void)
414 {
415     int bufsize;
416     AudioState *s = &sdl_audio;
417
418     own (s);
419     bufsize = s->bufsize;
420     disown (s);
421     return bufsize;
422 }
423
424 #define QC_SDL_NSAMPLES "QEMU_SDL_NSAMPLES"
425
426 static void cleanup (void)
427 {
428     AudioState *s = &sdl_audio;
429     own (s);
430     s->exit = 1;
431     sem_post (s);
432     disown (s);
433 }
434
435 void AUD_init (void)
436 {
437     AudioState *s = &sdl_audio;
438
439     atexit (cleanup);
440     SDL_InitSubSystem (SDL_INIT_AUDIO);
441     s->mutex = SDL_CreateMutex ();
442     if (!s->mutex) {
443         dolog ("SDL_CreateMutex: %s\n", SDL_GetError ());
444         return;
445     }
446
447     s->sem = SDL_CreateSemaphore (0);
448     if (!s->sem) {
449         dolog ("SDL_CreateSemaphore: %s\n", SDL_GetError ());
450         return;
451     }
452
453     conf.samples = get_conf_val (QC_SDL_NSAMPLES, conf.samples);
454 }
455
456 #elif !defined(_WIN32) && !defined(__APPLE__)
457
458 #include <fcntl.h>
459 #include <errno.h>
460 #include <unistd.h>
461 #include <sys/mman.h>
462 #include <sys/types.h>
463 #include <sys/ioctl.h>
464 #include <sys/soundcard.h>
465
466 /* http://www.df.lth.se/~john_e/gems/gem002d.html */
467 /* http://www.multi-platforms.com/Tips/PopCount.htm */
468 static inline uint32_t popcount (uint32_t u)
469 {
470   u = ((u&0x55555555) + ((u>>1)&0x55555555));
471   u = ((u&0x33333333) + ((u>>2)&0x33333333));
472   u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
473   u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
474   u = ( u&0x0000ffff) + (u>>16);
475   return u;
476 }
477
478 static inline uint32_t lsbindex (uint32_t u)
479 {
480   return popcount ((u&-u)-1);
481 }
482
483 #define IOCTL(args) do {                        \
484   int ret = ioctl args;                         \
485   if (-1 == ret) {                              \
486     ERRFail (#args);                            \
487   }                                             \
488   ldebug ("ioctl " #args " = %d\n", ret);       \
489 } while (0)
490
491 typedef struct AudioState {
492     int fd;
493     int freq;
494     int bits16;
495     int nchannels;
496     int rpos;
497     int wpos;
498     int live;
499     int oss_fmt;
500     int bytes_per_second;
501     int is_mapped;
502     void *buf;
503     int bufsize;
504     int nfrags;
505     int fragsize;
506     int old_optr;
507     int leftover;
508     uint64_t old_ticks;
509     void (*copy_fn)(void *, void *, int);
510 } AudioState;
511
512 static AudioState oss_audio = { .fd = -1 };
513
514 static struct {
515     int try_mmap;
516     int nfrags;
517     int fragsize;
518 } conf = {
519     .try_mmap = 0,
520     .nfrags = 4,
521     .fragsize = 4096
522 };
523
524 static enum {DONT, DSP, TID} est = DONT;
525
526 static void pab (AudioState *s, struct audio_buf_info *abinfo)
527 {
528     DEREF (abinfo);
529
530     ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
531             "rpos %d, wpos %d, live %d\n",
532             abinfo->fragments,
533             abinfo->fragstotal,
534             abinfo->fragsize,
535             abinfo->bytes,
536             s->rpos, s->wpos, s->live);
537 }
538
539 static void do_open (AudioState *s)
540 {
541     int mmmmssss;
542     audio_buf_info abinfo;
543     int fmt, freq, nchannels;
544
545     if (s->buf) {
546         if (s->is_mapped) {
547             if (-1 == munmap (s->buf, s->bufsize)) {
548             ERRFail ("failed to unmap audio buffer %p %d",
549                          s->buf, s->bufsize);
550         }
551         }
552         else {
553             qemu_free (s->buf);
554         }
555         s->buf = NULL;
556     }
557
558     if (-1 != s->fd)
559         close (s->fd);
560
561     s->fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK);
562     if (-1 == s->fd) {
563         ERRFail ("can not open /dev/dsp");
564     }
565
566     fmt = s->oss_fmt;
567     freq = s->freq;
568     nchannels = s->nchannels;
569
570     IOCTL ((s->fd, SNDCTL_DSP_RESET, 1));
571     IOCTL ((s->fd, SNDCTL_DSP_SAMPLESIZE, &fmt));
572     IOCTL ((s->fd, SNDCTL_DSP_CHANNELS, &nchannels));
573     IOCTL ((s->fd, SNDCTL_DSP_SPEED, &freq));
574     IOCTL ((s->fd, SNDCTL_DSP_NONBLOCK));
575
576     mmmmssss = (conf.nfrags << 16) | conf.fragsize;
577     IOCTL ((s->fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
578
579     if ((s->oss_fmt != fmt)
580         || (s->nchannels != nchannels)
581         || (s->freq != freq)) {
582         Fail ("failed to set audio parameters\n"
583               "parameter | requested value | obtained value\n"
584               "format    |      %10d |     %10d\n"
585               "channels  |      %10d |     %10d\n"
586               "frequency |      %10d |     %10d\n",
587               s->oss_fmt, fmt,
588               s->nchannels, nchannels,
589               s->freq, freq);
590     }
591
592     IOCTL ((s->fd, SNDCTL_DSP_GETOSPACE, &abinfo));
593
594     s->nfrags = abinfo.fragstotal;
595     s->fragsize = abinfo.fragsize;
596     s->bufsize = s->nfrags * s->fragsize;
597     s->old_optr = 0;
598
599     s->bytes_per_second = (freq << (nchannels >> 1)) << s->bits16;
600
601     linfo ("bytes per second %d\n", s->bytes_per_second);
602
603     linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
604            abinfo.fragments,
605            abinfo.fragstotal,
606            abinfo.fragsize,
607            abinfo.bytes,
608            s->bufsize);
609
610     s->buf = MAP_FAILED;
611     s->is_mapped = 0;
612
613     if (conf.try_mmap) {
614         s->buf = mmap (NULL, s->bufsize, PROT_WRITE, MAP_SHARED, s->fd, 0);
615         if (MAP_FAILED == s->buf) {
616             int err;
617
618             err = errno;
619             dolog ("failed to mmap audio, size %d, fd %d\n"
620                  "syserr: %s\n",
621                    s->bufsize, s->fd, strerror (err));
622         }
623     else {
624             est = TID;
625             s->is_mapped = 1;
626         }
627     }
628
629     if (MAP_FAILED == s->buf) {
630         est = TID;
631         s->buf = qemu_mallocz (s->bufsize);
632         if (!s->buf) {
633             ERRFail ("audio buf malloc failed, size %d", s->bufsize);
634         }
635     }
636
637     s->rpos = 0;
638     s->wpos = 0;
639     s->live = 0;
640
641     if (s->is_mapped) {
642         int trig;
643
644         trig = 0;
645         IOCTL ((s->fd, SNDCTL_DSP_SETTRIGGER, &trig));
646         trig = PCM_ENABLE_OUTPUT;
647         IOCTL ((s->fd, SNDCTL_DSP_SETTRIGGER, &trig));
648     }
649 }
650
651 static void maybe_open (AudioState *s, int req_freq, int req_nchannels,
652                         audfmt_e req_fmt, int force_open)
653 {
654     int oss_fmt, bits16;
655
656     switch (req_fmt) {
657     case AUD_FMT_U8:
658         bits16 = 0;
659         oss_fmt = AFMT_U8;
660         s->copy_fn = copy_no_conversion;
661         break;
662
663     case AUD_FMT_S8:
664         Fail ("can not play 8bit signed");
665
666     case AUD_FMT_S16:
667         bits16 = 1;
668         oss_fmt = AFMT_S16_LE;
669         s->copy_fn = copy_no_conversion;
670         break;
671
672     case AUD_FMT_U16:
673         bits16 = 1;
674         oss_fmt = AFMT_S16_LE;
675         s->copy_fn = copy_u16_to_s16;
676         break;
677
678     default:
679         abort ();
680     }
681
682     if (force_open
683         || (-1 == s->fd)
684         || (oss_fmt != s->oss_fmt)
685         || (req_nchannels != s->nchannels)
686         || (req_freq != s->freq)
687         || (bits16 != s->bits16)) {
688         s->oss_fmt = oss_fmt;
689         s->nchannels = req_nchannels;
690         s->freq = req_freq;
691         s->bits16 = bits16;
692         do_open (s);
693     }
694 }
695
696 void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
697 {
698     AudioState *s = &oss_audio;
699     maybe_open (s, req_freq, req_nchannels, req_fmt, 0);
700 }
701
702 void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
703 {
704     AudioState *s = &oss_audio;
705     maybe_open (s, req_freq, req_nchannels, req_fmt, 1);
706 }
707
708 int AUD_write (void *in_buf, int size)
709 {
710     AudioState *s = &oss_audio;
711     int to_copy, temp;
712     uint8_t *in, *out;
713
714     to_copy = MIN (s->bufsize - s->live, size);
715
716     temp = to_copy;
717
718     in = in_buf;
719     out = s->buf;
720
721     while (temp) {
722         int copy;
723
724         copy = MIN (temp, s->bufsize - s->wpos);
725         s->copy_fn (out + s->wpos, in, copy);
726
727         s->wpos += copy;
728         if (s->wpos == s->bufsize) {
729             s->wpos = 0;
730         }
731
732         temp -= copy;
733         in += copy;
734         s->live += copy;
735     }
736
737     return to_copy;
738 }
739
740 void AUD_run (void)
741 {
742     int res;
743     int bytes;
744     struct audio_buf_info abinfo;
745     AudioState *s = &oss_audio;
746
747     if (0 == s->live)
748         return;
749
750     if (s->is_mapped) {
751         count_info info;
752
753         res = ioctl (s->fd, SNDCTL_DSP_GETOPTR, &info);
754         if (res < 0) {
755             int err;
756
757             err = errno;
758             lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
759             return;
760         }
761
762         if (info.ptr > s->old_optr) {
763             bytes = info.ptr - s->old_optr;
764         }
765         else {
766             bytes = s->bufsize + info.ptr - s->old_optr;
767         }
768
769         s->old_optr = info.ptr;
770         s->live -= bytes;
771         return;
772     }
773
774     res = ioctl (s->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
775
776     if (res < 0) {
777         int err;
778
779         err = errno;
780         lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err));
781         return;
782     }
783
784     bytes = abinfo.bytes;
785     bytes = MIN (s->live, bytes);
786 #if 0
787     bytes = (bytes / fragsize) * fragsize;
788 #endif
789
790     while (bytes) {
791         int left, play, written;
792
793         left = s->bufsize - s->rpos;
794         play = MIN (left, bytes);
795         written = write (s->fd, (uint8_t *)s->buf + s->rpos, play);
796
797         if (-1 == written) {
798             if (EAGAIN == errno || EINTR == errno) {
799                 return;
800             }
801             else {
802                 ERRFail ("write audio");
803             }
804         }
805
806         play = written;
807         s->live -= play;
808         s->rpos += play;
809         bytes -= play;
810
811         if (s->rpos == s->bufsize) {
812             s->rpos = 0;
813         }
814     }
815 }
816
817 static int get_dsp_bytes (void)
818 {
819     int res;
820     struct count_info info;
821     AudioState *s = &oss_audio;
822
823     res = ioctl (s->fd, SNDCTL_DSP_GETOPTR, &info);
824     if (-1 == res) {
825         int err;
826
827         err = errno;
828         lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
829         return -1;
830     }
831     else {
832         ldebug ("bytes %d\n", info.bytes);
833         return info.bytes;
834     }
835 }
836
837 void AUD_adjust_estimate (int leftover)
838 {
839     AudioState *s = &oss_audio;
840     s->leftover = leftover;
841 }
842
843 int AUD_get_free (void)
844 {
845     int free, elapsed;
846     AudioState *s = &oss_audio;
847
848     free = s->bufsize - s->live;
849
850     if (free <= 0)
851         return 0;
852
853     elapsed = free;
854     switch (est) {
855     case DONT:
856         break;
857
858     case DSP:
859         {
860             static int old_bytes;
861             int bytes;
862
863             bytes = get_dsp_bytes ();
864             if (bytes <= 0)
865                 return free;
866
867             elapsed = bytes - old_bytes;
868             old_bytes = bytes;
869             ldebug ("dsp elapsed %d bytes\n", elapsed);
870             break;
871         }
872
873     case TID:
874         {
875             uint64_t ticks, delta;
876             uint64_t ua_elapsed;
877             uint64_t al_elapsed;
878
879             ticks = qemu_get_clock(rt_clock);
880             delta = ticks - s->old_ticks;
881             s->old_ticks = ticks;
882
883             ua_elapsed = (delta * s->bytes_per_second) / 1000;
884             al_elapsed = ua_elapsed & ~3ULL;
885
886             ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
887
888             if (al_elapsed > (uint64_t) INT_MAX)
889                 elapsed = INT_MAX;
890             else
891                 elapsed = al_elapsed;
892
893             elapsed += s->leftover;
894         }
895     }
896
897     if (elapsed > free) {
898         lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
899         return free;
900     }
901     else {
902         return elapsed;
903     }
904 }
905
906 int AUD_get_live (void)
907 {
908     AudioState *s = &oss_audio;
909     return s->live;
910 }
911
912 int AUD_get_buffer_size (void)
913 {
914     AudioState *s = &oss_audio;
915     return s->bufsize;
916 }
917
918 #define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
919 #define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
920 #define QC_OSS_MMAP "QEMU_OSS_MMAP"
921
922 void AUD_init (void)
923 {
924     int fsp;
925
926     DEREF (pab);
927
928     conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize);
929     conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags);
930     conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap);
931
932     fsp = conf.fragsize;
933     if (0 != (fsp & (fsp - 1))) {
934         Fail ("fragment size %d is not power of 2", fsp);
935     }
936
937     conf.fragsize = lsbindex (fsp);
938 }
939
940 #else
941
942 void AUD_run (void)
943 {
944 }
945
946 int AUD_write (void *in_buf, int size)
947 {
948     return 0;
949 }
950
951 void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
952 {
953 }
954
955 void AUD_adjust_estimate (int _leftover)
956 {
957 }
958
959 int AUD_get_free (void)
960 {
961     return 0;
962 }
963
964 int AUD_get_live (void)
965 {
966     return 0;
967 }
968
969 int AUD_get_buffer_size (void)
970 {
971     return 0;
972 }
973
974 void AUD_init (void)
975 {
976 }
977
978 #endif