HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) { TRACE("(%p)\n", device); /* **** */ EnterCriticalSection(&(device->mixlock)); DSOUND_PrimaryClose(device); HeapFree(GetProcessHeap(),0,device->pwfx); device->pwfx=NULL; LeaveCriticalSection(&(device->mixlock)); /* **** */ return DS_OK; }
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) { HRESULT err = DS_OK; TRACE("(%p)\n", device); if (device->hwbuf) { err = IDsDriverBuffer_Stop(device->hwbuf); if (err == DSERR_BUFFERLOST) { DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if (FAILED(err)) ERR("DSOUND_ReopenDevice failed\n"); else { err = DSOUND_PrimaryOpen(device); if (FAILED(err)) WARN("DSOUND_PrimaryOpen failed\n"); } } else if (err != DS_OK) { WARN("IDsDriverBuffer_Stop failed\n"); } } else { /* don't call the wave system with the lock set */ LeaveCriticalSection(&(device->mixlock)); /* **** */ err = mmErr(waveOutPause(device->hwo)); /* **** */ EnterCriticalSection(&(device->mixlock)); if (err != DS_OK) WARN("waveOutPause failed\n"); } return err; }
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) { TRACE("(%p)\n", device); /* **** */ EnterCriticalSection(&(device->mixlock)); DSOUND_PrimaryClose(device); if (device->driver) { if (device->hwbuf) { if (IDsDriverBuffer_Release(device->hwbuf) == 0) device->hwbuf = 0; } } else HeapFree(GetProcessHeap(),0,device->pwave); HeapFree(GetProcessHeap(),0,device->pwfx); device->pwfx=NULL; LeaveCriticalSection(&(device->mixlock)); /* **** */ return DS_OK; }
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) { TRACE("(%p)\n", device); /* **** */ EnterCriticalSection(&(device->mixlock)); DSOUND_PrimaryClose(device); if(device->primary && (device->primary->ref || device->primary->numIfaces)) WARN("Destroying primary buffer while references held (%u %u)\n", device->primary->ref, device->primary->numIfaces); HeapFree(GetProcessHeap(), 0, device->primary); device->primary = NULL; HeapFree(GetProcessHeap(),0,device->primary_pwfx); HeapFree(GetProcessHeap(),0,device->pwfx); device->pwfx=NULL; LeaveCriticalSection(&(device->mixlock)); /* **** */ return DS_OK; }
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) { HRESULT err = DSERR_BUFFERLOST; int i; WAVEFORMATEX *old_fmt; WAVEFORMATEXTENSIBLE *fmtex; BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY); TRACE("(%p,%p)\n", device, passed_fmt); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (passed_fmt == NULL) { WARN("invalid parameter: passed_fmt==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec, passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign, passed_fmt->wBitsPerSample, passed_fmt->cbSize); /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); old_fmt = device->pwfx; device->pwfx = DSOUND_CopyFormat(passed_fmt); fmtex = (WAVEFORMATEXTENSIBLE *)device->pwfx; if (device->pwfx == NULL) { device->pwfx = old_fmt; old_fmt = NULL; err = DSERR_OUTOFMEMORY; goto done; } DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; /* requested format failed, so try others */ if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT){ device->pwfx->wFormatTag = WAVE_FORMAT_PCM; device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; } if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE && IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)){ fmtex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; } device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 16; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 8; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->nChannels = (passed_fmt->nChannels == 2) ? 1 : 2; device->pwfx->wBitsPerSample = passed_fmt->wBitsPerSample; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 16; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 8; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; WARN("No formats could be opened\n"); goto done; opened: err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } if (passed_fmt->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) { DSOUND_PrimaryClose(device); device->pwfx->nSamplesPerSec = passed_fmt->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); FillMemory(device->mix_buffer, device->mix_buffer_len, 0); device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; if (old_fmt->nSamplesPerSec != device->pwfx->nSamplesPerSec || old_fmt->wBitsPerSample != device->pwfx->wBitsPerSample || old_fmt->nChannels != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; DSOUND_RecalcFormat((*dsb)); DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); (*dsb)->primary_mixpos = 0; RtlReleaseResource(&(*dsb)->lock); /* **** */ } } done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ HeapFree(GetProcessHeap(), 0, old_fmt); return err; }
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) { HRESULT err = S_OK; WAVEFORMATEX *old_fmt; WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt; BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY); TRACE("(%p,%p)\n", device, passed_fmt); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (passed_fmt == NULL) { WARN("invalid parameter: passed_fmt==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec, passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign, passed_fmt->wBitsPerSample, passed_fmt->cbSize); if(passed_fmt->wBitsPerSample < 8 || passed_fmt->wBitsPerSample % 8 != 0 || passed_fmt->nChannels == 0 || passed_fmt->nSamplesPerSec == 0 || passed_fmt->nAvgBytesPerSec == 0 || passed_fmt->nBlockAlign != passed_fmt->nChannels * passed_fmt->wBitsPerSample / 8) return DSERR_INVALIDPARAM; if(passed_fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ if(passed_fmtex->Samples.wValidBitsPerSample > passed_fmtex->Format.wBitsPerSample) return DSERR_INVALIDPARAM; } /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); if (device->priolevel == DSSCL_WRITEPRIMARY) { old_fmt = device->primary_pwfx; device->primary_pwfx = DSOUND_CopyFormat(passed_fmt); fmtex = (WAVEFORMATEXTENSIBLE *)device->primary_pwfx; if (device->primary_pwfx == NULL) { err = DSERR_OUTOFMEMORY; goto out; } if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmtex->Samples.wValidBitsPerSample == 0) { TRACE("Correcting 0 valid bits per sample\n"); fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample; } DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, forced); if (FAILED(err)) { ERR("No formats could be opened\n"); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { ERR("DSOUND_PrimaryOpen failed\n"); goto done; } done: if (err != DS_OK) device->primary_pwfx = old_fmt; else HeapFree(GetProcessHeap(), 0, old_fmt); } else { HeapFree(GetProcessHeap(), 0, device->primary_pwfx); device->primary_pwfx = DSOUND_CopyFormat(passed_fmt); } out: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ return err; }
static HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced) { HRESULT err = DSERR_BUFFERLOST; int i; DWORD nSamplesPerSec, bpp, chans; LPWAVEFORMATEX oldpwfx; TRACE("(%p,%p)\n", device, wfex); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (wfex == NULL) { WARN("invalid parameter: wfex==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize); /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); nSamplesPerSec = device->pwfx->nSamplesPerSec; bpp = device->pwfx->wBitsPerSample; chans = device->pwfx->nChannels; oldpwfx = device->pwfx; device->pwfx = DSOUND_CopyFormat(wfex); if (device->pwfx == NULL) { device->pwfx = oldpwfx; oldpwfx = NULL; err = DSERR_OUTOFMEMORY; goto done; } if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) { err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx); /* On bad format, try to re-create, big chance it will work then, only do this if we <HAVE> to */ if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT)) { DWORD cp_size = wfex->wFormatTag == WAVE_FORMAT_PCM ? sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + wfex->cbSize; err = DSERR_BUFFERLOST; CopyMemory(device->pwfx, wfex, cp_size); } if (err != DSERR_BUFFERLOST && FAILED(err)) { DWORD size = DSOUND_GetFormatSize(oldpwfx); WARN("IDsDriverBuffer_SetFormat failed\n"); if (!forced) { CopyMemory(device->pwfx, oldpwfx, size); err = DS_OK; } goto done; } if (err == S_FALSE) { /* ALSA specific: S_FALSE tells that recreation was successful, * but size and location may be changed, and buffer has to be restarted * I put it here, so if frequency doesn't match the error will be changed to DSERR_BUFFERLOST * and the entire re-initialization will occur anyway */ IDsDriverBuffer_Lock(device->hwbuf, (LPVOID *)&device->buffer, &device->buflen, NULL, NULL, 0, 0, DSBLOCK_ENTIREBUFFER); IDsDriverBuffer_Unlock(device->hwbuf, device->buffer, 0, NULL, 0); if (device->state == STATE_PLAYING) device->state = STATE_STARTING; else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0; err = DS_OK; } DSOUND_RecalcPrimary(device); } if (err == DSERR_BUFFERLOST) { DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if (FAILED(err)) { WARN("DSOUND_ReopenDevice failed: %08x\n", err); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) { DSOUND_PrimaryClose(device); device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } } device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); FillMemory(device->mix_buffer, device->mix_buffer_len, 0); device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; DSOUND_RecalcFormat((*dsb)); DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); (*dsb)->primary_mixpos = 0; RtlReleaseResource(&(*dsb)->lock); /* **** */ } } done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ HeapFree(GetProcessHeap(), 0, oldpwfx); return err; }
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) { HRESULT err = DSERR_BUFFERLOST; int i; DWORD nSamplesPerSec, bpp, chans; LPWAVEFORMATEX oldpwfx; BOOL forced = device->priolevel == DSSCL_WRITEPRIMARY; TRACE("(%p,%p)\n", device, wfex); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (wfex == NULL) { WARN("invalid parameter: wfex==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize); /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); nSamplesPerSec = device->pwfx->nSamplesPerSec; bpp = device->pwfx->wBitsPerSample; chans = device->pwfx->nChannels; oldpwfx = device->pwfx; device->pwfx = DSOUND_CopyFormat(wfex); if (device->pwfx == NULL) { device->pwfx = oldpwfx; oldpwfx = NULL; err = DSERR_OUTOFMEMORY; goto done; } DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if (FAILED(err)) { WARN("DSOUND_ReopenDevice failed: %08x\n", err); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) { DSOUND_PrimaryClose(device); device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); FillMemory(device->mix_buffer, device->mix_buffer_len, 0); device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; DSOUND_RecalcFormat((*dsb)); DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); (*dsb)->primary_mixpos = 0; RtlReleaseResource(&(*dsb)->lock); /* **** */ } } done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ HeapFree(GetProcessHeap(), 0, oldpwfx); return err; }