diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 9b375949c90..4371a36b581 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -199,6 +199,8 @@ typedef struct _IFilterGraphImpl { BOOL bUnkOuterValid; BOOL bAggregatable; GUID timeformatseek; + LONGLONG start_time; + LONGLONG position; } IFilterGraphImpl; static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This, @@ -1517,7 +1519,7 @@ static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter /* Explorer the graph from source filters to renderers, determine renderers * number and run filters from renderers to source filters */ - This->nRenderers = 0; + This->nRenderers = 0; ResetEvent(This->hEventCompletion); for(i = 0; i < This->nFilters; i++) @@ -1567,6 +1569,13 @@ static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) { if (This->state == State_Running) return S_OK; EnterCriticalSection(&This->cs); + if (This->refClock) + { + IReferenceClock_GetTime(This->refClock, &This->start_time); + This->start_time += 500000; + } + else This->position = This->start_time = 0; + SendFilterMessage(iface, SendRun); This->state = State_Running; LeaveCriticalSection(&This->cs); @@ -1580,6 +1589,13 @@ static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) { if (This->state == State_Paused) return S_OK; EnterCriticalSection(&This->cs); + if (This->state == State_Running && This->refClock) + { + LONGLONG time = This->start_time; + IReferenceClock_GetTime(This->refClock, &time); + This->position += time - This->start_time; + } + SendFilterMessage(iface, SendPause); This->state = State_Paused; LeaveCriticalSection(&This->cs); @@ -1593,6 +1609,13 @@ static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) { if (This->state == State_Stopped) return S_OK; EnterCriticalSection(&This->cs); + if (This->state == State_Running && This->refClock) + { + LONGLONG time = This->start_time; + IReferenceClock_GetTime(This->refClock, &time); + This->position += time - This->start_time; + } + if (This->state == State_Running) SendFilterMessage(iface, SendPause); SendFilterMessage(iface, SendStop); This->state = State_Stopped; @@ -1952,8 +1975,23 @@ static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent) { ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); + LONGLONG time = 0; - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pCurrent); + if (!pCurrent) + return E_POINTER; + + if (This->state == State_Running && This->refClock) + { + IReferenceClock_GetTime(This->refClock, &time); + if (time) + time += This->position - This->start_time; + if (time < This->position) + time = This->position; + *pCurrent = time; + } + else + *pCurrent = This->position; + TRACE("Time: %lld.%03lld\n", *pCurrent / 10000000, (*pCurrent / 10000)%1000); return S_OK; } @@ -4933,6 +4971,7 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs"); fimpl->nItfCacheEntries = 0; memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID)); + fimpl->start_time = fimpl->position = 0; hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2); if (FAILED(hr)) { diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 2a2a806169a..efe12fce41c 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -172,6 +172,42 @@ static void test_graph_builder_addfilter(void) hr = IGraphBuilder_AddFilter(pgraph, pF, NULL); ok(hr == S_OK, "IGraphBuilder_AddFilter returned: %x\n", hr); + IMediaFilter_Release(pF); +} + +static void test_mediacontrol(void) +{ + HRESULT hr; + LONGLONG pos = 0xdeadbeef; + IMediaSeeking *seeking = NULL; + IMediaFilter *filter = NULL; + + IFilterGraph2_SetDefaultSyncSource(pgraph); + hr = IFilterGraph2_QueryInterface(pgraph, &IID_IMediaSeeking, (void**) &seeking); + ok(hr == S_OK, "QueryInterface IMediaControl failed: %08x\n", hr); + if (FAILED(hr)) + return; + + hr = IFilterGraph2_QueryInterface(pgraph, &IID_IMediaFilter, (void**) &filter); + ok(hr == S_OK, "QueryInterface IMediaFilter failed: %08x\n", hr); + if (FAILED(hr)) + { + IUnknown_Release(seeking); + return; + } + + hr = IMediaSeeking_GetCurrentPosition(seeking, &pos); + ok(hr == S_OK, "GetCurrentPosition failed: %08x\n", hr); + ok(pos == 0, "Position != 0 (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos); + + IMediaFilter_SetSyncSource(filter, NULL); + pos = 0xdeadbeef; + hr = IMediaSeeking_GetCurrentPosition(seeking, &pos); + ok(hr == S_OK, "GetCurrentPosition failed: %08x\n", hr); + ok(pos == 0, "Position != 0 (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos); + + IUnknown_Release(seeking); + IUnknown_Release(filter); releasefiltergraph(); } @@ -195,5 +231,6 @@ START_TEST(filtergraph) test_render_run(); test_graph_builder(); test_graph_builder_addfilter(); + test_mediacontrol(); test_filter_graph2(); }