Maarten Lankhorst : quartz: Make the directsound renderer handle the Play-> Pause->Play position without dropping data.

Alexandre Julliard julliard at winehq.org
Wed Apr 9 05:31:44 CDT 2008


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

Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date:   Tue Apr  8 16:48:00 2008 -0700

quartz: Make the directsound renderer handle the Play->Pause->Play position without dropping data.

---

 dlls/quartz/dsoundrender.c |   51 ++++++++++++++++++++++++++-----------------
 1 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index 290e02e..529f836 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -71,6 +71,7 @@ typedef struct DSoundRenderImpl
 
     DWORD last_play_pos;
     DWORD play_loops;
+
     REFERENCE_TIME play_time;
     MediaSeekingImpl mediaSeeking;
 
@@ -103,31 +104,20 @@ static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPo
     EnterCriticalSection(&This->csFilter);
     {
         DWORD state;
+        DWORD write_pos;
 
         hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state);
         if (SUCCEEDED(hr) && !(state & DSBSTATUS_PLAYING) && This->state == State_Running)
         {
-            LPBYTE buf;
-            DWORD size;
             TRACE("Not playing, kickstarting the engine\n");
-            This->write_pos = 0;
-            IDirectSoundBuffer_SetCurrentPosition(This->dsbuffer, 0);
-
-            hr = IDirectSoundBuffer_Lock(This->dsbuffer, 0, 0, (void**)&buf, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
-            if (hr != DS_OK)
-                ERR("Unable to lock sound buffer! (%x)\n", hr);
-            else
-                memset(buf, 0, size);
-            hr = IDirectSoundBuffer_Unlock(This->dsbuffer, buf, size, NULL, 0);
 
             hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING);
             if (FAILED(hr))
                 ERR("Can't play sound buffer (%x)\n", hr);
-            hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, &This->last_play_pos, &This->write_pos);
-            *pPlayPos = This->last_play_pos;
         }
-        else if (SUCCEEDED(hr))
-            hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, pPlayPos, NULL);
+
+        if (SUCCEEDED(hr))
+            hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, pPlayPos, &write_pos);
         if (hr == S_OK)
         {
             DWORD play_pos = *pPlayPos;
@@ -136,10 +126,13 @@ static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPo
                 This->play_loops++;
             This->last_play_pos = play_pos;
 
-            /* If we're really falling behind, kick the play time back */
+            /* If we really fell behind, start at the next possible position
+             * Also happens when just starting playback for the first time,
+             * or when flushing
+             */
             if ((This->play_loops*This->buf_size)+play_pos >=
                 (This->write_loops*This->buf_size)+This->write_pos)
-                This->play_loops--;
+                This->write_pos = write_pos;
 
             if (pRefTime)
             {
@@ -172,7 +165,7 @@ static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *d
     DWORD size2;
     DWORD play_pos,buf_free;
 
-    while (size && This->state == State_Running && !This->pInputPin->flushing) {
+    do {
 
         hr = DSoundRender_GetPos(This, &play_pos, NULL);
         if (hr != DS_OK)
@@ -216,7 +209,7 @@ static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *d
             This->write_pos -= This->buf_size;
             This->write_loops++;
         }
-    }
+    } while (size && This->state == State_Running);
 
     return hr;
 }
@@ -778,6 +771,8 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
     IMediaEventSink* pEventSink;
     HRESULT hr;
 
+    EnterCriticalSection(This->pin.pCritSec);
+
     TRACE("(%p/%p)->()\n", This, iface);
     InputPin_EndOfStream(iface);
 
@@ -797,6 +792,7 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
         hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
         IMediaEventSink_Release(pEventSink);
     }
+    LeaveCriticalSection(This->pin.pCritSec);
 
     return hr;
 }
@@ -806,13 +802,28 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
     InputPin *This = (InputPin *)iface;
     DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
     HRESULT hr;
+    LPBYTE buffer;
+    DWORD size;
 
     TRACE("\n");
-    hr = InputPin_BeginFlush(iface);
 
     EnterCriticalSection(This->pin.pCritSec);
+    hr = InputPin_BeginFlush(iface);
+
     if (pFilter->dsbuffer)
+    {
         IDirectSoundBuffer_Stop(pFilter->dsbuffer);
+
+        /* Force a reset */
+        IDirectSoundBuffer_SetCurrentPosition(pFilter->dsbuffer, 0);
+        pFilter->write_pos = pFilter->last_play_pos = 0;
+        ++pFilter->play_loops;
+        pFilter->write_loops = pFilter->play_loops;
+
+        IDirectSoundBuffer_Lock(pFilter->dsbuffer, 0, 0, (LPVOID *)&buffer, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
+        memset(buffer, 0, size);
+        IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0);
+    }
     LeaveCriticalSection(This->pin.pCritSec);
 
     return hr;




More information about the wine-cvs mailing list