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