Maarten Lankhorst : quartz: Implement state transitions in directsound renderer, and block on pause.

Alexandre Julliard julliard at winehq.org
Fri Jul 4 13:59:19 CDT 2008


Module: wine
Branch: master
Commit: b6b67f698a193d3c076c42dc0e3a186631e547f4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b6b67f698a193d3c076c42dc0e3a186631e547f4

Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date:   Fri Jul  4 00:09:07 2008 -0700

quartz: Implement state transitions in directsound renderer, and block on pause.

---

 dlls/quartz/dsoundrender.c |   81 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index e81acfb..9e6e7ed 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -73,6 +73,8 @@ typedef struct DSoundRenderImpl
     REFERENCE_TIME play_time;
     MediaSeekingImpl mediaSeeking;
 
+    HANDLE state_change, blocked;
+
     long volume;
     long pan;
 } DSoundRenderImpl;
@@ -246,6 +248,8 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
     if (This->state == State_Stopped)
         return VFW_E_WRONG_STATE;
 
+    SetEvent(This->state_change);
+
     hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
     if (FAILED(hr))
     {
@@ -270,7 +274,19 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
     }
 
     if (This->state == State_Paused)
-        return S_OK;
+    {
+        LeaveCriticalSection(&This->csFilter);
+        WaitForSingleObject(This->blocked, INFINITE);
+        EnterCriticalSection(&This->csFilter);
+        if (This->state == State_Stopped)
+            return VFW_E_WRONG_STATE;
+
+        if (This->state == State_Paused)
+        {
+            /* Assuming we return because of flushing */
+            return S_OK;
+        }
+    }
 
     cbSrcStream = IMediaSample_GetActualDataLength(pSample);
     TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream);
@@ -359,6 +375,15 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
         MediaSeekingImpl_Init((IBaseFilter*)pDSoundRender, sound_mod_stop, sound_mod_start, sound_mod_rate, &pDSoundRender->mediaSeeking, &pDSoundRender->csFilter);
         pDSoundRender->mediaSeeking.lpVtbl = &IMediaSeeking_Vtbl;
 
+        pDSoundRender->state_change = CreateEventW(NULL, TRUE, TRUE, NULL);
+        pDSoundRender->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+        if (!pDSoundRender->state_change || !pDSoundRender->blocked)
+        {
+            IUnknown_Release((IUnknown *)pDSoundRender);
+            return HRESULT_FROM_WIN32(GetLastError());
+        }
+
         *ppv = (LPVOID)pDSoundRender;
     }
     else
@@ -453,6 +478,9 @@ static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface)
         This->csFilter.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&This->csFilter);
 
+        CloseHandle(This->state_change);
+        CloseHandle(This->blocked);
+
         TRACE("Destroying Audio Renderer\n");
         CoTaskMemFree(This);
         
@@ -497,6 +525,10 @@ static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface)
         }
         if (SUCCEEDED(hr))
             This->state = State_Stopped;
+
+        /* Complete our transition */
+        SetEvent(This->state_change);
+        SetEvent(This->blocked);
     }
     LeaveCriticalSection(&This->csFilter);
     
@@ -511,10 +543,13 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
     TRACE("(%p/%p)->()\n", This, iface);
 
     EnterCriticalSection(&This->csFilter);
+    if (This->state != State_Paused)
     {
         DWORD state = 0;
         if (This->state == State_Stopped)
+        {
             This->pInputPin->end_of_stream = 0;
+        }
 
         if (This->dsbuffer)
         {
@@ -527,6 +562,9 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
         }
         if (SUCCEEDED(hr))
             This->state = State_Paused;
+
+        ResetEvent(This->blocked);
+        ResetEvent(This->state_change);
     }
     LeaveCriticalSection(&This->csFilter);
 
@@ -543,8 +581,18 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar
     EnterCriticalSection(&This->csFilter);
     {
         This->rtStreamStart = tStart;
+        if (This->state == State_Paused)
+        {
+            /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */
+            SetEvent(This->blocked);
+        }
+        else if (This->state == State_Stopped)
+        {
+            ResetEvent(This->state_change);
+            This->pInputPin->end_of_stream = 0;
+        }
+
         This->state = State_Running;
-        This->pInputPin->end_of_stream = 0;
     }
     LeaveCriticalSection(&This->csFilter);
 
@@ -553,10 +601,16 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar
 
 static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
 {
+    HRESULT hr;
     DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
 
     TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
 
+    if (WaitForSingleObject(This->state_change, dwMilliSecsTimeout) == WAIT_TIMEOUT)
+        hr = VFW_S_STATE_INTERMEDIATE;
+    else
+        hr = S_OK;
+
     EnterCriticalSection(&This->csFilter);
     {
         *pState = This->state;
@@ -866,6 +920,27 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
         memset(buffer, 0, size);
         IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0);
     }
+
+    if (pFilter->state == State_Paused)
+        SetEvent(pFilter->blocked);
+    LeaveCriticalSection(This->pin.pCritSec);
+
+    return hr;
+}
+
+static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface)
+{
+    InputPin *This = (InputPin *)iface;
+    DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
+    HRESULT hr;
+
+    TRACE("\n");
+
+    EnterCriticalSection(This->pin.pCritSec);
+    hr = InputPin_EndFlush(iface);
+
+    if (pFilter->state == State_Paused)
+        SetEvent(pFilter->blocked);
     LeaveCriticalSection(This->pin.pCritSec);
 
     return hr;
@@ -889,7 +964,7 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl =
     IPinImpl_QueryInternalConnections,
     DSoundRender_InputPin_EndOfStream,
     DSoundRender_InputPin_BeginFlush,
-    InputPin_EndFlush,
+    DSoundRender_InputPin_EndFlush,
     InputPin_NewSegment
 };
 




More information about the wine-cvs mailing list