quartz: Implement MediaControl_GetState.
This allows applications to wait for state transitions to be really
complete. Fixes some xvid crashes.
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 7031c72..c63663d 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -1555,9 +1555,9 @@
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;
IPin* pInputPin;
@@ -1594,7 +1594,7 @@
/* Explore the graph downstream from this pin
* 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). */
- ExploreGraph(pGraph, ppPins[i], FoundFilter);
+ ExploreGraph(pGraph, ppPins[i], FoundFilter, data);
IPin_Release(ppPins[i]);
}
@@ -1602,14 +1602,15 @@
}
TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
- FoundFilter(PinInfo.pFilter);
+ FoundFilter(PinInfo.pFilter, data);
}
if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
return hr;
}
-static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
+static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data)
+{
LONGLONG time = 0;
IReferenceClock *clock = NULL;
@@ -1628,15 +1629,39 @@
return IBaseFilter_Run(pFilter, time);
}
-static HRESULT WINAPI SendPause(IBaseFilter *pFilter) {
+static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data)
+{
return IBaseFilter_Pause(pFilter);
}
-static HRESULT WINAPI SendStop(IBaseFilter *pFilter) {
+static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data)
+{
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);
int i;
IBaseFilter* pfilter;
@@ -1680,10 +1705,10 @@
while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
{
/* Explore the graph downstream from this pin */
- ExploreGraph(This, pPin, FoundFilter);
+ ExploreGraph(This, pPin, FoundFilter, data);
IPin_Release(pPin);
}
- FoundFilter(pfilter);
+ FoundFilter(pfilter, data);
}
IEnumPins_Release(pEnum);
}
@@ -1709,7 +1734,7 @@
}
else This->position = This->start_time = 0;
- SendFilterMessage(iface, SendRun);
+ SendFilterMessage(iface, SendRun, 0);
This->state = State_Running;
LeaveCriticalSection(&This->cs);
return S_FALSE;
@@ -1732,7 +1757,7 @@
This->position += time - This->start_time;
}
- SendFilterMessage(iface, SendPause);
+ SendFilterMessage(iface, SendPause, 0);
This->state = State_Paused;
LeaveCriticalSection(&This->cs);
return S_FALSE;
@@ -1752,8 +1777,8 @@
This->position += time - This->start_time;
}
- if (This->state == State_Running) SendFilterMessage(iface, SendPause);
- SendFilterMessage(iface, SendStop);
+ if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0);
+ SendFilterMessage(iface, SendStop, 0);
This->state = State_Stopped;
LeaveCriticalSection(&This->cs);
return S_OK;
@@ -1763,8 +1788,9 @@
LONG msTimeout,
OAFilterState *pfs) {
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)
return E_POINTER;
@@ -1772,6 +1798,20 @@
EnterCriticalSection(&This->cs);
*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);