[DSOUND]
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 27 Jan 2014 11:38:02 +0000 (11:38 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 27 Jan 2014 11:38:02 +0000 (11:38 +0000)
* Revert r60474 until Johannes has time to look into it.

svn path=/trunk/; revision=61851

reactos/dll/directx/wine/dsound/CMakeLists.txt
reactos/dll/directx/wine/dsound/capture.c
reactos/dll/directx/wine/dsound/dsound.c
reactos/dll/directx/wine/dsound/dsound_main.c
reactos/dll/directx/wine/dsound/dsound_private.h
reactos/dll/directx/wine/dsound/primary.c
reactos/media/doc/README.WINE

index d77cb4a..9d81dc6 100644 (file)
@@ -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)
index fd7539a..756bbc0 100644 (file)
@@ -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;
index eff3de8..19577c9 100644 (file)
@@ -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;
index fc20c51..43e1432 100644 (file)
@@ -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;
 }
index 6bd6a98..7a1d901 100644 (file)
@@ -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;
index 5a90782..fd1dbb7 100644 (file)
@@ -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(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;
+       if (wfex->wFormatTag == WAVE_FORMAT_PCM)
+               return sizeof(WAVEFORMATEX);
+       else
+               return sizeof(WAVEFORMATEX) + wfex->cbSize;
+}
 
-    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:
index f8e229e..f6940fb 100644 (file)
@@ -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