📄 primary.c
字号:
device->pwfx = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,device->pwfx,alloc_size); nSamplesPerSec = device->pwfx->nSamplesPerSec; CopyMemory(device->pwfx, wfex, cp_size); if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) { DWORD flags = CALLBACK_FUNCTION; if (ds_hw_accel != DS_HW_ACCEL_EMULATION) flags |= WAVE_DIRECTSOUND; /* FIXME: check for errors */ DSOUND_PrimaryClose(device); waveOutClose(device->hwo); device->hwo = 0; err = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD)device, flags)); if (err == DS_OK) { err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } } else { WARN("waveOutOpen failed\n"); goto done; } } else if (device->hwbuf) { err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx); if (err == DSERR_BUFFERLOST) { /* Wine-only: the driver wants us to recreate the HW buffer */ IDsDriverBuffer_Release(device->hwbuf); err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx, DSBCAPS_PRIMARYBUFFER,0, &(device->buflen),&(device->buffer), (LPVOID)&(device->hwbuf)); if (err != DS_OK) { WARN("IDsDriver_CreateSoundBuffer failed\n"); goto done; } if (device->state == STATE_PLAYING) device->state = STATE_STARTING; else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; } else { WARN("IDsDriverBuffer_SetFormat failed\n"); goto done; } /* FIXME: should we set err back to DS_OK in all cases ? */ } DSOUND_RecalcPrimary(device); if (nSamplesPerSec != device->pwfx->nSamplesPerSec) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ EnterCriticalSection(&((*dsb)->lock)); (*dsb)->freqAdjust = ((*dsb)->freq << DSOUND_FREQSHIFT) / wfex->nSamplesPerSec; LeaveCriticalSection(&((*dsb)->lock)); /* **** */ } }done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ return err;}static HRESULT WINAPI PrimaryBufferImpl_SetVolume( LPDIRECTSOUNDBUFFER8 iface,LONG vol) { DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; DWORD ampfactors; DSVOLUMEPAN volpan; HRESULT hres = DS_OK; TRACE("(%p,%ld)\n", iface, vol); if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL; } if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) { WARN("invalid parameter: vol = %ld\n", vol); return DSERR_INVALIDPARAM; } /* **** */ EnterCriticalSection(&(device->mixlock)); waveOutGetVolume(device->hwo, &factors); volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; volpan.dwTotalRightAmpFactor=ampfactors >> 16; DSOUND_AmpFactorToVolPan(&volpan); if (vol != volpan.lVolume) { volpan.lVolume=vol; DSOUND_RecalcVolPan(&volpan); if (device->hwbuf) { hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &volpan); if (hres != DS_OK) WARN("IDsDriverBuffer_SetVolumePan failed\n"); } else { ampfactors = (volpan.dwTotalLeftAmpFactor & 0xffff) | (volpan.dwTotalRightAmpFactor << 16); waveOutSetVolume(device->hwo, ampfactors); } } LeaveCriticalSection(&(device->mixlock)); /* **** */ return hres;}static HRESULT WINAPI PrimaryBufferImpl_GetVolume( LPDIRECTSOUNDBUFFER8 iface,LPLONG vol) { DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; DWORD ampfactors; DSVOLUMEPAN volpan; TRACE("(%p,%p)\n", iface, vol); if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL; } if (vol == NULL) { WARN("invalid parameter: vol = NULL\n"); return DSERR_INVALIDPARAM; } waveOutGetVolume(device->hwo, &factors); volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; volpan.dwTotalRightAmpFactor=ampfactors >> 16; DSOUND_AmpFactorToVolPan(&volpan); *vol = volpan.lVolume; return DS_OK;}static HRESULT WINAPI PrimaryBufferImpl_SetFrequency( LPDIRECTSOUNDBUFFER8 iface,DWORD freq) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; TRACE("(%p,%ld)\n",This,freq); /* You cannot set the frequency of the primary buffer */ WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL;}static HRESULT WINAPI PrimaryBufferImpl_Play( LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags) { DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; TRACE("(%p,%08lx,%08lx,%08lx)\n", iface, reserved1, reserved2, flags); if (!(flags & DSBPLAY_LOOPING)) { WARN("invalid parameter: flags = %08lx\n", flags); return DSERR_INVALIDPARAM; } /* **** */ EnterCriticalSection(&(device->mixlock)); if (device->state == STATE_STOPPED) device->state = STATE_STARTING; else if (device->state == STATE_STOPPING) device->state = STATE_PLAYING; LeaveCriticalSection(&(device->mixlock)); /* **** */ return DS_OK;}static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface){ DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; TRACE("(%p)\n", iface); /* **** */ EnterCriticalSection(&(device->mixlock)); if (device->state == STATE_PLAYING) device->state = STATE_STOPPING; else if (device->state == STATE_STARTING) device->state = STATE_STOPPED; LeaveCriticalSection(&(device->mixlock)); /* **** */ return DS_OK;}static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface){ PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); TRACE("(%p) ref was %ld\n", This, ref - 1); return ref;}static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface){ PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; DWORD ref = InterlockedDecrement(&(This->ref)); TRACE("(%p) ref was %ld\n", This, ref + 1); if (!ref) { This->dsound->device->primary = NULL; HeapFree(GetProcessHeap(), 0, This); TRACE("(%p) released\n", This); } return ref;}static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition( LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos) { HRESULT hres; DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; TRACE("(%p,%p,%p)\n", iface, playpos, writepos); hres = DSOUND_PrimaryGetPosition(device, playpos, writepos); if (hres != DS_OK) { WARN("DSOUND_PrimaryGetPosition failed\n"); return hres; } if (writepos) { if (device->state != STATE_STOPPED) /* apply the documented 10ms lead to writepos */ *writepos += device->writelead; while (*writepos >= device->buflen) *writepos -= device->buflen; } TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount()); return DS_OK;}static HRESULT WINAPI PrimaryBufferImpl_GetStatus( LPDIRECTSOUNDBUFFER8 iface,LPDWORD status) { DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; TRACE("(%p,%p)\n", iface, status); if (status == NULL) { WARN("invalid parameter: status == NULL\n"); return DSERR_INVALIDPARAM; } *status = 0; if ((device->state == STATE_STARTING) || (device->state == STATE_PLAYING)) *status |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING; TRACE("status=%lx\n", *status); return DS_OK;}static HRESULT WINAPI PrimaryBufferImpl_GetFormat( LPDIRECTSOUNDBUFFER8 iface, LPWAVEFORMATEX lpwf, DWORD wfsize, LPDWORD wfwritten){ DWORD size; DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; TRACE("(%p,%p,%ld,%p)\n", iface, lpwf, wfsize, wfwritten); size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize; if (lpwf) { /* NULL is valid */ if (wfsize >= size) { CopyMemory(lpwf,device->pwfx,size); if (wfwritten) *wfwritten = size; } else { WARN("invalid parameter: wfsize too small\n"); if (wfwritten) *wfwritten = 0; return DSERR_INVALIDPARAM; } } else { if (wfwritten) *wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize; else { WARN("invalid parameter: wfwritten == NULL\n"); return DSERR_INVALIDPARAM; } } return DS_OK;}static HRESULT WINAPI PrimaryBufferImpl_Lock( LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags) { DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n", iface, writecursor, writebytes, lplpaudioptr1, audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount() ); if (device->priolevel != DSSCL_WRITEPRIMARY) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } if (flags & DSBLOCK_FROMWRITECURSOR) { DWORD writepos; HRESULT hres; /* GetCurrentPosition does too much magic to duplicate here */ hres = IDirectSoundBuffer_GetCurrentPosition(iface, NULL, &writepos); if (hres != DS_OK) { WARN("IDirectSoundBuffer_GetCurrentPosition failed\n"); return hres; } writecursor += writepos; } while (writecursor >= device->buflen) writecursor -= device->buflen; if (flags & DSBLOCK_ENTIREBUFFER) writebytes = device->buflen; if (writebytes > device->buflen) writebytes = device->buflen; if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) { HRESULT hres; hres = IDsDriverBuffer_Lock(device->hwbuf, lplpaudioptr1, audiobytes1, lplpaudioptr2, audiobytes2, writecursor, writebytes, 0); if (hres != DS_OK) { WARN("IDsDriverBuffer_Lock failed\n"); return hres; } } else { if (writecursor+writebytes <= device->buflen) { *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor; *audiobytes1 = writebytes; if (lplpaudioptr2) *(LPBYTE*)lplpaudioptr2 = NULL; if (audiobytes2) *audiobytes2 = 0; TRACE("->%ld.0\n",writebytes);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -