Commit b6b67f69 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Alexandre Julliard

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

parent 620d7836
...@@ -73,6 +73,8 @@ typedef struct DSoundRenderImpl ...@@ -73,6 +73,8 @@ typedef struct DSoundRenderImpl
REFERENCE_TIME play_time; REFERENCE_TIME play_time;
MediaSeekingImpl mediaSeeking; MediaSeekingImpl mediaSeeking;
HANDLE state_change, blocked;
long volume; long volume;
long pan; long pan;
} DSoundRenderImpl; } DSoundRenderImpl;
...@@ -246,6 +248,8 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) ...@@ -246,6 +248,8 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
if (This->state == State_Stopped) if (This->state == State_Stopped)
return VFW_E_WRONG_STATE; return VFW_E_WRONG_STATE;
SetEvent(This->state_change);
hr = IMediaSample_GetPointer(pSample, &pbSrcStream); hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr)) if (FAILED(hr))
{ {
...@@ -270,7 +274,19 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) ...@@ -270,7 +274,19 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
} }
if (This->state == State_Paused) if (This->state == State_Paused)
{
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; return S_OK;
}
}
cbSrcStream = IMediaSample_GetActualDataLength(pSample); cbSrcStream = IMediaSample_GetActualDataLength(pSample);
TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream); TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream);
...@@ -359,6 +375,15 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) ...@@ -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); MediaSeekingImpl_Init((IBaseFilter*)pDSoundRender, sound_mod_stop, sound_mod_start, sound_mod_rate, &pDSoundRender->mediaSeeking, &pDSoundRender->csFilter);
pDSoundRender->mediaSeeking.lpVtbl = &IMediaSeeking_Vtbl; 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; *ppv = (LPVOID)pDSoundRender;
} }
else else
...@@ -453,6 +478,9 @@ static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface) ...@@ -453,6 +478,9 @@ static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface)
This->csFilter.DebugInfo->Spare[0] = 0; This->csFilter.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csFilter); DeleteCriticalSection(&This->csFilter);
CloseHandle(This->state_change);
CloseHandle(This->blocked);
TRACE("Destroying Audio Renderer\n"); TRACE("Destroying Audio Renderer\n");
CoTaskMemFree(This); CoTaskMemFree(This);
...@@ -497,6 +525,10 @@ static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface) ...@@ -497,6 +525,10 @@ static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface)
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
This->state = State_Stopped; This->state = State_Stopped;
/* Complete our transition */
SetEvent(This->state_change);
SetEvent(This->blocked);
} }
LeaveCriticalSection(&This->csFilter); LeaveCriticalSection(&This->csFilter);
...@@ -511,10 +543,13 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) ...@@ -511,10 +543,13 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
TRACE("(%p/%p)->()\n", This, iface); TRACE("(%p/%p)->()\n", This, iface);
EnterCriticalSection(&This->csFilter); EnterCriticalSection(&This->csFilter);
if (This->state != State_Paused)
{ {
DWORD state = 0; DWORD state = 0;
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
This->pInputPin->end_of_stream = 0; This->pInputPin->end_of_stream = 0;
}
if (This->dsbuffer) if (This->dsbuffer)
{ {
...@@ -527,6 +562,9 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) ...@@ -527,6 +562,9 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
This->state = State_Paused; This->state = State_Paused;
ResetEvent(This->blocked);
ResetEvent(This->state_change);
} }
LeaveCriticalSection(&This->csFilter); LeaveCriticalSection(&This->csFilter);
...@@ -543,9 +581,19 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar ...@@ -543,9 +581,19 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar
EnterCriticalSection(&This->csFilter); EnterCriticalSection(&This->csFilter);
{ {
This->rtStreamStart = tStart; This->rtStreamStart = tStart;
This->state = State_Running; 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->pInputPin->end_of_stream = 0;
} }
This->state = State_Running;
}
LeaveCriticalSection(&This->csFilter); LeaveCriticalSection(&This->csFilter);
return hr; return hr;
...@@ -553,10 +601,16 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar ...@@ -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) static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{ {
HRESULT hr;
DSoundRenderImpl *This = (DSoundRenderImpl *)iface; DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); 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); EnterCriticalSection(&This->csFilter);
{ {
*pState = This->state; *pState = This->state;
...@@ -866,6 +920,27 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface) ...@@ -866,6 +920,27 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
memset(buffer, 0, size); memset(buffer, 0, size);
IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0); 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); LeaveCriticalSection(This->pin.pCritSec);
return hr; return hr;
...@@ -889,7 +964,7 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl = ...@@ -889,7 +964,7 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl =
IPinImpl_QueryInternalConnections, IPinImpl_QueryInternalConnections,
DSoundRender_InputPin_EndOfStream, DSoundRender_InputPin_EndOfStream,
DSoundRender_InputPin_BeginFlush, DSoundRender_InputPin_BeginFlush,
InputPin_EndFlush, DSoundRender_InputPin_EndFlush,
InputPin_NewSegment InputPin_NewSegment
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment