diff --git a/reactos/dll/directx/wine/dsound/CMakeLists.txt b/reactos/dll/directx/wine/dsound/CMakeLists.txt index 37a695a2034..71aa4176092 100644 --- a/reactos/dll/directx/wine/dsound/CMakeLists.txt +++ b/reactos/dll/directx/wine/dsound/CMakeLists.txt @@ -5,7 +5,6 @@ add_definitions( -D__WINESRC__) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) - spec2def(dsound.dll dsound.spec ADD_IMPORTLIB) add_library(dsound SHARED @@ -19,10 +18,9 @@ add_library(dsound SHARED primary.c propset.c sound3d.c - version.rc ${CMAKE_CURRENT_BINARY_DIR}/dsound.def) -set_module_type(dsound win32dll) +set_module_type(dsound win32dll version.rc) target_link_libraries(dsound dxguid uuid wine) -add_importlibs(dsound winmm ole32 advapi32 user32 msvcrt kernel32 ntdll) +add_importlibs(dsound 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 df3fdcf7476..fcee0b8e866 100644 --- a/reactos/dll/directx/wine/dsound/capture.c +++ b/reactos/dll/directx/wine/dsound/capture.c @@ -62,6 +62,8 @@ typedef struct IDirectSoundCaptureBufferImpl /* IDirectSoundNotify fields */ DSBPOSITIONNOTIFY *notifies; int nrofnotifies; + HANDLE thread; + HANDLE sleepev; } IDirectSoundCaptureBufferImpl; /* DirectSoundCaptureDevice implementation structure */ @@ -75,7 +77,6 @@ struct DirectSoundCaptureDevice WAVEFORMATEX *pwfx; IDirectSoundCaptureBufferImpl *capture_buffer; DWORD state; - UINT timerID; CRITICAL_SECTION lock; IMMDevice *mmdevice; IAudioClient *client; @@ -83,12 +84,20 @@ 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) { @@ -742,8 +751,8 @@ static HRESULT IDirectSoundCaptureBufferImpl_Create( } err = IAudioClient_Initialize(device->client, - AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST, - 200 * 100000, 50000, device->pwfx, NULL); + AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + 200 * 100000, 0, device->pwfx, NULL); if(FAILED(err)){ WARN("Initialize failed: %08x\n", err); IAudioClient_Release(device->client); @@ -756,12 +765,27 @@ 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 ); @@ -779,6 +803,7 @@ 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 ); @@ -786,6 +811,7 @@ 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); @@ -833,9 +859,6 @@ 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); @@ -854,29 +877,19 @@ static ULONG DirectSoundCaptureDevice_Release( return ref; } -static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user, - DWORD_PTR dw1, DWORD_PTR dw2) +static HRESULT DSOUND_capture_data(DirectSoundCaptureDevice *device) { - DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user; - UINT32 packet_frames, packet_bytes, avail_bytes; + HRESULT hr; + UINT32 packet_frames, packet_bytes, avail_bytes, skip_bytes = 0; DWORD flags; BYTE *buf; - HRESULT hr; - if(!device->ref) - return; - - EnterCriticalSection(&device->lock); - - if(!device->capture_buffer || device->state == STATE_STOPPED){ - LeaveCriticalSection(&device->lock); - return; - } + if(!device->capture_buffer || device->state == STATE_STOPPED) + return S_FALSE; if(device->state == STATE_STOPPING){ device->state = STATE_STOPPED; - LeaveCriticalSection(&device->lock); - return; + return S_FALSE; } if(device->state == STATE_STARTING) @@ -885,24 +898,28 @@ static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames, &flags, NULL, NULL); if(FAILED(hr)){ - LeaveCriticalSection(&device->lock); WARN("GetBuffer failed: %08x\n", hr); - return; + return hr; } 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, avail_bytes); + memcpy(device->buffer + device->write_pos_bytes, buf + skip_bytes, 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 + avail_bytes, packet_bytes); + memcpy(device->buffer, buf + skip_bytes + avail_bytes, packet_bytes); capture_CheckNotify(device->capture_buffer, 0, packet_bytes); }else{ device->state = STATE_STOPPED; @@ -915,12 +932,44 @@ static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames); if(FAILED(hr)){ - LeaveCriticalSection(&device->lock); WARN("ReleaseBuffer failed: %08x\n", hr); - return; + return hr; } - LeaveCriticalSection(&device->lock); + 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; } static struct _TestFormat { @@ -984,14 +1033,6 @@ 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"); @@ -1026,8 +1067,6 @@ 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 3de24e57eb6..13f6a5d5c64 100644 --- a/reactos/dll/directx/wine/dsound/dsound.c +++ b/reactos/dll/directx/wine/dsound/dsound.c @@ -738,30 +738,6 @@ 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 a4e5e7125bb..aa75c558eeb 100644 --- a/reactos/dll/directx/wine/dsound/dsound_main.c +++ b/reactos/dll/directx/wine/dsound/dsound_main.c @@ -800,20 +800,16 @@ 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: - TRACE("DLL_PROCESS_DETACH\n"); + if (lpvReserved) break; 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 1a3900c4870..a8f5f42a7f1 100644 --- a/reactos/dll/directx/wine/dsound/dsound_private.h +++ b/reactos/dll/directx/wine/dsound/dsound_private.h @@ -261,6 +261,5 @@ 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 15a97896d12..93962a0a963 100644 --- a/reactos/dll/directx/wine/dsound/primary.c +++ b/reactos/dll/directx/wine/dsound/primary.c @@ -443,35 +443,24 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP return DS_OK; } -static DWORD DSOUND_GetFormatSize(LPCWAVEFORMATEX wfex) +WAVEFORMATEX *DSOUND_CopyFormat(const WAVEFORMATEX *wfex) { - if (wfex->wFormatTag == WAVE_FORMAT_PCM) - return sizeof(WAVEFORMATEX); - else - return sizeof(WAVEFORMATEX) + wfex->cbSize; -} + 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); + } -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; + 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; } HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) @@ -548,27 +537,9 @@ 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 { - device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex)); - memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex)); + HeapFree(GetProcessHeap(), 0, device->primary_pwfx); + device->primary_pwfx = DSOUND_CopyFormat(passed_fmt); } out: diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 2a56c50ec94..3d21994fefb 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -39,7 +39,7 @@ reactos/dll/directx/wine/dinput8 # Synced to Wine-1.5.26 reactos/dll/directx/wine/dmusic # Synced to Wine-1.5.26 reactos/dll/directx/wine/dplay # Synced to Wine-1.5.26 reactos/dll/directx/wine/dplayx # Synced to Wine-1.5.26 -reactos/dll/directx/wine/dsound # Synced to Wine-1.5.26 +reactos/dll/directx/wine/dsound # Synced to Wine-1.7.1 reactos/dll/directx/wine/dxdiagn # Synced to Wine-0_9_5 reactos/dll/directx/wine/dxgi # Synced to Wine-1.7.1 reactos/dll/directx/wine/msdmo # Autosync