3 * Copyright 1998 Marcus Meissner
6 * Note: This file requires multithread ability. It is not possible to
7 * implement the stuff in a single thread anyway. And most DirectX apps
8 * require threading themselves.
10 * FIXME: This file is full of race conditions and unlocked variable access
11 * from two threads. But we usually don't need to bother.
13 * Tested with a Soundblaster clone and a Gravis UltraSound Classic.
16 * - Wing Commander 4/W95:
17 * The intromovie plays without problems. Nearly lipsynchron.
19 * The sound works, but noticeable chunks are left out (from the sound and
20 * the animation). Don't know why yet.
22 * Sound works, but slows down the movieplayer.
26 * The background sound of the startscreen works ;)
27 * - WingCommander Prophecy Demo:
28 * Sound works for the intromovie.
33 #include <sys/types.h>
35 #include <sys/fcntl.h>
41 #include "interfaces.h"
49 #include <sys/ioctl.h>
50 #include <sys/soundcard.h>
52 static int audiofd = -1;
53 static int current_buffered_frags = 4;
54 static LPDIRECTSOUND dsound = NULL;
56 static short playbuf[2048];
60 HRESULT WINAPI DirectSoundEnumerate32A(LPDSENUMCALLBACK32A enumcb,LPVOID context) {
62 enumcb(NULL,"WINE DirectSound using Open Sound System","sound",context);
68 static void _dump_DSBCAPS(DWORD xmask) {
73 #define FE(x) { x, #x },
74 FE(DSBCAPS_PRIMARYBUFFER)
76 FE(DSBCAPS_LOCHARDWARE)
77 FE(DSBCAPS_LOCSOFTWARE)
78 FE(DSBCAPS_CTRLFREQUENCY)
80 FE(DSBCAPS_CTRLVOLUME)
81 FE(DSBCAPS_CTRLDEFAULT)
83 FE(DSBCAPS_STICKYFOCUS)
84 FE(DSBCAPS_GETCURRENTPOSITION2)
88 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
89 if (flags[i].mask & xmask)
90 fprintf(stderr,"%s ",flags[i].name);
93 /*******************************************************************************
96 static HRESULT WINAPI IDirectSoundNotify_QueryInterface(
97 LPDIRECTSOUNDNOTIFY this,REFIID riid,LPVOID *ppobj
101 StringFromCLSID(riid,xbuf);
102 fprintf(stderr,"IDirectSound(%p)->QueryInterface(%s,%p)\n",this,xbuf,ppobj);
106 static ULONG WINAPI IDirectSoundNotify_AddRef(LPDIRECTSOUNDNOTIFY this) {
107 return ++(this->ref);
110 static ULONG WINAPI IDirectSoundNotify_Release(LPDIRECTSOUNDNOTIFY this) {
113 this->dsb->lpvtbl->fnRelease(this->dsb);
114 HeapFree(GetProcessHeap(),0,this);
120 static int _sort_notifies(const void *a,const void *b) {
121 LPDSBPOSITIONNOTIFY na = (LPDSBPOSITIONNOTIFY)a;
122 LPDSBPOSITIONNOTIFY nb = (LPDSBPOSITIONNOTIFY)b;
124 return na->dwOffset-nb->dwOffset;
127 static HRESULT WINAPI IDirectSoundNotify_SetNotificationPositions(
128 LPDIRECTSOUNDNOTIFY this,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
132 fprintf(stderr,"IDirectSoundNotify(%p)->SetNotificationPositions(0x%08lx,%p),stub!\n",this,howmuch,notify);
133 for (i=0;i<howmuch;i++)
134 fprintf(stderr," notify at %ld to 0x%08lx\n",notify[i].dwOffset,notify[i].hEventNotify);
135 this->dsb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,this->dsb->notifies,(this->dsb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY));
136 memcpy( this->dsb->notifies+this->dsb->nrofnotifies,
138 howmuch*sizeof(DSBPOSITIONNOTIFY)
140 this->dsb->nrofnotifies+=howmuch;
141 qsort(this->dsb->notifies,this->dsb->nrofnotifies,sizeof(DSBPOSITIONNOTIFY),_sort_notifies);
142 for (i=0;i<this->dsb->nrofnotifies;i++)
143 fprintf(stderr," notify at %ld to 0x%08lx\n",this->dsb->notifies[i].dwOffset,this->dsb->notifies[i].hEventNotify);
147 IDirectSoundNotify_VTable dsnvt = {
148 IDirectSoundNotify_QueryInterface,
149 IDirectSoundNotify_AddRef,
150 IDirectSoundNotify_Release,
151 IDirectSoundNotify_SetNotificationPositions,
154 /*******************************************************************************
157 static HRESULT WINAPI IDirectSoundBuffer_SetFormat(
158 LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX wfex
161 memcpy(&(this->wfx),wfex,sizeof(this->wfx));
162 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->SetFormat(%p),stub!\n",this,wfex);
163 dprintf_dsound(stderr," [formattag=0x%04x,",wfex->wFormatTag);
164 dprintf_dsound(stderr,"chans=%d,",wfex->nChannels);
165 dprintf_dsound(stderr,"samplerate=%ld,",wfex->nSamplesPerSec);
166 dprintf_dsound(stderr,"bytespersec=%ld,",wfex->nAvgBytesPerSec);
167 dprintf_dsound(stderr,"blockalign=%d,",wfex->nBlockAlign);
168 dprintf_dsound(stderr,"bitspersamp=%d,",wfex->wBitsPerSample);
169 dprintf_dsound(stderr,"cbSize=%d]\n",wfex->cbSize);
174 static HRESULT WINAPI IDirectSoundBuffer_SetVolume(
175 LPDIRECTSOUNDBUFFER this,LONG vol
177 fprintf(stderr,"IDirectSoundBuffer(%p)->SetVolume(%ld),stub!\n",this,vol);
182 static HRESULT WINAPI IDirectSoundBuffer_GetVolume(
183 LPDIRECTSOUNDBUFFER this,LPLONG vol
185 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->GetVolume(%p),stub!\n",this,vol);
190 static HRESULT WINAPI IDirectSoundBuffer_SetFrequency(
191 LPDIRECTSOUNDBUFFER this,DWORD freq
193 fprintf(stderr,"IDirectSoundBuffer(%p)->SetFrequency(%08lx),stub!\n",this,freq);
197 static HRESULT WINAPI IDirectSoundBuffer_Play(
198 LPDIRECTSOUNDBUFFER this,DWORD reserved1,DWORD reserved2,DWORD flags
200 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->Play(%08lx,%08lx,%08lx),stub!\n",
201 this,reserved1,reserved2,flags
204 this->playflags = flags;
209 static HRESULT WINAPI IDirectSoundBuffer_Stop(LPDIRECTSOUNDBUFFER this) {
210 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->Stop()\n",this);
212 this->writepos = 0; /* hmm */
216 static DWORD WINAPI IDirectSoundBuffer_AddRef(LPDIRECTSOUNDBUFFER this) {
217 return ++(this->ref);
219 static DWORD WINAPI IDirectSoundBuffer_Release(LPDIRECTSOUNDBUFFER this) {
224 for (i=0;i<this->dsound->nrofbuffers;i++)
225 if (this->dsound->buffers[i] == this)
227 if (i < this->dsound->nrofbuffers) {
229 this->dsound->buffers+i,
230 this->dsound->buffers+i+1,
231 sizeof(LPDIRECTSOUNDBUFFER)*(this->dsound->nrofbuffers-i-1)
233 this->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,this->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER)*this->dsound->nrofbuffers);
234 this->dsound->nrofbuffers--;
235 this->dsound->lpvtbl->fnRelease(this->dsound);
237 HeapFree(GetProcessHeap(),0,this);
241 static HRESULT WINAPI IDirectSoundBuffer_GetCurrentPosition(
242 LPDIRECTSOUNDBUFFER this,LPDWORD playpos,LPDWORD writepos
244 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->GetCurrentPosition(%p,%p),stub!\n",this,playpos,writepos);
245 if (playpos) *playpos = this->playpos;
246 if (writepos) *writepos = this->writepos;
250 static HRESULT WINAPI IDirectSoundBuffer_GetStatus(
251 LPDIRECTSOUNDBUFFER this,LPDWORD status
253 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->GetStatus(%p)\n",this,status);
256 *status |= DSBSTATUS_PLAYING;
257 if (this->playflags & DSBPLAY_LOOPING)
258 *status |= DSBSTATUS_LOOPING;
262 static HRESULT WINAPI IDirectSoundBuffer_GetFormat(
263 LPDIRECTSOUNDBUFFER this,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten
265 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->GetFormat(%p,%ld,%p)\n",this,lpwf,wfsize,wfwritten);
266 if (wfsize>sizeof(this->wfx)) wfsize = sizeof(this->wfx);
267 memcpy(lpwf,&(this->wfx),wfsize);
268 if (wfwritten) *wfwritten = wfsize;
272 static HRESULT WINAPI IDirectSoundBuffer_Lock(
273 LPDIRECTSOUNDBUFFER this,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
276 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->Lock(%ld,%ld,%p,%p,%p,%p,0x%08lx)\n",
286 if (flags & DSBLOCK_FROMWRITECURSOR)
287 writecursor = this->writepos;
288 assert(audiobytes1!=audiobytes2);
289 assert(lplpaudioptr1!=lplpaudioptr2);
290 if (writecursor+writebytes <= this->buflen) {
291 *(LPBYTE*)lplpaudioptr1 = this->buffer+writecursor;
292 *audiobytes1 = writebytes;
294 *(LPBYTE*)lplpaudioptr2 = NULL;
297 dprintf_dsound(stderr,"->%ld.0\n",writebytes);
299 *(LPBYTE*)lplpaudioptr1 = this->buffer+writecursor;
300 *audiobytes1 = this->buflen-writecursor;
302 *(LPBYTE*)lplpaudioptr2 = this->buffer;
304 *audiobytes2 = writebytes-(this->buflen-writecursor);
305 dprintf_dsound(stderr,"->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
307 this->writepos=(writecursor+writebytes)%this->buflen;
311 static HRESULT WINAPI IDirectSoundBuffer_SetCurrentPosition(
312 LPDIRECTSOUNDBUFFER this,DWORD newpos
314 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->SetCurrentPosition(%ld)\n",this,newpos);
315 this->playpos = newpos;
319 static HRESULT WINAPI IDirectSoundBuffer_SetPan(
320 LPDIRECTSOUNDBUFFER this,LONG newpan
322 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->SetPan(%ld),stub!\n",this,newpan);
327 static HRESULT WINAPI IDirectSoundBuffer_GetPan(
328 LPDIRECTSOUNDBUFFER this,LPLONG pan
330 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->GetPan(%p),stub!\n",this,pan);
335 static HRESULT WINAPI IDirectSoundBuffer_Unlock(
336 LPDIRECTSOUNDBUFFER this,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
338 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->Unlock(%p,%ld,%p,%ld)\n",
344 static HRESULT WINAPI IDirectSoundBuffer_GetFrequency(
345 LPDIRECTSOUNDBUFFER this,LPDWORD freq
347 dprintf_dsound(stderr,"IDirectSoundBuffer(%p)->GetFrequency(%p)\n",
350 *freq = this->wfx.nSamplesPerSec;
354 static HRESULT WINAPI IDirectSoundBuffer_Initialize(
355 LPDIRECTSOUNDBUFFER this,LPDIRECTSOUND dsound,LPDSBUFFERDESC dbsd
357 fprintf(stderr,"IDirectSoundBuffer(%p)->Initialize(%p,%p),stub!\n",this,dsound,dbsd);
358 return DSERR_ALREADYINITIALIZED;
361 static HRESULT WINAPI IDirectSoundBuffer_GetCaps(
362 LPDIRECTSOUNDBUFFER this,LPDSBCAPS caps
364 caps->dwSize = sizeof(*caps);
365 caps->dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_STATIC|DSBCAPS_CTRLALL|DSBCAPS_LOCSOFTWARE;
366 caps->dwBufferBytes = 0;
367 caps->dwUnlockTransferRate = 0;
368 caps->dwPlayCpuOverhead = 0;
372 static HRESULT WINAPI IDirectSoundBuffer_QueryInterface(
373 LPDIRECTSOUNDBUFFER this,REFIID riid,LPVOID *ppobj
377 if (!memcmp(&IID_IDirectSoundNotify,riid,sizeof(*riid))) {
378 IDirectSoundNotify *dsn;
380 dsn = (LPDIRECTSOUNDNOTIFY)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn));
383 this->lpvtbl->fnAddRef(this);
384 dsn->lpvtbl = &dsnvt;
385 *ppobj = (LPVOID)dsn;
388 StringFromCLSID(riid,xbuf);
389 fprintf(stderr,"IDirectSoundBuffer(%p)->QueryInterface(%s,%p)\n",this,xbuf,ppobj);
393 static struct tagLPDIRECTSOUNDBUFFER_VTABLE dsbvt = {
394 IDirectSoundBuffer_QueryInterface,
395 IDirectSoundBuffer_AddRef,
396 IDirectSoundBuffer_Release,
397 IDirectSoundBuffer_GetCaps,
398 IDirectSoundBuffer_GetCurrentPosition,
399 IDirectSoundBuffer_GetFormat,
400 IDirectSoundBuffer_GetVolume,
401 IDirectSoundBuffer_GetPan,
402 IDirectSoundBuffer_GetFrequency,
403 IDirectSoundBuffer_GetStatus,
404 IDirectSoundBuffer_Initialize,
405 IDirectSoundBuffer_Lock,
406 IDirectSoundBuffer_Play,
407 IDirectSoundBuffer_SetCurrentPosition,
408 IDirectSoundBuffer_SetFormat,
409 IDirectSoundBuffer_SetVolume,
410 IDirectSoundBuffer_SetPan,
411 IDirectSoundBuffer_SetFrequency,
412 IDirectSoundBuffer_Stop,
413 IDirectSoundBuffer_Unlock
416 /*******************************************************************************
420 static HRESULT WINAPI IDirectSound_SetCooperativeLevel(
421 LPDIRECTSOUND this,HWND32 hwnd,DWORD level
423 dprintf_dsound(stderr,"IDirectSound(%p)->SetCooperativeLevel(%08lx,%ld)\n",
424 this,(DWORD)hwnd,level
430 static HRESULT WINAPI IDirectSound_CreateSoundBuffer(
431 LPDIRECTSOUND this,LPDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER ppdsb,LPUNKNOWN lpunk
433 if (debugging_dsound) {
434 fprintf(stderr,"IDirectSound(%p)->CreateSoundBuffer(%p,%p,%p),stub!\n",this,dsbd,ppdsb,lpunk);
435 fprintf(stderr,"[size=%ld,",dsbd->dwSize);
436 fprintf(stderr,"flags = 0x%08lx,",dsbd->dwFlags);
437 _dump_DSBCAPS(dsbd->dwFlags);
438 fprintf(stderr,"bufferbytes = %ld,",dsbd->dwBufferBytes);
439 fprintf(stderr,"lpwfxFormat = %p]\n",dsbd->lpwfxFormat);
441 *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
443 (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsbd->dwBufferBytes);
444 (*ppdsb)->buflen = dsbd->dwBufferBytes;
445 (*ppdsb)->playpos = 0;
446 (*ppdsb)->writepos = 0;
447 (*ppdsb)->lpvtbl = &dsbvt;
448 (*ppdsb)->dsound = this;
449 (*ppdsb)->playing = 0;
450 memcpy(&((*ppdsb)->dsbd),dsbd,sizeof(*dsbd));
452 /* register buffer */
453 this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
454 this->buffers[this->nrofbuffers] = *ppdsb;
456 this->lpvtbl->fnAddRef(this);
458 if (dsbd->lpwfxFormat) dsbvt.fnSetFormat(*ppdsb,dsbd->lpwfxFormat);
462 static HRESULT WINAPI IDirectSound_DuplicateSoundBuffer(
463 LPDIRECTSOUND this,LPDIRECTSOUNDBUFFER pdsb,LPLPDIRECTSOUNDBUFFER ppdsb
465 fprintf(stderr,"IDirectSound(%p)->DuplicateSoundBuffer(%p,%p),stub!\n",this,pdsb,ppdsb);
467 *ppdsb = (LPDIRECTSOUNDBUFFER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundBuffer));
469 (*ppdsb)->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,pdsb->buflen);
470 memcpy((*ppdsb)->buffer,pdsb->buffer,pdsb->buflen);
471 (*ppdsb)->buflen = pdsb->buflen;
472 (*ppdsb)->playpos = 0;
473 (*ppdsb)->writepos = 0;
474 (*ppdsb)->lpvtbl = &dsbvt;
475 (*ppdsb)->dsound = this;
476 dsbvt.fnSetFormat(*ppdsb,&(pdsb->wfx));
477 /* register buffer */
478 this->buffers = (LPDIRECTSOUNDBUFFER*)HeapReAlloc(GetProcessHeap(),0,this->buffers,sizeof(LPDIRECTSOUNDBUFFER)*(this->nrofbuffers+1));
479 this->buffers[this->nrofbuffers] = *ppdsb;
481 this->lpvtbl->fnAddRef(this);
486 static HRESULT WINAPI IDirectSound_GetCaps(LPDIRECTSOUND this,LPDSCAPS caps) {
487 fprintf(stderr,"IDirectSound(%p)->GetCaps(%p),stub!\n",this,caps);
488 fprintf(stderr," flags = 0x%08lx\n",caps->dwFlags);
490 caps->dwSize = sizeof(*caps);
491 caps->dwFlags = DSCAPS_PRIMARYSTEREO|DSCAPS_PRIMARY16BIT|DSCAPS_EMULDRIVER|DSCAPS_SECONDARYSTEREO|DSCAPS_SECONDARY16BIT;
492 /* FIXME: query OSS */
493 caps->dwMinSecondarySampleRate = 22050;
494 caps->dwMaxSecondarySampleRate = 48000;
495 caps->dwPrimaryBuffers = 1;
496 /* FIXME: set the rest... hmm */
500 static ULONG WINAPI IDirectSound_AddRef(LPDIRECTSOUND this) {
501 return ++(this->ref);
504 static ULONG WINAPI IDirectSound_Release(LPDIRECTSOUND this) {
505 if (!--(this->ref)) {
506 HeapFree(GetProcessHeap(),0,this);
508 close(audiofd);audiofd = -1;
514 static HRESULT WINAPI IDirectSound_SetSpeakerConfig(
515 LPDIRECTSOUND this,DWORD config
517 fprintf(stderr,"IDirectSound(%p)->SetSpeakerConfig(0x%08lx)\n",this,config);
521 static HRESULT WINAPI IDirectSound_QueryInterface(
522 LPDIRECTSOUND this,REFIID riid,LPVOID *ppobj
526 StringFromCLSID(riid,xbuf);
527 fprintf(stderr,"IDirectSound(%p)->QueryInterface(%s,%p)\n",this,xbuf,ppobj);
531 static struct tagLPDIRECTSOUND_VTABLE dsvt = {
532 IDirectSound_QueryInterface,
534 IDirectSound_Release,
535 IDirectSound_CreateSoundBuffer,
536 IDirectSound_GetCaps,
537 IDirectSound_DuplicateSoundBuffer,
538 IDirectSound_SetCooperativeLevel,
541 IDirectSound_SetSpeakerConfig,
546 DSOUND_setformat(LPWAVEFORMATEX wfex) {
547 int xx,channels,speed,format,nformat;
549 switch (wfex->wFormatTag) {
551 fprintf(stderr,"unknown WAVE_FORMAT tag %d\n",wfex->wFormatTag);
552 return DSERR_BADFORMAT;
553 case WAVE_FORMAT_PCM:
554 format = AFMT_S16_LE;
557 if (-1==ioctl(audiofd,SNDCTL_DSP_GETFMTS,&xx)) {
558 perror("ioctl SNDCTL_DSP_GETFMTS");
561 if ((xx&format)!=format) {/* format unsupported */
562 fprintf(stderr,"SNDCTL_DSP_GETFMTS: format not supported\n");
566 if (-1==ioctl(audiofd,SNDCTL_DSP_SETFMT,&nformat)) {
567 perror("ioctl SNDCTL_DSP_SETFMT");
570 if (nformat!=format) {/* didn't work */
571 fprintf(stderr,"SNDCTL_DSP_GETFMTS: format not set\n");
575 channels = wfex->nChannels-1;
576 if (-1==ioctl(audiofd,SNDCTL_DSP_STEREO,&channels)) {
577 perror("ioctl SNDCTL_DSP_STEREO");
580 speed = wfex->nSamplesPerSec;
581 if (-1==ioctl(audiofd,SNDCTL_DSP_SPEED,&speed)) {
582 perror("ioctl SNDCTL_DSP_SPEED");
588 static LPDSBPOSITIONNOTIFY
589 DSOUND_nextevent(IDirectSoundBuffer *dsb) {
592 if (dsb->nrofnotifies) {
593 for (i=0;i<dsb->nrofnotifies;i++) {
594 if (dsb->playpos<dsb->notifies[i].dwOffset)
597 if (i==dsb->nrofnotifies)
599 return dsb->notifies+i;
604 #define CHECK_EVENT \
605 if (nextevent && (dsb->playpos == nextevent->dwOffset)) { \
606 SetEvent(nextevent->hEventNotify); \
607 fprintf(stderr,"signalled event %d\n",nextevent->hEventNotify);\
608 nextevent = DSOUND_nextevent(dsb); \
613 DSOUND_MixInBuffer(IDirectSoundBuffer *dsb) {
614 int i,j,buflen = dsb->buflen;
615 LPDSBPOSITIONNOTIFY nextevent;
617 if (dsb->wfx.nSamplesPerSec != dsound->wfx.nSamplesPerSec) {
618 fprintf(stderr,"mixing in buffer of different frequency, argh!\n");
620 nextevent = DSOUND_nextevent(dsb);
622 if (dsb->wfx.wBitsPerSample == 8) {
623 unsigned char *xbuf = (unsigned char*)(dsb->buffer);
624 if (dsb->wfx.nChannels == 1) {
625 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
626 dsb->playpos=(dsb->playpos+1)%buflen;
627 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
629 dsb->playpos = buflen;
632 /* FIXME: pan,volume */
633 playbuf[(j<<1) ]+=xbuf[dsb->playpos]<<8;
634 playbuf[(j<<1)+1]+=xbuf[dsb->playpos]<<8;
638 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0]);j++) {
639 dsb->playpos=(dsb->playpos+1)%buflen;
640 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
642 dsb->playpos = buflen;
645 /* FIXME: pan,volume */
646 playbuf[j]+=xbuf[dsb->playpos]<<8;
651 short *xbuf = (short*)(dsb->buffer);
652 if (dsb->wfx.nChannels == 1) {
653 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0])/2;j++) {
654 dsb->playpos=(dsb->playpos+2)%buflen;
655 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
657 dsb->playpos = buflen;
660 /* FIXME: pan,volume */
661 playbuf[(j<<1) ]+=xbuf[dsb->playpos>>1];
662 playbuf[(j<<1)+1]+=xbuf[dsb->playpos>>1];
666 for (j=0;j<sizeof(playbuf)/sizeof(playbuf[0]);j++) {
667 dsb->playpos=(dsb->playpos+2)%buflen;
668 if (!dsb->playpos && !(dsb->playflags&DSBPLAY_LOOPING)) {
670 dsb->playpos = buflen;
673 /* FIXME: pan,volume */
674 playbuf[j]+=xbuf[dsb->playpos>>1];
682 DSOUND_thread(LPVOID arg) {
683 int fragsdiff,res,i,curleft,playing;
684 struct audio_buf_info abi;
686 fprintf(stderr,"dsound is at pid %d\n",getpid());
687 ioctl(audiofd,SNDCTL_DSP_GETOSPACE,&abi);
688 fragsdiff = abi.fragstotal-abi.fragments;
691 fprintf(stderr,"DSOUND thread giving up.\n");
694 /* RACE: dsound could be deleted */
695 dsound->lpvtbl->fnAddRef(dsound);
696 if (!dsound->nrofbuffers) {
697 /* no soundbuffer yet... wait. */
701 memset(playbuf,0,sizeof(playbuf));
702 /* empty in memory soundbuffers */
704 ioctl(audiofd,SNDCTL_DSP_GETOSPACE,&abi);
705 if (abi.fragstotal-abi.fragments<=fragsdiff+current_buffered_frags)
710 dsound->lpvtbl->fnAddRef(dsound);
711 for (i=dsound->nrofbuffers;i--;) {
712 IDirectSoundBuffer *dsb = dsound->buffers[i];
714 dsb->lpvtbl->fnAddRef(dsb);
715 if (dsb->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) {
716 if (memcmp(&dsound->wfx,&(dsb->wfx),sizeof(dsound->wfx))) {
717 DSOUND_setformat(&(dsb->wfx));
718 memcpy(&dsound->wfx,&(dsb->wfx),sizeof(dsb->wfx));
721 dsb->lpvtbl->fnRelease(dsb);
723 for (i=dsound->nrofbuffers;i--;) {
724 IDirectSoundBuffer *dsb = dsound->buffers[i];
726 dsb->lpvtbl->fnAddRef(dsb);
727 if (dsb->buflen && dsb->playing) {
729 DSOUND_MixInBuffer(dsb);
731 dsb->lpvtbl->fnRelease(dsb);
733 dsound->lpvtbl->fnRelease(dsound);
735 /*fputc('0'+playing,stderr);*/
737 ioctl(audiofd,SNDCTL_DSP_GETOSPACE,&abi);
738 if ((abi.fragstotal-abi.fragments)<=1+fragsdiff) {
739 current_buffered_frags++;
740 } else if ((abi.fragstotal-abi.fragments)>2+fragsdiff) {
741 current_buffered_frags--;
743 while (curleft < sizeof(playbuf)) {
744 res = write(audiofd,(LPBYTE)playbuf+curleft,sizeof(playbuf)-curleft);
746 perror("write audiofd");
756 #endif /* HAVE_OSS */
758 HRESULT WINAPI DirectSoundCreate(LPGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pUnkOuter ) {
760 fprintf(stderr,"DirectSoundCreate(%p,%p,%p)\n",lpGUID,ppDS,pUnkOuter);
763 return DSERR_ALLOCATED;
764 audiofd = open("/dev/audio",O_WRONLY);
766 perror("open /dev/audio");
768 return DSERR_NODRIVER;
772 if (-1==ioctl(audiofd,SNDCTL_DSP_SETFRAGMENT,&xx))
773 perror("ioctl SETFRAGMENT");
776 *ppDS = (LPDIRECTSOUND)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSound));
778 (*ppDS)->lpvtbl = &dsvt;
779 (*ppDS)->buffers = NULL;
780 (*ppDS)->nrofbuffers = 0;
782 (*ppDS)->wfx.wFormatTag = 1;
783 (*ppDS)->wfx.nChannels = 2;
784 (*ppDS)->wfx.nSamplesPerSec = 22050;
785 (*ppDS)->wfx.nAvgBytesPerSec = 44100;
786 (*ppDS)->wfx.nBlockAlign = 2;
787 (*ppDS)->wfx.wBitsPerSample = 8;
789 DSOUND_setformat(&((*ppDS)->wfx));
796 hnd = CreateThread(NULL,NULL,DSOUND_thread,0,0,&xid);
800 MessageBox32A(0,"DirectSound needs the Open Sound System Driver, which has not been found by ./configure.","WINE DirectSound",MB_OK|MB_ICONSTOP);
801 return DSERR_NODRIVER;