]> git.proxmox.com Git - mirror_qemu.git/blame - oss.c
ide select logic fix
[mirror_qemu.git] / oss.c
CommitLineData
27503323
FB
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 */
67b915a5
FB
24#include "vl.h"
25
26#ifndef _WIN32
27503323
FB
27#include <fcntl.h>
28#include <errno.h>
29#include <stdio.h>
30#include <unistd.h>
31#include <string.h>
32#include <stdlib.h>
33#include <limits.h>
34#include <inttypes.h>
35#include <sys/types.h>
36#include <sys/ioctl.h>
37#include <sys/soundcard.h>
38
27503323
FB
39
40/* http://www.df.lth.se/~john_e/gems/gem002d.html */
41/* http://www.multi-platforms.com/Tips/PopCount.htm */
42static inline uint32_t popcount (uint32_t u)
43{
44 u = ((u&0x55555555) + ((u>>1)&0x55555555));
45 u = ((u&0x33333333) + ((u>>2)&0x33333333));
46 u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
47 u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
48 u = ( u&0x0000ffff) + (u>>16);
49 return u;
50}
51
52static inline uint32_t lsbindex (uint32_t u)
53{
54 return popcount ((u&-u)-1);
55}
56
57#define MIN(a, b) ((a)>(b)?(b):(a))
58#define MAX(a, b) ((a)<(b)?(b):(a))
59
60#define DEREF(x) (void)x
61#define log(...) fprintf (stderr, "oss: " __VA_ARGS__)
62#define ERRFail(...) do { \
63 int _errno = errno; \
64 fprintf (stderr, "oss: " __VA_ARGS__); \
65 fprintf (stderr, "system error: %s\n", strerror (_errno)); \
66 abort (); \
67} while (0)
68#define Fail(...) do { \
69 fprintf (stderr, "oss: " __VA_ARGS__); \
70 fprintf (stderr, "\n"); \
71 abort (); \
72} while (0)
73
74#ifdef DEBUG_OSS
75#define lwarn(...) fprintf (stderr, "oss: " __VA_ARGS__)
76#define linfo(...) fprintf (stderr, "oss: " __VA_ARGS__)
77#define ldebug(...) fprintf (stderr, "oss: " __VA_ARGS__)
78#else
79#define lwarn(...)
80#define linfo(...)
81#define ldebug(...)
82#endif
83
84
85#define IOCTL(args) do { \
86 int ret = ioctl args; \
87 if (-1 == ret) { \
88 ERRFail (#args); \
89 } \
90 ldebug ("ioctl " #args " = %d\n", ret); \
91} while (0)
92
93static int audio_fd = -1;
94static int freq;
95static int conf_nfrags = 4;
96static int conf_fragsize;
97static int nfrags;
98static int fragsize;
99static int bufsize;
100static int nchannels;
101static int fmt;
102static int rpos;
103static int wpos;
104static int atom;
105static int live;
106static int leftover;
107static int bytes_per_second;
108static void *buf;
109static enum {DONT, DSP, TID} estimate = TID;
110
111static void (*copy_fn)(void *, void *, int);
112
113static void copy_no_conversion (void *dst, void *src, int size)
114{
115 memcpy (dst, src, size);
116}
117
118static void copy_u16_to_s16 (void *dst, void *src, int size)
119{
120 int i;
121 uint16_t *out, *in;
122
123 out = dst;
124 in = src;
125
126 for (i = 0; i < size / 2; i++) {
127 out[i] = in[i] + 0x8000;
128 }
129}
130
131static void pab (struct audio_buf_info *abinfo)
132{
133 DEREF (abinfo);
134
135 ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
136 "rpos %d, wpos %d, live %d\n",
137 abinfo->fragments,
138 abinfo->fragstotal,
139 abinfo->fragsize,
140 abinfo->bytes,
141 rpos, wpos, live);
142}
143
144void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
145{
146 int fmt_;
147 int bits16;
148
149 if (-1 == audio_fd) {
150 AUD_open (rfreq, rnchannels, rfmt);
151 return;
152 }
153
154 switch (rfmt) {
155 case AUD_FMT_U8:
156 bits16 = 0;
157 fmt_ = AFMT_U8;
158 copy_fn = copy_no_conversion;
159 atom = 1;
160 break;
161
162 case AUD_FMT_S8:
163 Fail ("can not play 8bit signed");
164
165 case AUD_FMT_S16:
166 bits16 = 1;
167 fmt_ = AFMT_S16_LE;
168 copy_fn = copy_no_conversion;
169 atom = 2;
170 break;
171
172 case AUD_FMT_U16:
173 bits16 = 1;
174 fmt_ = AFMT_S16_LE;
175 copy_fn = copy_u16_to_s16;
176 atom = 2;
177 break;
178
179 default:
180 abort ();
181 }
182
183 if ((fmt_ == fmt) && (bits16 + 1 == nchannels) && (rfreq == freq))
184 return;
185 else {
186 AUD_open (rfreq, rnchannels, rfmt);
187 }
188}
189
190void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt)
191{
192 int fmt_;
193 int mmmmssss;
194 struct audio_buf_info abinfo;
195 int _fmt;
196 int _freq;
197 int _nchannels;
198 int bits16;
199
200 bits16 = 0;
201
202 switch (rfmt) {
203 case AUD_FMT_U8:
204 bits16 = 0;
205 fmt_ = AFMT_U8;
206 copy_fn = copy_no_conversion;
207 atom = 1;
208 break;
209
210 case AUD_FMT_S8:
211 Fail ("can not play 8bit signed");
212
213 case AUD_FMT_S16:
214 bits16 = 1;
215 fmt_ = AFMT_S16_LE;
216 copy_fn = copy_no_conversion;
217 atom = 2;
218 break;
219
220 case AUD_FMT_U16:
221 bits16 = 1;
222 fmt_ = AFMT_S16_LE;
223 copy_fn = copy_u16_to_s16;
224 atom = 2;
225 break;
226
227 default:
228 abort ();
229 }
230
231 if (buf) {
232 free (buf);
233 buf = 0;
234 }
235
236 if (-1 != audio_fd)
237 close (audio_fd);
238
239 audio_fd = open ("/dev/dsp", O_WRONLY | O_NONBLOCK);
240 if (-1 == audio_fd) {
241 ERRFail ("can not open /dev/dsp");
242 }
243
244 _fmt = fmt_;
245 _freq = rfreq;
246 _nchannels = rnchannels;
247
248 IOCTL ((audio_fd, SNDCTL_DSP_RESET, 1));
249 IOCTL ((audio_fd, SNDCTL_DSP_SAMPLESIZE, &_fmt));
250 IOCTL ((audio_fd, SNDCTL_DSP_CHANNELS, &_nchannels));
251 IOCTL ((audio_fd, SNDCTL_DSP_SPEED, &_freq));
252 IOCTL ((audio_fd, SNDCTL_DSP_NONBLOCK));
253
254 /* from oss.pdf:
255
256 The argument to this call is an integer encoded as 0xMMMMSSSS (in
257 hex). The 16 least significant bits determine the fragment
258 size. The size is 2^SSSS. For examp le SSSS=0008 gives fragment
259 size of 256 bytes (2^8). The minimum is 16 bytes (SSSS=4) and the
260 maximum is total_buffer_size/2. Some devices or processor
261 architectures may require larger fragments - in this case the
262 requested fragment size is automatically increased.
263
264 So ahem... 4096 = 2^12, and grand total 0x0004000c
265 */
266
267 mmmmssss = (conf_nfrags << 16) | conf_fragsize;
268 IOCTL ((audio_fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
269
270 linfo ("_fmt = %d, fmt = %d\n"
271 "_channels = %d, rnchannels = %d\n"
272 "_freq = %d, freq = %d\n",
273 _fmt, fmt_,
274 _nchannels, rnchannels,
275 _freq, rfreq);
276
277 if (_fmt != fmt_) {
278 Fail ("format %d != %d", _fmt, fmt_);
279 }
280
281 if (_nchannels != rnchannels) {
282 Fail ("channels %d != %d", _nchannels, rnchannels);
283 }
284
285 if (_freq != rfreq) {
286 Fail ("freq %d != %d", _freq, rfreq);
287 }
288
289 IOCTL ((audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo));
290
291 nfrags = abinfo.fragstotal;
292 fragsize = abinfo.fragsize;
293 freq = _freq;
294 fmt = _fmt;
295 nchannels = rnchannels;
296 atom <<= nchannels >> 1;
297 bufsize = nfrags * fragsize;
298
299 bytes_per_second = (freq << (nchannels >> 1)) << bits16;
300
301 linfo ("bytes per second %d\n", bytes_per_second);
302
303 linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
304 abinfo.fragments,
305 abinfo.fragstotal,
306 abinfo.fragsize,
307 abinfo.bytes,
308 bufsize);
309
310 if (NULL == buf) {
311 buf = malloc (bufsize);
312 if (NULL == buf) {
313 abort ();
314 }
315 }
316
317 rpos = 0;
318 wpos = 0;
319 live = 0;
320}
321
322int AUD_write (void *in_buf, int size)
323{
324 int to_copy, temp;
325 uint8_t *in, *out;
326
327 to_copy = MIN (bufsize - live, size);
328
329 temp = to_copy;
330
331 in = in_buf;
332 out = buf;
333
334 while (temp) {
335 int copy;
336
337 copy = MIN (temp, bufsize - wpos);
338 copy_fn (out + wpos, in, copy);
339
340 wpos += copy;
341 if (wpos == bufsize) {
342 wpos = 0;
343 }
344
345 temp -= copy;
346 in += copy;
347 live += copy;
348 }
349
350 return to_copy;
351}
352
353void AUD_run (void)
354{
355 int res;
356 int bytes;
357 struct audio_buf_info abinfo;
358
359 if (0 == live)
360 return;
361
362 res = ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo);
363
364 if (-1 == res) {
365 int err;
366
367 err = errno;
368 lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err));
369 }
370
371 bytes = abinfo.bytes;
372 bytes = MIN (live, bytes);
373#if 0
374 bytes = (bytes / fragsize) * fragsize;
375#endif
376
377 while (bytes) {
378 int left, play, written;
379
380 left = bufsize - rpos;
381 play = MIN (left, bytes);
382 written = write (audio_fd, (void *) ((uint32_t) buf + rpos), play);
383
384 if (-1 == written) {
385 if (EAGAIN == errno || EINTR == errno) {
386 return;
387 }
388 else {
389 ERRFail ("write audio");
390 }
391 }
392
393 play = written;
394 live -= play;
395 rpos += play;
396 bytes -= play;
397
398 if (rpos == bufsize) {
399 rpos = 0;
400 }
401 }
402}
403
404static int get_dsp_bytes (void)
405{
406 int res;
407 struct count_info info;
408
409 res = ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &info);
410 if (-1 == res) {
411 int err;
412
413 err = errno;
414 lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
415 return -1;
416 }
417 else {
418 ldebug ("bytes %d\n", info.bytes);
419 return info.bytes;
420 }
421}
422
423void AUD_adjust_estimate (int _leftover)
424{
425 leftover = _leftover;
426}
427
428int AUD_get_free (void)
429{
430 int free, elapsed;
431
432 free = bufsize - live;
433
434 if (0 == free)
435 return 0;
436
437 elapsed = free;
438 switch (estimate) {
439 case DONT:
440 break;
441
442 case DSP:
443 {
444 static int old_bytes;
445 int bytes;
446
447 bytes = get_dsp_bytes ();
448 if (bytes <= 0)
449 return free;
450
451 elapsed = bytes - old_bytes;
452 old_bytes = bytes;
453 ldebug ("dsp elapsed %d bytes\n", elapsed);
454 break;
455 }
456
457 case TID:
458 {
459 static uint64_t old_ticks;
460 uint64_t ticks, delta;
461 uint64_t ua_elapsed;
462 uint64_t al_elapsed;
463
8a7ddc38 464 ticks = qemu_get_clock(rt_clock);
27503323
FB
465 delta = ticks - old_ticks;
466 old_ticks = ticks;
467
8a7ddc38 468 ua_elapsed = (delta * bytes_per_second) / 1000;
27503323
FB
469 al_elapsed = ua_elapsed & ~3ULL;
470
471 ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
472
473 if (al_elapsed > (uint64_t) INT_MAX)
474 elapsed = INT_MAX;
475 else
476 elapsed = al_elapsed;
477
478 elapsed += leftover;
479 }
480 }
481
482 if (elapsed > free) {
483 lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
484 return free;
485 }
486 else {
487 return elapsed;
488 }
489}
490
491int AUD_get_live (void)
492{
493 return live;
494}
495
496int AUD_get_buffer_size (void)
497{
498 return bufsize;
499}
500
501void AUD_init (void)
502{
503 int fsp;
504 int _fragsize = 4096;
505
506 DEREF (pab);
507
508 fsp = _fragsize;
509 if (0 != (fsp & (fsp - 1))) {
510 Fail ("fragment size %d is not power of 2", fsp);
511 }
512
513 conf_fragsize = lsbindex (fsp);
514}
67b915a5
FB
515
516#else
517
518void AUD_run (void)
519{
520}
521
522int AUD_write (void *in_buf, int size)
523{
524 return 0;
525}
526
527void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
528{
529}
530
531void AUD_adjust_estimate (int _leftover)
532{
533}
534
535int AUD_get_free (void)
536{
537 return 0;
538}
539
540int AUD_get_live (void)
541{
542 return 0;
543}
544
545int AUD_get_buffer_size (void)
546{
547 return 0;
548}
549
550void AUD_init (void)
551{
552}
553
554#endif