quartz: Implement MediaControl_GetState.

This allows applications to wait for state transitions to be really
complete. Fixes some xvid crashes.
This commit is contained in:
Maarten Lankhorst 2008-06-10 18:20:33 +02:00 committed by Alexandre Julliard
parent aaee8a1b0e
commit 29b6dbab80
1 changed files with 55 additions and 15 deletions

View File

@ -1555,9 +1555,9 @@ static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface,
return S_OK; return S_OK;
} }
typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *); typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter) static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
{ {
HRESULT hr; HRESULT hr;
IPin* pInputPin; IPin* pInputPin;
@ -1594,7 +1594,7 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF
/* Explore the graph downstream from this pin /* Explore the graph downstream from this pin
* FIXME: We should prevent exploring from a pin more than once. This can happens when * FIXME: We should prevent exploring from a pin more than once. This can happens when
* several input pins are connected to the same output (a MUX for instance). */ * several input pins are connected to the same output (a MUX for instance). */
ExploreGraph(pGraph, ppPins[i], FoundFilter); ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
IPin_Release(ppPins[i]); IPin_Release(ppPins[i]);
} }
@ -1602,14 +1602,15 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF
} }
TRACE("Doing stuff with filter %p\n", PinInfo.pFilter); TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
FoundFilter(PinInfo.pFilter); FoundFilter(PinInfo.pFilter, data);
} }
if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter); if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
return hr; return hr;
} }
static HRESULT WINAPI SendRun(IBaseFilter *pFilter) { static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
{
LONGLONG time = 0; LONGLONG time = 0;
IReferenceClock *clock = NULL; IReferenceClock *clock = NULL;
@ -1628,15 +1629,39 @@ static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
return IBaseFilter_Run(pFilter, time); return IBaseFilter_Run(pFilter, time);
} }
static HRESULT WINAPI SendPause(IBaseFilter *pFilter) { static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
{
return IBaseFilter_Pause(pFilter); return IBaseFilter_Pause(pFilter);
} }
static HRESULT WINAPI SendStop(IBaseFilter *pFilter) { static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
{
return IBaseFilter_Stop(pFilter); return IBaseFilter_Stop(pFilter);
} }
static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter) { static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
{
FILTER_STATE state;
DWORD time_end = data;
DWORD time_now = GetTickCount();
LONG wait;
if (time_end == INFINITE)
{
wait = INFINITE;
}
else if (time_end > time_now)
{
wait = time_end - time_now;
}
else
wait = 0;
return IBaseFilter_GetState(pFilter, wait, &state);
}
static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter, DWORD_PTR data) {
ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
int i; int i;
IBaseFilter* pfilter; IBaseFilter* pfilter;
@ -1680,10 +1705,10 @@ static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter
while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK) while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
{ {
/* Explore the graph downstream from this pin */ /* Explore the graph downstream from this pin */
ExploreGraph(This, pPin, FoundFilter); ExploreGraph(This, pPin, FoundFilter, data);
IPin_Release(pPin); IPin_Release(pPin);
} }
FoundFilter(pfilter); FoundFilter(pfilter, data);
} }
IEnumPins_Release(pEnum); IEnumPins_Release(pEnum);
} }
@ -1709,7 +1734,7 @@ static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
} }
else This->position = This->start_time = 0; else This->position = This->start_time = 0;
SendFilterMessage(iface, SendRun); SendFilterMessage(iface, SendRun, 0);
This->state = State_Running; This->state = State_Running;
LeaveCriticalSection(&This->cs); LeaveCriticalSection(&This->cs);
return S_FALSE; return S_FALSE;
@ -1732,7 +1757,7 @@ static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) {
This->position += time - This->start_time; This->position += time - This->start_time;
} }
SendFilterMessage(iface, SendPause); SendFilterMessage(iface, SendPause, 0);
This->state = State_Paused; This->state = State_Paused;
LeaveCriticalSection(&This->cs); LeaveCriticalSection(&This->cs);
return S_FALSE; return S_FALSE;
@ -1752,8 +1777,8 @@ static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) {
This->position += time - This->start_time; This->position += time - This->start_time;
} }
if (This->state == State_Running) SendFilterMessage(iface, SendPause); if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0);
SendFilterMessage(iface, SendStop); SendFilterMessage(iface, SendStop, 0);
This->state = State_Stopped; This->state = State_Stopped;
LeaveCriticalSection(&This->cs); LeaveCriticalSection(&This->cs);
return S_OK; return S_OK;
@ -1763,8 +1788,9 @@ static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
LONG msTimeout, LONG msTimeout,
OAFilterState *pfs) { OAFilterState *pfs) {
ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
DWORD end;
TRACE("(%p/%p)->(%d, %p): semi-stub !!!\n", This, iface, msTimeout, pfs); TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
if (!pfs) if (!pfs)
return E_POINTER; return E_POINTER;
@ -1772,6 +1798,20 @@ static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface,
EnterCriticalSection(&This->cs); EnterCriticalSection(&This->cs);
*pfs = This->state; *pfs = This->state;
if (msTimeout > 0)
{
end = GetTickCount() + msTimeout;
}
else if (msTimeout < 0)
{
end = INFINITE;
}
else
{
end = 0;
}
if (end)
SendFilterMessage(iface, SendGetState, end);
LeaveCriticalSection(&This->cs); LeaveCriticalSection(&This->cs);