[PATCH 0/2] MR10458: quartz: Reset the completion event on paused -> running transition.
Otherwise, `WaitForCompletion` method doesn't block and returns immediately after seeking. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10458
From: Akihiro Sagawa <sagawa.aki@gmail.com> --- dlls/quartz/tests/filtergraph.c | 75 +++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index a70601060c5..5d5757176c1 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -5989,6 +5989,80 @@ static void test_event_dispatch(void) ok(!ref, "Got outstanding refcount %ld.\n", ref); } +static void test_event_completion(void) +{ + WCHAR *filename = load_resource(L"test_32bpp.avi"); + IFilterGraph2 *graph = create_graph(); + IMediaControl *control; + IMediaSeeking *seeking; + IMediaEvent *event; + LONGLONG pos; + HRESULT hr; + ULONG ref; + LONG code; + BOOL ret; + + hr = IFilterGraph2_RenderFile(graph, filename, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaSeeking, (void **)&seeking); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&event); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaEvent_WaitForCompletion(event, 0, &code); + ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr); + + /* play to 200ms */ + pos = 200 * 10000; + hr = IMediaSeeking_SetPositions(seeking, NULL, AM_SEEKING_NoPositioning, + &pos, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Run(control); + ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); + + code = 0xdeadbeef; + hr = IMediaEvent_WaitForCompletion(event, 500, &code); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(code == EC_COMPLETE, "Got %ld.\n", code); + + hr = IMediaEvent_WaitForCompletion(event, 0, &code); + todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr); + + /* seek to beginning */ + pos = 0; + hr = IMediaSeeking_SetPositions(seeking, &pos, AM_SEEKING_AbsolutePositioning, + NULL, AM_SEEKING_NoPositioning); + ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); + + hr = IMediaEvent_WaitForCompletion(event, 0, &code); + todo_wine ok(hr == E_ABORT, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Pause(control); + ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); + + hr = IMediaEvent_WaitForCompletion(event, 0, &code); + ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr); + + hr = IMediaControl_Run(control); + ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); + + hr = IMediaEvent_WaitForCompletion(event, 0, &code); + todo_wine ok(hr == E_ABORT, "Got hr %#lx.\n", hr); + + IMediaEvent_Release(event); + IMediaSeeking_Release(seeking); + IMediaControl_Release(control); + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %lu.\n", GetLastError()); +} + START_TEST(filtergraph) { CoInitializeEx(NULL, COINIT_MULTITHREADED); @@ -6018,6 +6092,7 @@ START_TEST(filtergraph) test_set_notify_flags(); test_events(); test_event_dispatch(); + test_event_completion(); CoUninitialize(); test_render_with_multithread(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10458
From: Akihiro Sagawa <sagawa.aki@gmail.com> Otherwise, WaitForCompletion method doesn't block and returns immediately after seeking. --- dlls/quartz/filtergraph.c | 1 + dlls/quartz/tests/filtergraph.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 17e5bb1c5b3..1fd82ca6be6 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -1791,6 +1791,7 @@ static HRESULT graph_start(struct filter_graph *graph, REFERENCE_TIME stream_sta } if (list_empty(&graph->media_events)) ResetEvent(graph->media_event_handle); + ResetEvent(graph->hEventCompletion); if (graph->defaultclock && !graph->refClock) IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface); diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 5d5757176c1..921ab639f44 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -6039,7 +6039,7 @@ static void test_event_completion(void) ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); hr = IMediaEvent_WaitForCompletion(event, 0, &code); - todo_wine ok(hr == E_ABORT, "Got hr %#lx.\n", hr); + ok(hr == E_ABORT, "Got hr %#lx.\n", hr); hr = IMediaControl_Pause(control); ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); @@ -6051,7 +6051,7 @@ static void test_event_completion(void) ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); hr = IMediaEvent_WaitForCompletion(event, 0, &code); - todo_wine ok(hr == E_ABORT, "Got hr %#lx.\n", hr); + ok(hr == E_ABORT, "Got hr %#lx.\n", hr); IMediaEvent_Release(event); IMediaSeeking_Release(seeking); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10458
If we're resetting the event on paused->running, then the seek is irrelevant, and the test would be more convincing without it. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10458#note_134381
On Sun Apr 5 13:01:07 2026 +0000, Elizabeth Figura wrote:
If we're resetting the event on paused->running, then the seek is irrelevant, and the test would be more convincing without it. Thanks for the comment. I'll try a different approach.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10458#note_135063
On Sun Apr 5 13:01:07 2026 +0000, Akihiro Sagawa wrote:
Thanks for the comment. I'll try a different approach. I don't think anything needs to be fundamentally changed, just rather you could remove the seek from the test. Or does that make it fail?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10458#note_135154
On Mon Apr 6 18:37:09 2026 +0000, Elizabeth Figura wrote:
I don't think anything needs to be fundamentally changed, just rather you could remove the seek from the test. Or does that make it fail? Without seeking, the graph position is not updated. As a result, when calling `Run` immediately after `Pause`, the renderer filter emits `EC_COMPLETE` right away, which prevents us from reliably checking whether the event has been reset.
I'll add the test at the end of `test_events()` where `testfilter` does not handle `EC_COMPLETE`. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10458#note_135295
participants (3)
-
Akihiro Sagawa -
Akihiro Sagawa (@sgwaki) -
Elizabeth Figura (@zfigura)