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

This commit is contained in:
Maarten Lankhorst 2008-07-04 00:09:07 -07:00 committed by Alexandre Julliard
parent 620d783680
commit b6b67f698a
1 changed files with 78 additions and 3 deletions

View File

@ -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
};