diff --git a/reactos/dll/directx/wine/dsound/CMakeLists.txt b/reactos/dll/directx/wine/dsound/CMakeLists.txt index d77cb4a499f..9d81dc6c6c7 100644 --- a/reactos/dll/directx/wine/dsound/CMakeLists.txt +++ b/reactos/dll/directx/wine/dsound/CMakeLists.txt @@ -5,6 +5,7 @@ add_definitions( -D__WINESRC__) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) + spec2def(dsound.dll dsound.spec ADD_IMPORTLIB) add_library(dsound SHARED @@ -24,5 +25,5 @@ add_library(dsound SHARED set_module_type(dsound win32dll) target_link_libraries(dsound dxguid uuid wine) -add_importlibs(dsound ole32 advapi32 user32 msvcrt kernel32 ntdll) +add_importlibs(dsound winmm ole32 advapi32 user32 msvcrt kernel32 ntdll) add_cd_file(TARGET dsound DESTINATION reactos/system32 FOR all) diff --git a/reactos/dll/directx/wine/dsound/capture.c b/reactos/dll/directx/wine/dsound/capture.c index fd7539ac645..756bbc090f2 100644 --- a/reactos/dll/directx/wine/dsound/capture.c +++ b/reactos/dll/directx/wine/dsound/capture.c @@ -43,8 +43,6 @@ typedef struct IDirectSoundCaptureBufferImpl /* IDirectSoundNotify fields */ DSBPOSITIONNOTIFY *notifies; int nrofnotifies; - HANDLE thread; - HANDLE sleepev; } IDirectSoundCaptureBufferImpl; /* DirectSoundCaptureDevice implementation structure */ @@ -58,6 +56,7 @@ struct DirectSoundCaptureDevice WAVEFORMATEX *pwfx; IDirectSoundCaptureBufferImpl *capture_buffer; DWORD state; + UINT timerID; CRITICAL_SECTION lock; IMMDevice *mmdevice; IAudioClient *client; @@ -65,20 +64,12 @@ struct DirectSoundCaptureDevice struct list entry; }; -static DWORD WINAPI DSOUND_capture_thread(void *user); static void capturebuffer_destroy(IDirectSoundCaptureBufferImpl *This) { if (This->device->state == STATE_CAPTURING) This->device->state = STATE_STOPPING; - if(This->thread){ - SetEvent(This->sleepev); - WaitForSingleObject(This->thread, INFINITE); - CloseHandle(This->thread); - } - CloseHandle(This->sleepev); - HeapFree(GetProcessHeap(),0, This->pdscbd); if (This->device->client) { @@ -732,8 +723,8 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create( } err = IAudioClient_Initialize(device->client, - AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - 200 * 100000, 0, device->pwfx, NULL); + AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST, + 200 * 100000, 50000, device->pwfx, NULL); if(FAILED(err)){ WARN("Initialize failed: %08x\n", err); IAudioClient_Release(device->client); @@ -746,27 +737,12 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create( return err; } - This->sleepev = CreateEventW(NULL, 0, 0, NULL); - - err = IAudioClient_SetEventHandle(device->client, This->sleepev); - if(FAILED(err)){ - WARN("SetEventHandle failed: %08x\n", err); - IAudioClient_Release(device->client); - device->client = NULL; - CloseHandle(This->sleepev); - HeapFree(GetProcessHeap(), 0, This->pdscbd); - This->device->capture_buffer = 0; - HeapFree( GetProcessHeap(), 0, This ); - return err; - } - err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient, (void**)&device->capture); if(FAILED(err)){ WARN("GetService failed: %08x\n", err); IAudioClient_Release(device->client); device->client = NULL; - CloseHandle(This->sleepev); HeapFree(GetProcessHeap(), 0, This->pdscbd); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); @@ -784,7 +760,6 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create( device->client = NULL; IAudioCaptureClient_Release(device->capture); device->capture = NULL; - CloseHandle(This->sleepev); HeapFree(GetProcessHeap(), 0, This->pdscbd); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); @@ -792,7 +767,6 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create( } device->buffer = newbuf; device->buflen = buflen; - This->thread = CreateThread(NULL, 0, DSOUND_capture_thread, This, 0, NULL); } IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface); @@ -840,6 +814,9 @@ static ULONG DirectSoundCaptureDevice_Release( if (!ref) { TRACE("deleting object\n"); + timeKillEvent(device->timerID); + timeEndPeriod(DS_TIME_RES); + EnterCriticalSection(&DSOUND_capturers_lock); list_remove(&device->entry); LeaveCriticalSection(&DSOUND_capturers_lock); @@ -858,19 +835,29 @@ static ULONG DirectSoundCaptureDevice_Release( return ref; } -static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device) +static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user, + DWORD_PTR dw1, DWORD_PTR dw2) { - HRESULT hr; - UINT32 packet_frames, packet_bytes, avail_bytes, skip_bytes = 0; + DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user; + UINT32 packet_frames, packet_bytes, avail_bytes; DWORD flags; BYTE *buf; + HRESULT hr; - if(!device->capture_buffer || device->state == STATE_STOPPED) - return S_FALSE; + if(!device->ref) + return; + + EnterCriticalSection(&device->lock); + + if(!device->capture_buffer || device->state == STATE_STOPPED){ + LeaveCriticalSection(&device->lock); + return; + } if(device->state == STATE_STOPPING){ device->state = STATE_STOPPED; - return S_FALSE; + LeaveCriticalSection(&device->lock); + return; } if(device->state == STATE_STARTING) @@ -879,28 +866,24 @@ static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device) hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames, &flags, NULL, NULL); if(FAILED(hr)){ + LeaveCriticalSection(&device->lock); WARN("GetBuffer failed: %08x\n", hr); - return hr; + return; } packet_bytes = packet_frames * device->pwfx->nBlockAlign; - if(packet_bytes > device->buflen){ - TRACE("audio glitch: dsound buffer too small for data\n"); - skip_bytes = packet_bytes - device->buflen; - packet_bytes = device->buflen; - } avail_bytes = device->buflen - device->write_pos_bytes; if(avail_bytes > packet_bytes) avail_bytes = packet_bytes; - memcpy(device->buffer + device->write_pos_bytes, buf + skip_bytes, avail_bytes); + memcpy(device->buffer + device->write_pos_bytes, buf, avail_bytes); capture_CheckNotify(device->capture_buffer, device->write_pos_bytes, avail_bytes); packet_bytes -= avail_bytes; if(packet_bytes > 0){ if(device->capture_buffer->flags & DSCBSTART_LOOPING){ - memcpy(device->buffer, buf + skip_bytes + avail_bytes, packet_bytes); + memcpy(device->buffer, buf + avail_bytes, packet_bytes); capture_CheckNotify(device->capture_buffer, 0, packet_bytes); }else{ device->state = STATE_STOPPED; @@ -913,44 +896,12 @@ static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device) hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames); if(FAILED(hr)){ + LeaveCriticalSection(&device->lock); WARN("ReleaseBuffer failed: %08x\n", hr); - return hr; + return; } - return S_OK; -} - -static DWORD WINAPI DSOUND_capture_thread(void *user) -{ - IDirectSoundCaptureBufferImpl *buffer = user; - HRESULT hr; - DWORD ret, wait_ms; - REFERENCE_TIME period; - - hr = IAudioClient_GetDevicePeriod(buffer->device->client, &period, NULL); - if(FAILED(hr)){ - WARN("GetDevicePeriod failed: %08x\n", hr); - wait_ms = 5; - }else - wait_ms = MulDiv(5, period, 10000); - - while(buffer->ref){ - ret = WaitForSingleObject(buffer->sleepev, wait_ms); - - if(!buffer->device->ref) - break; - - if(ret == WAIT_OBJECT_0){ - EnterCriticalSection(&buffer->device->lock); - - DSOUND_capture_data(buffer->device); - - LeaveCriticalSection(&buffer->device->lock); - }else if(ret != WAIT_TIMEOUT) - WARN("WaitForSingleObject failed: %u\n", GetLastError()); - } - - return 0; + LeaveCriticalSection(&device->lock); } static struct _TestFormat { @@ -1014,6 +965,14 @@ static HRESULT DirectSoundCaptureDevice_Initialize( EnterCriticalSection(&DSOUND_capturers_lock); + LIST_FOR_EACH_ENTRY(device, &DSOUND_capturers, DirectSoundCaptureDevice, entry){ + if(IsEqualGUID(&device->guid, &devGUID)){ + IMMDevice_Release(mmdevice); + LeaveCriticalSection(&DSOUND_capturers_lock); + return DSERR_ALLOCATED; + } + } + hr = DirectSoundCaptureDevice_Create(&device); if (hr != DS_OK) { WARN("DirectSoundCaptureDevice_Create failed\n"); @@ -1048,6 +1007,8 @@ static HRESULT DirectSoundCaptureDevice_Initialize( } IAudioClient_Release(client); + device->timerID = DSOUND_create_timer(DSOUND_capture_timer, (DWORD_PTR)device); + list_add_tail(&DSOUND_capturers, &device->entry); *ppDevice = device; diff --git a/reactos/dll/directx/wine/dsound/dsound.c b/reactos/dll/directx/wine/dsound/dsound.c index eff3de84191..19577c914d7 100644 --- a/reactos/dll/directx/wine/dsound/dsound.c +++ b/reactos/dll/directx/wine/dsound/dsound.c @@ -715,6 +715,30 @@ BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate, return hr == S_OK; } +UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user) +{ + UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id; + TIMECAPS time; + + timeGetDevCaps(&time, sizeof(TIMECAPS)); + TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax); + if (triggertime < time.wPeriodMin) + triggertime = time.wPeriodMin; + if (res < time.wPeriodMin) + res = time.wPeriodMin; + if (timeBeginPeriod(res) == TIMERR_NOCANDO) + WARN("Could not set minimum resolution, don't expect sound\n"); + id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS); + if (!id) + { + WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n"); + id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC); + if (!id) + ERR("Could not create timer, sound playback will not occur\n"); + } + return id; +} + HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID) { HRESULT hr = DS_OK; diff --git a/reactos/dll/directx/wine/dsound/dsound_main.c b/reactos/dll/directx/wine/dsound/dsound_main.c index fc20c51d6af..43e143276f6 100644 --- a/reactos/dll/directx/wine/dsound/dsound_main.c +++ b/reactos/dll/directx/wine/dsound/dsound_main.c @@ -768,16 +768,20 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) switch (fdwReason) { case DLL_PROCESS_ATTACH: + TRACE("DLL_PROCESS_ATTACH\n"); instance = hInstDLL; DisableThreadLibraryCalls(hInstDLL); /* Increase refcount on dsound by 1 */ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)hInstDLL, &hInstDLL); break; case DLL_PROCESS_DETACH: - if (lpvReserved) break; + TRACE("DLL_PROCESS_DETACH\n"); DeleteCriticalSection(&DSOUND_renderers_lock); DeleteCriticalSection(&DSOUND_capturers_lock); break; + default: + TRACE("UNKNOWN REASON\n"); + break; } return TRUE; } diff --git a/reactos/dll/directx/wine/dsound/dsound_private.h b/reactos/dll/directx/wine/dsound/dsound_private.h index 6bd6a9813f4..7a1d901f975 100644 --- a/reactos/dll/directx/wine/dsound/dsound_private.h +++ b/reactos/dll/directx/wine/dsound/dsound_private.h @@ -287,5 +287,6 @@ HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device) DECLSP BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate, DWORD depth, WORD channels) DECLSPEC_HIDDEN; +UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user) DECLSPEC_HIDDEN; HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, LPDSENUMCALLBACKW cb, void *user) DECLSPEC_HIDDEN; diff --git a/reactos/dll/directx/wine/dsound/primary.c b/reactos/dll/directx/wine/dsound/primary.c index 5a907826c2d..fd1dbb75cc8 100644 --- a/reactos/dll/directx/wine/dsound/primary.c +++ b/reactos/dll/directx/wine/dsound/primary.c @@ -425,24 +425,35 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP return DS_OK; } -WAVEFORMATEX *DSOUND_CopyFormat(const WAVEFORMATEX *wfex) +static DWORD DSOUND_GetFormatSize(LPCWAVEFORMATEX wfex) { - WAVEFORMATEX *pwfx; - if(wfex->wFormatTag == WAVE_FORMAT_PCM){ - pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX)); - CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT)); - pwfx->cbSize = 0; - }else{ - pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX) + wfex->cbSize); - CopyMemory(pwfx, wfex, sizeof(WAVEFORMATEX) + wfex->cbSize); - } + if (wfex->wFormatTag == WAVE_FORMAT_PCM) + return sizeof(WAVEFORMATEX); + else + return sizeof(WAVEFORMATEX) + wfex->cbSize; +} - if(pwfx->wFormatTag == WAVE_FORMAT_PCM || - (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE && - IsEqualGUID(&((const WAVEFORMATEXTENSIBLE*)pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) - pwfx->nBlockAlign = (pwfx->nChannels * pwfx->wBitsPerSample) / 8; - - return pwfx; +LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex) +{ + DWORD size = DSOUND_GetFormatSize(wfex); + LPWAVEFORMATEX pwfx = HeapAlloc(GetProcessHeap(),0,size); + if (pwfx == NULL) { + WARN("out of memory\n"); + } else if (wfex->wFormatTag != WAVE_FORMAT_PCM) { + CopyMemory(pwfx, wfex, size); + } else { + CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT)); + pwfx->cbSize=0; + if (pwfx->nBlockAlign != pwfx->nChannels * pwfx->wBitsPerSample/8) { + WARN("Fixing bad nBlockAlign (%u)\n", pwfx->nBlockAlign); + pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8; + } + if (pwfx->nAvgBytesPerSec != pwfx->nSamplesPerSec * pwfx->nBlockAlign) { + WARN("Fixing bad nAvgBytesPerSec (%u)\n", pwfx->nAvgBytesPerSec); + pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign; + } + } + return pwfx; } HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) @@ -519,9 +530,27 @@ done: device->primary_pwfx = old_fmt; else HeapFree(GetProcessHeap(), 0, old_fmt); + } else if (passed_fmt->wFormatTag == WAVE_FORMAT_PCM || + passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { + /* Fill in "real" values to primary_pwfx */ + WAVEFORMATEX *fmt = device->primary_pwfx; + + *fmt = *device->pwfx; + fmtex = (void*)device->pwfx; + + if (IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) && + passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { + fmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + } else { + fmt->wFormatTag = WAVE_FORMAT_PCM; + fmt->wBitsPerSample = 16; + } + fmt->nBlockAlign = fmt->nChannels * fmt->wBitsPerSample / 8; + fmt->nAvgBytesPerSec = fmt->nBlockAlign * fmt->nSamplesPerSec; + fmt->cbSize = 0; } else { - HeapFree(GetProcessHeap(), 0, device->primary_pwfx); - device->primary_pwfx = DSOUND_CopyFormat(passed_fmt); + device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex)); + memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex)); } out: diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index f8e229eabe2..f6940fb9be1 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -40,7 +40,7 @@ reactos/dll/directx/wine/dinput8 # Synced to Wine-1.7.1 reactos/dll/directx/wine/dmusic # Synced to Wine-1.7.1 reactos/dll/directx/wine/dplay # Synced to Wine-1.7.1 reactos/dll/directx/wine/dplayx # Synced to Wine-1.7.1 -reactos/dll/directx/wine/dsound # Synced to Wine-1.7.1 +reactos/dll/directx/wine/dsound # Synced to Wine-1.5.26 reactos/dll/directx/wine/dxdiagn # Synced to Wine-1.7.1 reactos/dll/directx/wine/dxgi # Synced to Wine-1.7.1 reactos/dll/directx/wine/msdmo # Synced to Wine-1.7.1