Commit d329a6fb2213e53008a9b1cd186fe2ff258fa272
1 parent
7ebb5e41
audip fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@911 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
275 additions
and
198 deletions
hw/sb16.c
... | ... | @@ -26,7 +26,10 @@ |
26 | 26 | #define MIN(a, b) ((a)>(b)?(b):(a)) |
27 | 27 | #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) |
28 | 28 | |
29 | -#define log(...) fprintf (stderr, "sb16: " __VA_ARGS__) | |
29 | +#define log(...) do { \ | |
30 | + fprintf (stderr, "sb16: " __VA_ARGS__); \ | |
31 | + fputc ('\n', stderr); \ | |
32 | +} while (0) | |
30 | 33 | |
31 | 34 | /* #define DEBUG_SB16 */ |
32 | 35 | #ifdef DEBUG_SB16 |
... | ... | @@ -44,6 +47,8 @@ |
44 | 47 | #define IO_WRITE_PROTO(name) \ |
45 | 48 | void name (void *opaque, uint32_t nport, uint32_t val) |
46 | 49 | |
50 | +static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; | |
51 | + | |
47 | 52 | static struct { |
48 | 53 | int ver_lo; |
49 | 54 | int ver_hi; |
... | ... | @@ -76,7 +81,7 @@ typedef struct SB16State { |
76 | 81 | int v2x6; |
77 | 82 | |
78 | 83 | uint8_t in_data[10]; |
79 | - uint8_t out_data[10]; | |
84 | + uint8_t out_data[50]; | |
80 | 85 | |
81 | 86 | int left_till_irq; |
82 | 87 | |
... | ... | @@ -223,6 +228,20 @@ static void command (SB16State *dsp, uint8_t cmd) |
223 | 228 | /* IMS uses those when probing for sound devices */ |
224 | 229 | return; |
225 | 230 | |
231 | + case 0x04: | |
232 | + dsp->needed_bytes = 1; | |
233 | + break; | |
234 | + | |
235 | + case 0x05: | |
236 | + case 0x0e: | |
237 | + dsp->needed_bytes = 2; | |
238 | + break; | |
239 | + | |
240 | + case 0x0f: | |
241 | + dsp->needed_bytes = 1; | |
242 | + dsp_out_data (dsp, 0); | |
243 | + break; | |
244 | + | |
226 | 245 | case 0x10: |
227 | 246 | dsp->needed_bytes = 1; |
228 | 247 | break; |
... | ... | @@ -274,8 +293,8 @@ static void command (SB16State *dsp, uint8_t cmd) |
274 | 293 | uint8_t d0; |
275 | 294 | |
276 | 295 | d0 = 4; |
277 | - if (dsp->fmt_signed) d0 |= 16; | |
278 | - if (dsp->fmt_stereo) d0 |= 32; | |
296 | + /* if (dsp->fmt_signed) d0 |= 16; */ | |
297 | + /* if (dsp->fmt_stereo) d0 |= 32; */ | |
279 | 298 | dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1); |
280 | 299 | cmd = -1; |
281 | 300 | break; |
... | ... | @@ -324,6 +343,14 @@ static void command (SB16State *dsp, uint8_t cmd) |
324 | 343 | dsp_out_data(dsp, sb.ver_hi); |
325 | 344 | return; |
326 | 345 | |
346 | + case 0xe3: | |
347 | + { | |
348 | + int i; | |
349 | + for (i = sizeof (e3) - 1; i >= 0; --i) | |
350 | + dsp_out_data (dsp, e3[i]); | |
351 | + return; | |
352 | + } | |
353 | + | |
327 | 354 | case 0xf2: |
328 | 355 | dsp_out_data(dsp, 0xaa); |
329 | 356 | dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80]; |
... | ... | @@ -360,6 +387,11 @@ static void complete (SB16State *dsp) |
360 | 387 | } |
361 | 388 | else { |
362 | 389 | switch (dsp->cmd) { |
390 | + case 0x05: | |
391 | + case 0x04: | |
392 | + case 0x0e: | |
393 | + case 0x0f: | |
394 | + break; | |
363 | 395 | |
364 | 396 | case 0x10: |
365 | 397 | break; |
... | ... | @@ -425,8 +457,10 @@ static IO_WRITE_PROTO (dsp_write) |
425 | 457 | |
426 | 458 | iport = nport - sb.port; |
427 | 459 | |
460 | + ldebug ("write %#x %#x\n", nport, iport); | |
428 | 461 | switch (iport) { |
429 | 462 | case 0x6: |
463 | + control (0); | |
430 | 464 | if (0 == val) |
431 | 465 | dsp->v2x6 = 0; |
432 | 466 | else if ((1 == val) && (0 == dsp->v2x6)) { |
... | ... | @@ -477,7 +511,7 @@ static IO_READ_PROTO (dsp_read) |
477 | 511 | if (dsp->out_data_len) { |
478 | 512 | retval = dsp->out_data[--dsp->out_data_len]; |
479 | 513 | } else { |
480 | - log("empty output buffer\n"); | |
514 | + log("empty output buffer"); | |
481 | 515 | goto error; |
482 | 516 | } |
483 | 517 | break; |
... | ... | @@ -487,7 +521,7 @@ static IO_READ_PROTO (dsp_read) |
487 | 521 | break; |
488 | 522 | |
489 | 523 | case 0xd: /* timer interrupt clear */ |
490 | - log("timer interrupt clear\n"); | |
524 | + log("timer interrupt clear"); | |
491 | 525 | goto error; |
492 | 526 | |
493 | 527 | case 0xe: /* data available status | irq 8 ack */ |
... | ... | @@ -669,7 +703,7 @@ static int magic_of_irq (int irq) |
669 | 703 | case 10: |
670 | 704 | return 8; |
671 | 705 | default: |
672 | - log ("bad irq %d\n", irq); | |
706 | + log ("bad irq %d", irq); | |
673 | 707 | return 2; |
674 | 708 | } |
675 | 709 | } |
... | ... | @@ -687,7 +721,7 @@ static int irq_of_magic (int magic) |
687 | 721 | case 8: |
688 | 722 | return 10; |
689 | 723 | default: |
690 | - log ("bad irq magic %d\n", magic); | |
724 | + log ("bad irq magic %d", magic); | |
691 | 725 | return 2; |
692 | 726 | } |
693 | 727 | } | ... | ... |
oss.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include "vl.h" |
25 | 25 | |
26 | 26 | #ifndef _WIN32 |
27 | +#include <ctype.h> | |
27 | 28 | #include <fcntl.h> |
28 | 29 | #include <errno.h> |
29 | 30 | #include <stdio.h> |
... | ... | @@ -32,6 +33,7 @@ |
32 | 33 | #include <stdlib.h> |
33 | 34 | #include <limits.h> |
34 | 35 | #include <inttypes.h> |
36 | +#include <sys/mman.h> | |
35 | 37 | #include <sys/types.h> |
36 | 38 | #include <sys/ioctl.h> |
37 | 39 | #include <sys/soundcard.h> |
... | ... | @@ -90,25 +92,38 @@ static inline uint32_t lsbindex (uint32_t u) |
90 | 92 | ldebug ("ioctl " #args " = %d\n", ret); \ |
91 | 93 | } while (0) |
92 | 94 | |
93 | -static int audio_fd = -1; | |
94 | -static int freq; | |
95 | -static int conf_nfrags = 4; | |
96 | -static int conf_fragsize; | |
97 | -static int nfrags; | |
98 | -static int fragsize; | |
99 | -static int bufsize; | |
100 | -static int nchannels; | |
101 | -static int fmt; | |
102 | -static int rpos; | |
103 | -static int wpos; | |
104 | -static int atom; | |
105 | -static int live; | |
106 | -static int leftover; | |
107 | -static int bytes_per_second; | |
108 | -static void *buf; | |
109 | -static enum {DONT, DSP, TID} estimate = TID; | |
110 | - | |
111 | -static void (*copy_fn)(void *, void *, int); | |
95 | +static struct { | |
96 | + int fd; | |
97 | + int freq; | |
98 | + int bits16; | |
99 | + int nchannels; | |
100 | + int rpos; | |
101 | + int wpos; | |
102 | + int live; | |
103 | + int oss_fmt; | |
104 | + int bytes_per_second; | |
105 | + int is_mapped; | |
106 | + void *buf; | |
107 | + int bufsize; | |
108 | + int nfrags; | |
109 | + int fragsize; | |
110 | + int old_optr; | |
111 | + int leftover; | |
112 | + uint64_t old_ticks; | |
113 | + void (*copy_fn)(void *, void *, int); | |
114 | +} oss = { .fd = -1 }; | |
115 | + | |
116 | +static struct { | |
117 | + int try_mmap; | |
118 | + int nfrags; | |
119 | + int fragsize; | |
120 | +} conf = { | |
121 | + .try_mmap = 0, | |
122 | + .nfrags = 4, | |
123 | + .fragsize = 4096 | |
124 | +}; | |
125 | + | |
126 | +static enum {DONT, DSP, TID} est = DONT; | |
112 | 127 | |
113 | 128 | static void copy_no_conversion (void *dst, void *src, int size) |
114 | 129 | { |
... | ... | @@ -141,70 +156,124 @@ static void pab (struct audio_buf_info *abinfo) |
141 | 156 | rpos, wpos, live); |
142 | 157 | } |
143 | 158 | |
144 | -void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt) | |
159 | +static void do_open () | |
145 | 160 | { |
146 | - int fmt_; | |
147 | - int bits16; | |
161 | + int mmmmssss; | |
162 | + audio_buf_info abinfo; | |
163 | + int fmt, freq, nchannels; | |
148 | 164 | |
149 | - if (-1 == audio_fd) { | |
150 | - AUD_open (rfreq, rnchannels, rfmt); | |
151 | - return; | |
165 | + if (oss.buf) { | |
166 | + if (-1 == munmap (oss.buf, oss.bufsize)) { | |
167 | + ERRFail ("failed to unmap audio buffer %p %d", | |
168 | + oss.buf, oss.bufsize); | |
169 | + } | |
170 | + oss.buf = NULL; | |
152 | 171 | } |
153 | 172 | |
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; | |
173 | + if (-1 != oss.fd) | |
174 | + close (oss.fd); | |
161 | 175 | |
162 | - case AUD_FMT_S8: | |
163 | - Fail ("can not play 8bit signed"); | |
176 | + oss.fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK); | |
177 | + if (-1 == oss.fd) { | |
178 | + ERRFail ("can not open /dev/dsp"); | |
179 | + } | |
164 | 180 | |
165 | - case AUD_FMT_S16: | |
166 | - bits16 = 1; | |
167 | - fmt_ = AFMT_S16_LE; | |
168 | - copy_fn = copy_no_conversion; | |
169 | - atom = 2; | |
170 | - break; | |
181 | + fmt = oss.oss_fmt; | |
182 | + freq = oss.freq; | |
183 | + nchannels = oss.nchannels; | |
184 | + | |
185 | + IOCTL ((oss.fd, SNDCTL_DSP_RESET, 1)); | |
186 | + IOCTL ((oss.fd, SNDCTL_DSP_SAMPLESIZE, &fmt)); | |
187 | + IOCTL ((oss.fd, SNDCTL_DSP_CHANNELS, &nchannels)); | |
188 | + IOCTL ((oss.fd, SNDCTL_DSP_SPEED, &freq)); | |
189 | + IOCTL ((oss.fd, SNDCTL_DSP_NONBLOCK)); | |
190 | + | |
191 | + mmmmssss = (conf.nfrags << 16) | conf.fragsize; | |
192 | + IOCTL ((oss.fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)); | |
193 | + | |
194 | + if ((oss.oss_fmt != fmt) | |
195 | + || (oss.nchannels != nchannels) | |
196 | + || (oss.freq != freq)) { | |
197 | + Fail ("failed to set audio parameters\n" | |
198 | + "parameter | requested value | obtained value\n" | |
199 | + "format | %10d | %10d\n" | |
200 | + "channels | %10d | %10d\n" | |
201 | + "frequency | %10d | %10d\n", | |
202 | + oss.oss_fmt, fmt, | |
203 | + oss.nchannels, nchannels, | |
204 | + oss.freq, freq); | |
205 | + } | |
171 | 206 | |
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; | |
207 | + IOCTL ((oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo)); | |
178 | 208 | |
179 | - default: | |
180 | - abort (); | |
181 | - } | |
209 | + oss.nfrags = abinfo.fragstotal; | |
210 | + oss.fragsize = abinfo.fragsize; | |
211 | + oss.bufsize = oss.nfrags * oss.fragsize; | |
212 | + oss.old_optr = 0; | |
182 | 213 | |
183 | - if ((fmt_ == fmt) && (bits16 + 1 == nchannels) && (rfreq == freq)) | |
184 | - return; | |
214 | + oss.bytes_per_second = (freq << (nchannels >> 1)) << oss.bits16; | |
215 | + | |
216 | + linfo ("bytes per second %d\n", oss.bytes_per_second); | |
217 | + | |
218 | + linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n", | |
219 | + abinfo.fragments, | |
220 | + abinfo.fragstotal, | |
221 | + abinfo.fragsize, | |
222 | + abinfo.bytes, | |
223 | + oss.bufsize); | |
224 | + | |
225 | + oss.buf = MAP_FAILED; | |
226 | + oss.is_mapped = 0; | |
227 | + | |
228 | + if (conf.try_mmap) { | |
229 | + oss.buf = mmap (NULL, oss.bufsize, PROT_WRITE, MAP_SHARED, oss.fd, 0); | |
230 | + if (MAP_FAILED == oss.buf) { | |
231 | + int err; | |
232 | + | |
233 | + err = errno; | |
234 | + log ("failed to mmap audio, size %d, fd %d\n" | |
235 | + "syserr: %s\n", | |
236 | + oss.bufsize, oss.fd, strerror (err)); | |
237 | + } | |
185 | 238 | else { |
186 | - AUD_open (rfreq, rnchannels, rfmt); | |
239 | + est = TID; | |
240 | + oss.is_mapped = 1; | |
241 | + } | |
242 | + } | |
243 | + | |
244 | + if (MAP_FAILED == oss.buf) { | |
245 | + est = TID; | |
246 | + oss.buf = mmap (NULL, oss.bufsize, PROT_READ | PROT_WRITE, | |
247 | + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | |
248 | + if (MAP_FAILED == oss.buf) { | |
249 | + ERRFail ("mmap audio buf, size %d", oss.bufsize); | |
250 | + } | |
251 | + } | |
252 | + | |
253 | + oss.rpos = 0; | |
254 | + oss.wpos = 0; | |
255 | + oss.live = 0; | |
256 | + | |
257 | + if (oss.is_mapped) { | |
258 | + int trig; | |
259 | + | |
260 | + trig = 0; | |
261 | + IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig)); | |
262 | + trig = PCM_ENABLE_OUTPUT; | |
263 | + IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig)); | |
187 | 264 | } |
188 | 265 | } |
189 | 266 | |
190 | -void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt) | |
267 | +static void maybe_open (int req_freq, int req_nchannels, | |
268 | + audfmt_e req_fmt, int force_open) | |
191 | 269 | { |
192 | - int fmt_; | |
193 | - int mmmmssss; | |
194 | - struct audio_buf_info abinfo; | |
195 | - int _fmt; | |
196 | - int _freq; | |
197 | - int _nchannels; | |
198 | - int bits16; | |
270 | + int oss_fmt, bits16; | |
199 | 271 | |
200 | - bits16 = 0; | |
201 | - | |
202 | - switch (rfmt) { | |
272 | + switch (req_fmt) { | |
203 | 273 | case AUD_FMT_U8: |
204 | 274 | bits16 = 0; |
205 | - fmt_ = AFMT_U8; | |
206 | - copy_fn = copy_no_conversion; | |
207 | - atom = 1; | |
275 | + oss_fmt = AFMT_U8; | |
276 | + oss.copy_fn = copy_no_conversion; | |
208 | 277 | break; |
209 | 278 | |
210 | 279 | case AUD_FMT_S8: |
... | ... | @@ -212,111 +281,42 @@ void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt) |
212 | 281 | |
213 | 282 | case AUD_FMT_S16: |
214 | 283 | bits16 = 1; |
215 | - fmt_ = AFMT_S16_LE; | |
216 | - copy_fn = copy_no_conversion; | |
217 | - atom = 2; | |
284 | + oss_fmt = AFMT_S16_LE; | |
285 | + oss.copy_fn = copy_no_conversion; | |
218 | 286 | break; |
219 | 287 | |
220 | 288 | case AUD_FMT_U16: |
221 | 289 | bits16 = 1; |
222 | - fmt_ = AFMT_S16_LE; | |
223 | - copy_fn = copy_u16_to_s16; | |
224 | - atom = 2; | |
290 | + oss_fmt = AFMT_S16_LE; | |
291 | + oss.copy_fn = copy_u16_to_s16; | |
225 | 292 | break; |
226 | 293 | |
227 | 294 | default: |
228 | 295 | abort (); |
229 | 296 | } |
230 | 297 | |
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); | |
298 | + if (force_open | |
299 | + || (-1 == oss.fd) | |
300 | + || (oss_fmt != oss.oss_fmt) | |
301 | + || (req_nchannels != oss.nchannels) | |
302 | + || (req_freq != oss.freq) | |
303 | + || (bits16 != oss.bits16)) { | |
304 | + oss.oss_fmt = oss_fmt; | |
305 | + oss.nchannels = req_nchannels; | |
306 | + oss.freq = req_freq; | |
307 | + oss.bits16 = bits16; | |
308 | + do_open (); | |
283 | 309 | } |
310 | +} | |
284 | 311 | |
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 | - } | |
312 | +void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt) | |
313 | +{ | |
314 | + maybe_open (req_freq, req_nchannels, req_fmt, 0); | |
315 | +} | |
316 | 316 | |
317 | - rpos = 0; | |
318 | - wpos = 0; | |
319 | - live = 0; | |
317 | +void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt) | |
318 | +{ | |
319 | + maybe_open (req_freq, req_nchannels, req_fmt, 1); | |
320 | 320 | } |
321 | 321 | |
322 | 322 | int AUD_write (void *in_buf, int size) |
... | ... | @@ -324,27 +324,27 @@ int AUD_write (void *in_buf, int size) |
324 | 324 | int to_copy, temp; |
325 | 325 | uint8_t *in, *out; |
326 | 326 | |
327 | - to_copy = MIN (bufsize - live, size); | |
327 | + to_copy = MIN (oss.bufsize - oss.live, size); | |
328 | 328 | |
329 | 329 | temp = to_copy; |
330 | 330 | |
331 | 331 | in = in_buf; |
332 | - out = buf; | |
332 | + out = oss.buf; | |
333 | 333 | |
334 | 334 | while (temp) { |
335 | 335 | int copy; |
336 | 336 | |
337 | - copy = MIN (temp, bufsize - wpos); | |
338 | - copy_fn (out + wpos, in, copy); | |
337 | + copy = MIN (temp, oss.bufsize - oss.wpos); | |
338 | + oss.copy_fn (out + oss.wpos, in, copy); | |
339 | 339 | |
340 | - wpos += copy; | |
341 | - if (wpos == bufsize) { | |
342 | - wpos = 0; | |
340 | + oss.wpos += copy; | |
341 | + if (oss.wpos == oss.bufsize) { | |
342 | + oss.wpos = 0; | |
343 | 343 | } |
344 | 344 | |
345 | 345 | temp -= copy; |
346 | 346 | in += copy; |
347 | - live += copy; | |
347 | + oss.live += copy; | |
348 | 348 | } |
349 | 349 | |
350 | 350 | return to_copy; |
... | ... | @@ -356,10 +356,34 @@ void AUD_run (void) |
356 | 356 | int bytes; |
357 | 357 | struct audio_buf_info abinfo; |
358 | 358 | |
359 | - if (0 == live) | |
359 | + if (0 == oss.live) | |
360 | 360 | return; |
361 | 361 | |
362 | - res = ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo); | |
362 | + if (oss.is_mapped) { | |
363 | + count_info info; | |
364 | + | |
365 | + res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info); | |
366 | + if (-1 == res) { | |
367 | + int err; | |
368 | + | |
369 | + err = errno; | |
370 | + lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err)); | |
371 | + return; | |
372 | + } | |
373 | + | |
374 | + if (info.ptr > oss.old_optr) { | |
375 | + bytes = info.ptr - oss.old_optr; | |
376 | + } | |
377 | + else { | |
378 | + bytes = oss.bufsize + info.ptr - oss.old_optr; | |
379 | + } | |
380 | + | |
381 | + oss.old_optr = info.ptr; | |
382 | + oss.live -= bytes; | |
383 | + return; | |
384 | + } | |
385 | + | |
386 | + res = ioctl (oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo); | |
363 | 387 | |
364 | 388 | if (-1 == res) { |
365 | 389 | int err; |
... | ... | @@ -369,7 +393,7 @@ void AUD_run (void) |
369 | 393 | } |
370 | 394 | |
371 | 395 | bytes = abinfo.bytes; |
372 | - bytes = MIN (live, bytes); | |
396 | + bytes = MIN (oss.live, bytes); | |
373 | 397 | #if 0 |
374 | 398 | bytes = (bytes / fragsize) * fragsize; |
375 | 399 | #endif |
... | ... | @@ -377,9 +401,9 @@ void AUD_run (void) |
377 | 401 | while (bytes) { |
378 | 402 | int left, play, written; |
379 | 403 | |
380 | - left = bufsize - rpos; | |
404 | + left = oss.bufsize - oss.rpos; | |
381 | 405 | play = MIN (left, bytes); |
382 | - written = write (audio_fd, (void *) ((uint32_t) buf + rpos), play); | |
406 | + written = write (oss.fd, (void *) ((uint32_t) oss.buf + oss.rpos), play); | |
383 | 407 | |
384 | 408 | if (-1 == written) { |
385 | 409 | if (EAGAIN == errno || EINTR == errno) { |
... | ... | @@ -391,12 +415,12 @@ void AUD_run (void) |
391 | 415 | } |
392 | 416 | |
393 | 417 | play = written; |
394 | - live -= play; | |
395 | - rpos += play; | |
418 | + oss.live -= play; | |
419 | + oss.rpos += play; | |
396 | 420 | bytes -= play; |
397 | 421 | |
398 | - if (rpos == bufsize) { | |
399 | - rpos = 0; | |
422 | + if (oss.rpos == oss.bufsize) { | |
423 | + oss.rpos = 0; | |
400 | 424 | } |
401 | 425 | } |
402 | 426 | } |
... | ... | @@ -406,7 +430,7 @@ static int get_dsp_bytes (void) |
406 | 430 | int res; |
407 | 431 | struct count_info info; |
408 | 432 | |
409 | - res = ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &info); | |
433 | + res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info); | |
410 | 434 | if (-1 == res) { |
411 | 435 | int err; |
412 | 436 | |
... | ... | @@ -420,22 +444,22 @@ static int get_dsp_bytes (void) |
420 | 444 | } |
421 | 445 | } |
422 | 446 | |
423 | -void AUD_adjust_estimate (int _leftover) | |
447 | +void AUD_adjust_estimate (int leftover) | |
424 | 448 | { |
425 | - leftover = _leftover; | |
449 | + oss.leftover = leftover; | |
426 | 450 | } |
427 | 451 | |
428 | 452 | int AUD_get_free (void) |
429 | 453 | { |
430 | 454 | int free, elapsed; |
431 | 455 | |
432 | - free = bufsize - live; | |
456 | + free = oss.bufsize - oss.live; | |
433 | 457 | |
434 | 458 | if (0 == free) |
435 | 459 | return 0; |
436 | 460 | |
437 | 461 | elapsed = free; |
438 | - switch (estimate) { | |
462 | + switch (est) { | |
439 | 463 | case DONT: |
440 | 464 | break; |
441 | 465 | |
... | ... | @@ -456,16 +480,15 @@ int AUD_get_free (void) |
456 | 480 | |
457 | 481 | case TID: |
458 | 482 | { |
459 | - static uint64_t old_ticks; | |
460 | 483 | uint64_t ticks, delta; |
461 | 484 | uint64_t ua_elapsed; |
462 | 485 | uint64_t al_elapsed; |
463 | 486 | |
464 | 487 | ticks = qemu_get_clock(rt_clock); |
465 | - delta = ticks - old_ticks; | |
466 | - old_ticks = ticks; | |
488 | + delta = ticks - oss.old_ticks; | |
489 | + oss.old_ticks = ticks; | |
467 | 490 | |
468 | - ua_elapsed = (delta * bytes_per_second) / 1000; | |
491 | + ua_elapsed = (delta * oss.bytes_per_second) / 1000; | |
469 | 492 | al_elapsed = ua_elapsed & ~3ULL; |
470 | 493 | |
471 | 494 | ldebug ("tid elapsed %llu bytes\n", ua_elapsed); |
... | ... | @@ -475,7 +498,7 @@ int AUD_get_free (void) |
475 | 498 | else |
476 | 499 | elapsed = al_elapsed; |
477 | 500 | |
478 | - elapsed += leftover; | |
501 | + elapsed += oss.leftover; | |
479 | 502 | } |
480 | 503 | } |
481 | 504 | |
... | ... | @@ -490,27 +513,47 @@ int AUD_get_free (void) |
490 | 513 | |
491 | 514 | int AUD_get_live (void) |
492 | 515 | { |
493 | - return live; | |
516 | + return oss.live; | |
494 | 517 | } |
495 | 518 | |
496 | 519 | int AUD_get_buffer_size (void) |
497 | 520 | { |
498 | - return bufsize; | |
521 | + return oss.bufsize; | |
522 | +} | |
523 | + | |
524 | +#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE" | |
525 | +#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS" | |
526 | +#define QC_OSS_MMAP "QEMU_OSS_MMAP" | |
527 | + | |
528 | +static int get_conf_val (const char *key, int defval) | |
529 | +{ | |
530 | + int val = defval; | |
531 | + char *strval; | |
532 | + | |
533 | + strval = getenv (key); | |
534 | + if (strval) { | |
535 | + val = atoi (strval); | |
536 | + } | |
537 | + | |
538 | + return val; | |
499 | 539 | } |
500 | 540 | |
501 | 541 | void AUD_init (void) |
502 | 542 | { |
503 | 543 | int fsp; |
504 | - int _fragsize = 4096; | |
505 | 544 | |
506 | 545 | DEREF (pab); |
507 | 546 | |
508 | - fsp = _fragsize; | |
547 | + conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize); | |
548 | + conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags); | |
549 | + conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap); | |
550 | + | |
551 | + fsp = conf.fragsize; | |
509 | 552 | if (0 != (fsp & (fsp - 1))) { |
510 | 553 | Fail ("fragment size %d is not power of 2", fsp); |
511 | 554 | } |
512 | 555 | |
513 | - conf_fragsize = lsbindex (fsp); | |
556 | + conf.fragsize = lsbindex (fsp); | |
514 | 557 | } |
515 | 558 | |
516 | 559 | #else | ... | ... |