mirror of
https://github.com/reactos/wine.git
synced 2024-12-02 16:57:26 +00:00
dsound: Prevent reopening device from leaving dsound object in invalid state.
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
474033a4b8
commit
2fb97be187
@ -161,24 +161,20 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
|
||||
device->guid = GUID_NULL;
|
||||
|
||||
/* Set default wave format (may need it for waveOutOpen) */
|
||||
device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
|
||||
device->primary_pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
|
||||
if (!device->pwfx || !device->primary_pwfx) {
|
||||
if (!device->primary_pwfx) {
|
||||
WARN("out of memory\n");
|
||||
HeapFree(GetProcessHeap(),0,device->primary_pwfx);
|
||||
HeapFree(GetProcessHeap(),0,device->pwfx);
|
||||
HeapFree(GetProcessHeap(),0,device);
|
||||
return DSERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
|
||||
device->pwfx->nSamplesPerSec = 22050;
|
||||
device->pwfx->wBitsPerSample = 8;
|
||||
device->pwfx->nChannels = 2;
|
||||
device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
|
||||
device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
|
||||
device->pwfx->cbSize = 0;
|
||||
memcpy(device->primary_pwfx, device->pwfx, sizeof(*device->pwfx));
|
||||
device->primary_pwfx->wFormatTag = WAVE_FORMAT_PCM;
|
||||
device->primary_pwfx->nSamplesPerSec = 22050;
|
||||
device->primary_pwfx->wBitsPerSample = 8;
|
||||
device->primary_pwfx->nChannels = 2;
|
||||
device->primary_pwfx->nBlockAlign = device->primary_pwfx->wBitsPerSample * device->primary_pwfx->nChannels / 8;
|
||||
device->primary_pwfx->nAvgBytesPerSec = device->primary_pwfx->nSamplesPerSec * device->primary_pwfx->nBlockAlign;
|
||||
device->primary_pwfx->cbSize = 0;
|
||||
|
||||
InitializeCriticalSection(&(device->mixlock));
|
||||
device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
|
||||
@ -228,12 +224,12 @@ static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
|
||||
if (hr != DS_OK)
|
||||
WARN("DSOUND_PrimaryDestroy failed\n");
|
||||
|
||||
if(device->client)
|
||||
if(device->client) {
|
||||
IAudioClient_Stop(device->client);
|
||||
IAudioClient_Release(device->client);
|
||||
}
|
||||
if(device->render)
|
||||
IAudioRenderClient_Release(device->render);
|
||||
if(device->clock)
|
||||
IAudioClock_Release(device->clock);
|
||||
if(device->volume)
|
||||
IAudioStreamVolume_Release(device->volume);
|
||||
|
||||
@ -323,6 +319,7 @@ static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGU
|
||||
device->mmdevice = mmdevice;
|
||||
device->guid = devGUID;
|
||||
device->sleepev = CreateEventW(0, 0, 0, 0);
|
||||
device->buflen = ds_hel_buflen;
|
||||
|
||||
hr = DSOUND_ReopenDevice(device, FALSE);
|
||||
if (FAILED(hr))
|
||||
@ -381,13 +378,9 @@ static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGU
|
||||
|
||||
ZeroMemory(&device->volpan, sizeof(device->volpan));
|
||||
|
||||
hr = DSOUND_PrimaryCreate(device);
|
||||
if (hr == DS_OK) {
|
||||
device->thread_finished = CreateEventW(0, 0, 0, 0);
|
||||
device->thread = CreateThread(0, 0, DSOUND_mixthread, device, 0, 0);
|
||||
SetThreadPriority(device->thread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
} else
|
||||
WARN("DSOUND_PrimaryCreate failed: %08x\n", hr);
|
||||
device->thread_finished = CreateEventW(0, 0, 0, 0);
|
||||
device->thread = CreateThread(0, 0, DSOUND_mixthread, device, 0, 0);
|
||||
SetThreadPriority(device->thread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
||||
*ppDevice = device;
|
||||
list_add_tail(&DSOUND_renderers, &device->entry);
|
||||
@ -851,7 +844,6 @@ static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface
|
||||
{
|
||||
IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
|
||||
DirectSoundDevice *device = This->device;
|
||||
DWORD oldlevel;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
TRACE("(%p,%p,%s)\n", This, hwnd, dumpCooperativeLevel(level));
|
||||
@ -868,15 +860,10 @@ static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface
|
||||
|
||||
RtlAcquireResourceExclusive(&device->buffer_list_lock, TRUE);
|
||||
EnterCriticalSection(&device->mixlock);
|
||||
oldlevel = device->priolevel;
|
||||
device->priolevel = level;
|
||||
if ((level == DSSCL_WRITEPRIMARY) != (oldlevel == DSSCL_WRITEPRIMARY)) {
|
||||
if ((level == DSSCL_WRITEPRIMARY) != (device->priolevel == DSSCL_WRITEPRIMARY))
|
||||
hr = DSOUND_ReopenDevice(device, level == DSSCL_WRITEPRIMARY);
|
||||
if (FAILED(hr))
|
||||
device->priolevel = oldlevel;
|
||||
else
|
||||
DSOUND_PrimaryOpen(device);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
device->priolevel = level;
|
||||
LeaveCriticalSection(&device->mixlock);
|
||||
RtlReleaseResource(&device->buffer_list_lock);
|
||||
return hr;
|
||||
|
@ -100,7 +100,6 @@ struct DirectSoundDevice
|
||||
|
||||
IMMDevice *mmdevice;
|
||||
IAudioClient *client;
|
||||
IAudioClock *clock;
|
||||
IAudioStreamVolume *volume;
|
||||
IAudioRenderClient *render;
|
||||
|
||||
@ -204,13 +203,11 @@ void DSOUND_ParseSpeakerConfig(DirectSoundDevice *device) DECLSPEC_HIDDEN;
|
||||
|
||||
/* primary.c */
|
||||
|
||||
HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device) DECLSPEC_HIDDEN;
|
||||
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) DECLSPEC_HIDDEN;
|
||||
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device) DECLSPEC_HIDDEN;
|
||||
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) DECLSPEC_HIDDEN;
|
||||
LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex) DECLSPEC_HIDDEN;
|
||||
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) DECLSPEC_HIDDEN;
|
||||
HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device) DECLSPEC_HIDDEN;
|
||||
HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl **ppdsb,
|
||||
const DSBUFFERDESC *dsbd) DECLSPEC_HIDDEN;
|
||||
void primarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN;
|
||||
|
@ -197,16 +197,8 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
|
||||
static void DSOUND_ReleaseDevice(DirectSoundDevice *device)
|
||||
{
|
||||
WAVEFORMATEX *wfx = NULL;
|
||||
HRESULT hres;
|
||||
REFERENCE_TIME period, buflen = 800000;
|
||||
UINT32 frames;
|
||||
DWORD period_ms;
|
||||
|
||||
TRACE("(%p, %d)\n", device, forcewave);
|
||||
|
||||
if(device->client){
|
||||
IAudioClient_Release(device->client);
|
||||
device->client = NULL;
|
||||
@ -215,10 +207,6 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
|
||||
IAudioRenderClient_Release(device->render);
|
||||
device->render = NULL;
|
||||
}
|
||||
if(device->clock){
|
||||
IAudioClock_Release(device->clock);
|
||||
device->clock = NULL;
|
||||
}
|
||||
if(device->volume){
|
||||
IAudioStreamVolume_Release(device->volume);
|
||||
device->volume = NULL;
|
||||
@ -229,145 +217,75 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
|
||||
device->playpos %= device->buflen;
|
||||
device->pad = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
|
||||
CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
|
||||
if(FAILED(hres)) {
|
||||
WARN("Activate failed: %08x\n", hres);
|
||||
return hres;
|
||||
static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device, WAVEFORMATEX *wfx, DWORD frames, BOOL forcewave)
|
||||
{
|
||||
IDirectSoundBufferImpl** dsb = device->buffers;
|
||||
LPBYTE newbuf;
|
||||
DWORD new_buflen;
|
||||
BOOL mixfloat = FALSE;
|
||||
int i;
|
||||
|
||||
TRACE("(%p)\n", device);
|
||||
|
||||
new_buflen = device->buflen;
|
||||
new_buflen -= new_buflen % wfx->nBlockAlign;
|
||||
|
||||
if (wfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
|
||||
(wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
|
||||
IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)wfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
|
||||
mixfloat = TRUE;
|
||||
|
||||
/* reallocate emulated primary buffer */
|
||||
if (forcewave) {
|
||||
if (device->buffer)
|
||||
newbuf = HeapReAlloc(GetProcessHeap(), 0, device->buffer, new_buflen);
|
||||
else
|
||||
newbuf = HeapAlloc(GetProcessHeap(), 0, new_buflen);
|
||||
|
||||
if (!newbuf) {
|
||||
ERR("failed to allocate primary buffer\n");
|
||||
return DSERR_OUTOFMEMORY;
|
||||
}
|
||||
FillMemory(newbuf, new_buflen, (wfx->wBitsPerSample == 8) ? 128 : 0);
|
||||
} else if (!mixfloat) {
|
||||
DWORD alloc_len = frames * sizeof(float);
|
||||
|
||||
if (device->buffer)
|
||||
newbuf = HeapReAlloc(GetProcessHeap(), 0, device->buffer, alloc_len);
|
||||
else
|
||||
newbuf = HeapAlloc(GetProcessHeap(), 0, alloc_len);
|
||||
|
||||
if (!newbuf) {
|
||||
ERR("failed to allocate primary buffer\n");
|
||||
return DSERR_OUTOFMEMORY;
|
||||
}
|
||||
FillMemory(newbuf, alloc_len, (wfx->wBitsPerSample == 8) ? 128 : 0);
|
||||
} else {
|
||||
HeapFree(GetProcessHeap(), 0, device->buffer);
|
||||
newbuf = NULL;
|
||||
}
|
||||
|
||||
device->speaker_config = DSOUND_FindSpeakerConfig(device->mmdevice, 0);
|
||||
|
||||
DSOUND_ParseSpeakerConfig(device);
|
||||
|
||||
hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx);
|
||||
if (FAILED(hres)) {
|
||||
IAudioClient_Release(device->client);
|
||||
device->client = NULL;
|
||||
return hres;
|
||||
}
|
||||
device->buffer = newbuf;
|
||||
device->buflen = new_buflen;
|
||||
HeapFree(GetProcessHeap(), 0, device->pwfx);
|
||||
device->pwfx = wfx;
|
||||
|
||||
hres = IAudioClient_Initialize(device->client,
|
||||
AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buflen, 0, device->pwfx, NULL);
|
||||
if(FAILED(hres)){
|
||||
IAudioClient_Release(device->client);
|
||||
device->client = NULL;
|
||||
WARN("Initialize failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
IAudioClient_SetEventHandle(device->client, device->sleepev);
|
||||
if (device->state == STATE_PLAYING)
|
||||
device->state = STATE_STARTING;
|
||||
else if (device->state == STATE_STOPPING)
|
||||
device->state = STATE_STOPPED;
|
||||
|
||||
hres = IAudioClient_GetService(device->client, &IID_IAudioRenderClient,
|
||||
(void**)&device->render);
|
||||
if(FAILED(hres)){
|
||||
IAudioClient_Release(device->client);
|
||||
device->client = NULL;
|
||||
WARN("GetService failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
|
||||
hres = IAudioClient_GetService(device->client, &IID_IAudioClock,
|
||||
(void**)&device->clock);
|
||||
if(FAILED(hres)){
|
||||
IAudioClient_Release(device->client);
|
||||
IAudioRenderClient_Release(device->render);
|
||||
device->client = NULL;
|
||||
device->render = NULL;
|
||||
WARN("GetService failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
|
||||
hres = IAudioClient_GetService(device->client, &IID_IAudioStreamVolume,
|
||||
(void**)&device->volume);
|
||||
if(FAILED(hres)){
|
||||
IAudioClient_Release(device->client);
|
||||
IAudioRenderClient_Release(device->render);
|
||||
IAudioClock_Release(device->clock);
|
||||
device->client = NULL;
|
||||
device->render = NULL;
|
||||
device->clock = NULL;
|
||||
WARN("GetService failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
|
||||
/* Now kick off the timer so the event fires periodically */
|
||||
hres = IAudioClient_Start(device->client);
|
||||
if (FAILED(hres))
|
||||
WARN("starting failed with %08x\n", hres);
|
||||
|
||||
hres = IAudioClient_GetStreamLatency(device->client, &period);
|
||||
if (FAILED(hres)) {
|
||||
WARN("GetStreamLatency failed with %08x\n", hres);
|
||||
period = 100000;
|
||||
}
|
||||
period_ms = (period + 9999) / 10000;
|
||||
|
||||
hres = IAudioClient_GetBufferSize(device->client, &frames);
|
||||
if (FAILED(hres)) {
|
||||
WARN("GetBufferSize failed with %08x\n", hres);
|
||||
frames = (UINT64)device->pwfx->nSamplesPerSec * buflen / 10000000;
|
||||
}
|
||||
|
||||
device->fraglen = MulDiv(device->pwfx->nSamplesPerSec, period, 10000000) * device->pwfx->nBlockAlign;
|
||||
device->aclen = frames * device->pwfx->nBlockAlign;
|
||||
TRACE("period %u ms fraglen %u buflen %u\n", period_ms, device->fraglen, device->aclen);
|
||||
|
||||
if (period_ms < 3)
|
||||
device->sleeptime = 5;
|
||||
else
|
||||
device->sleeptime = period_ms * 5 / 2;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
|
||||
{
|
||||
IDirectSoundBufferImpl** dsb = device->buffers;
|
||||
LPBYTE newbuf;
|
||||
int i;
|
||||
|
||||
TRACE("(%p)\n", device);
|
||||
|
||||
/* on original windows, the buffer it set to a fixed size, no matter what the settings are.
|
||||
on windows this size is always fixed (tested on win-xp) */
|
||||
if (!device->buflen)
|
||||
device->buflen = ds_hel_buflen;
|
||||
device->buflen -= device->buflen % device->pwfx->nBlockAlign;
|
||||
|
||||
if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
|
||||
else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
|
||||
|
||||
/* reallocate emulated primary buffer */
|
||||
if (device->buffer)
|
||||
newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, device->buflen);
|
||||
else
|
||||
newbuf = HeapAlloc(GetProcessHeap(),0, device->buflen);
|
||||
|
||||
if (!newbuf) {
|
||||
ERR("failed to allocate primary buffer\n");
|
||||
return DSERR_OUTOFMEMORY;
|
||||
/* but the old buffer might still exist and must be re-prepared */
|
||||
}
|
||||
|
||||
device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
|
||||
|
||||
device->buffer = newbuf;
|
||||
device->writelead = (wfx->nSamplesPerSec / 100) * wfx->nBlockAlign;
|
||||
|
||||
TRACE("buflen: %u, fraglen: %u\n", device->buflen, device->fraglen);
|
||||
|
||||
if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
|
||||
(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
|
||||
IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat,
|
||||
&KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
|
||||
device->normfunction = NULL;
|
||||
if (!mixfloat)
|
||||
device->normfunction = normfunctions[wfx->wBitsPerSample/8 - 1];
|
||||
else
|
||||
device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
|
||||
device->normfunction = NULL;
|
||||
|
||||
FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
|
||||
device->playpos = 0;
|
||||
|
||||
for (i = 0; i < device->nrofbuffers; i++) {
|
||||
@ -379,35 +297,105 @@ HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
|
||||
static void DSOUND_PrimaryClose(DirectSoundDevice *device)
|
||||
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
|
||||
{
|
||||
HRESULT hr;
|
||||
HRESULT hres;
|
||||
REFERENCE_TIME period;
|
||||
UINT32 frames;
|
||||
DWORD period_ms;
|
||||
IAudioClient *client = NULL;
|
||||
IAudioRenderClient *render = NULL;
|
||||
IAudioStreamVolume *volume = NULL;
|
||||
DWORD fraglen;
|
||||
WAVEFORMATEX *wfx = NULL;
|
||||
DWORD oldspeakerconfig = device->speaker_config;
|
||||
|
||||
TRACE("(%p)\n", device);
|
||||
TRACE("(%p, %d)\n", device, forcewave);
|
||||
|
||||
if(device->client){
|
||||
hr = IAudioClient_Stop(device->client);
|
||||
if(FAILED(hr))
|
||||
WARN("Stop failed: %08x\n", hr);
|
||||
hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
|
||||
CLSCTX_INPROC_SERVER, NULL, (void **)&client);
|
||||
if(FAILED(hres)){
|
||||
WARN("Activate failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device)
|
||||
{
|
||||
HRESULT err = DS_OK;
|
||||
TRACE("(%p)\n", device);
|
||||
hres = DSOUND_WaveFormat(device, client, forcewave, &wfx);
|
||||
if (FAILED(hres)) {
|
||||
IAudioClient_Release(client);
|
||||
return hres;
|
||||
}
|
||||
|
||||
device->buflen = ds_hel_buflen;
|
||||
err = DSOUND_PrimaryOpen(device);
|
||||
hres = IAudioClient_Initialize(client,
|
||||
AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST |
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 800000, 0, wfx, NULL);
|
||||
if(FAILED(hres)){
|
||||
IAudioClient_Release(client);
|
||||
ERR("Initialize failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
|
||||
if (err != DS_OK) {
|
||||
WARN("DSOUND_PrimaryOpen failed\n");
|
||||
return err;
|
||||
}
|
||||
IAudioClient_SetEventHandle(client, device->sleepev);
|
||||
|
||||
device->state = STATE_STOPPED;
|
||||
return DS_OK;
|
||||
hres = IAudioClient_GetService(client, &IID_IAudioRenderClient, (void**)&render);
|
||||
if(FAILED(hres))
|
||||
goto err_service;
|
||||
|
||||
hres = IAudioClient_GetService(client, &IID_IAudioStreamVolume, (void**)&volume);
|
||||
if(FAILED(hres))
|
||||
goto err_service;
|
||||
|
||||
/* Now kick off the timer so the event fires periodically */
|
||||
hres = IAudioClient_Start(client);
|
||||
if (FAILED(hres)) {
|
||||
WARN("Start failed with %08x\n", hres);
|
||||
goto err;
|
||||
}
|
||||
hres = IAudioClient_GetStreamLatency(client, &period);
|
||||
if (FAILED(hres)) {
|
||||
WARN("GetStreamLatency failed with %08x\n", hres);
|
||||
goto err;
|
||||
}
|
||||
hres = IAudioClient_GetBufferSize(client, &frames);
|
||||
if (FAILED(hres)) {
|
||||
WARN("GetBufferSize failed with %08x\n", hres);
|
||||
goto err;
|
||||
}
|
||||
|
||||
period_ms = (period + 9999) / 10000;
|
||||
fraglen = MulDiv(wfx->nSamplesPerSec, period, 10000000) * wfx->nBlockAlign;
|
||||
TRACE("period %u ms fraglen %u buflen %u\n", period_ms, fraglen, frames * wfx->nBlockAlign);
|
||||
|
||||
hres = DSOUND_PrimaryOpen(device, wfx, frames, forcewave);
|
||||
if(FAILED(hres))
|
||||
goto err;
|
||||
|
||||
DSOUND_ReleaseDevice(device);
|
||||
device->client = client;
|
||||
device->render = render;
|
||||
device->volume = volume;
|
||||
device->fraglen = fraglen;
|
||||
device->aclen = frames * wfx->nBlockAlign;
|
||||
|
||||
if (period_ms < 3)
|
||||
device->sleeptime = 5;
|
||||
else
|
||||
device->sleeptime = period_ms * 5 / 2;
|
||||
|
||||
return S_OK;
|
||||
|
||||
err_service:
|
||||
ERR("GetService failed: %08x\n", hres);
|
||||
err:
|
||||
device->speaker_config = oldspeakerconfig;
|
||||
DSOUND_ParseSpeakerConfig(device);
|
||||
if (volume)
|
||||
IAudioStreamVolume_Release(volume);
|
||||
if (render)
|
||||
IAudioRenderClient_Release(render);
|
||||
if (client)
|
||||
IAudioClient_Release(client);
|
||||
HeapFree(GetProcessHeap(), 0, wfx);
|
||||
return hres;
|
||||
}
|
||||
|
||||
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
|
||||
@ -417,8 +405,6 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *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);
|
||||
|
||||
@ -470,10 +456,14 @@ WAVEFORMATEX *DSOUND_CopyFormat(const WAVEFORMATEX *wfex)
|
||||
WAVEFORMATEX *pwfx;
|
||||
if(wfex->wFormatTag == WAVE_FORMAT_PCM){
|
||||
pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX));
|
||||
if (!pwfx)
|
||||
return NULL;
|
||||
CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
|
||||
pwfx->cbSize = 0;
|
||||
}else{
|
||||
pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX) + wfex->cbSize);
|
||||
if (!pwfx)
|
||||
return NULL;
|
||||
CopyMemory(pwfx, wfex, sizeof(WAVEFORMATEX) + wfex->cbSize);
|
||||
}
|
||||
|
||||
@ -490,7 +480,6 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
|
||||
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);
|
||||
|
||||
@ -540,28 +529,20 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
|
||||
fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample;
|
||||
}
|
||||
|
||||
DSOUND_PrimaryClose(device);
|
||||
|
||||
err = DSOUND_ReopenDevice(device, forced);
|
||||
err = DSOUND_ReopenDevice(device, TRUE);
|
||||
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)
|
||||
HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
|
||||
device->primary_pwfx = old_fmt;
|
||||
else
|
||||
} else
|
||||
HeapFree(GetProcessHeap(), 0, old_fmt);
|
||||
} else {
|
||||
HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
|
||||
device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
|
||||
WAVEFORMATEX *wfx = DSOUND_CopyFormat(passed_fmt);
|
||||
if (wfx) {
|
||||
HeapFree(GetProcessHeap(), 0, device->primary_pwfx);
|
||||
device->primary_pwfx = wfx;
|
||||
} else
|
||||
err = DSERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
out:
|
||||
|
Loading…
Reference in New Issue
Block a user