Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtergraph.c | 86 ++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 55c70702e47..6288e3095dd 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -5156,12 +5156,12 @@ static void test_set_notify_flags(void) IMediaEventEx *media_event; struct testfilter filter; LONG_PTR param1, param2; + LONG code, flags; HANDLE event; HWND window; BSTR status; HRESULT hr; ULONG ref; - LONG code; MSG msg;
window = CreateWindowA("static", NULL, WS_OVERLAPPEDWINDOW, @@ -5196,9 +5196,25 @@ static void test_set_notify_flags(void)
while (PeekMessageA(&msg, window, WM_USER, WM_USER, PM_REMOVE));
+ hr = IMediaEventEx_SetNotifyFlags(media_event, 2); + ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + hr = IMediaEventEx_GetNotifyFlags(media_event, NULL); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + flags = 0xdeadbeef; + hr = IMediaEventEx_GetNotifyFlags(media_event, &flags); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!flags, "Got flags %#x\n", flags); + hr = IMediaEventEx_SetNotifyFlags(media_event, AM_MEDIAEVENT_NONOTIFY); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ flags = 0xdeadbeef; + hr = IMediaEventEx_GetNotifyFlags(media_event, &flags); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(flags == AM_MEDIAEVENT_NONOTIFY, "Got flags %#x\n", flags); + todo_wine ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
hr = IMediaEventEx_GetEvent(media_event, &code, ¶m1, ¶m2, 50); @@ -5249,6 +5265,11 @@ static void test_set_notify_flags(void) hr = IMediaEventEx_SetNotifyFlags(media_event, 0); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ flags = 0xdeadbeef; + hr = IMediaEventEx_GetNotifyFlags(media_event, &flags); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!flags, "Got flags %#x\n", flags); + hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaControl_Run(media_control); @@ -5295,6 +5316,8 @@ static void check_events_(unsigned int line, IMediaEventEx *media_event, ++ec_complete_count; if (code == EC_STATUS) ++ec_status_count; + hr = IMediaEventEx_FreeEventParams(media_event, code, param1, param2); + ok(hr == S_OK, "Got hr %#x.\n", hr); } ok(hr == E_ABORT, "Got hr %#x.\n", hr); todo_wine_if(todo) ok_(__FILE__, line)(ec_complete_count == expected_ec_complete_count, @@ -5336,9 +5359,51 @@ static void test_events(void) hr = IMediaEventEx_GetEventHandle(media_event, (OAEVENT *)&event); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ code = 0xdeadbeef; + param1 = 0xdeadbeef; + param2 = 0xdeadbeef; + hr = IMediaEventEx_GetEvent(media_event, &code, ¶m1, ¶m2, 0); + ok(hr == E_ABORT, "Got hr %#x.\n", hr); + ok(!code, "Got code %#x.\n", code); + todo_wine ok(!param1, "Got param1 %#Ix.\n", param1); + todo_wine ok(!param2, "Got param2 %#Ix.\n", param2); + + /* EC_COMPLETE is ignored while in stopped or paused state. */ + + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_COMPLETE, S_OK, + (LONG_PTR)&filter.IBaseFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + check_events(media_event, 0, 2, FALSE); + + hr = IMediaControl_Pause(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_COMPLETE, S_OK, + (LONG_PTR)&filter.IBaseFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + check_events(media_event, 0, 2, FALSE); + hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_events(media_event, 0, 0, FALSE); + + /* Pausing and then running the graph clears pending EC_COMPLETE events. + * This remains true even with default handling canceled. */ + + hr = IMediaEventEx_CancelDefaultHandling(media_event, EC_COMPLETE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaEventSink_Notify(media_event_sink, EC_COMPLETE, S_OK, @@ -5385,6 +5450,25 @@ static void test_events(void)
check_events(media_event, 1, 2, FALSE);
+ hr = IMediaControl_Run(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_COMPLETE, S_OK, + (LONG_PTR)&filter.IBaseFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Pause(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_Run(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + check_events(media_event, 0, 2, TRUE); + + /* GetEvent() resets the event object if there are no events available. */ + SetEvent(event);
hr = IMediaEventEx_GetEvent(media_event, &code, ¶m1, ¶m2, 50);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 8c1cd6232e4..681893a1e11 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -62,7 +62,6 @@ typedef struct { int ring_buffer_size; int msg_tosave; int msg_toget; - CRITICAL_SECTION msg_crst; HANDLE msg_event; /* Signaled for no empty queue */ } EventsQueue;
@@ -75,8 +74,6 @@ static int EventsQueue_Init(EventsQueue* omr) omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event)); ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event));
- InitializeCriticalSection(&omr->msg_crst); - omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst"); return TRUE; }
@@ -84,14 +81,11 @@ static int EventsQueue_Destroy(EventsQueue* omr) { CloseHandle(omr->msg_event); CoTaskMemFree(omr->messages); - omr->msg_crst.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&omr->msg_crst); return TRUE; }
static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt) { - EnterCriticalSection(&omr->msg_crst); if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)) { int old_ring_buffer_size = omr->ring_buffer_size; @@ -114,22 +108,13 @@ static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt) omr->messages[omr->msg_tosave] = *evt; SetEvent(omr->msg_event); omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size; - LeaveCriticalSection(&omr->msg_crst); return TRUE; }
-static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut) +static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt) { - if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0) - return FALSE; - - EnterCriticalSection(&omr->msg_crst); - if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */ - { - LeaveCriticalSection(&omr->msg_crst); return FALSE; - }
*evt = omr->messages[omr->msg_toget]; omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size; @@ -138,7 +123,6 @@ static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut) if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */ ResetEvent(omr->msg_event);
- LeaveCriticalSection(&omr->msg_crst); return TRUE; }
@@ -4786,14 +4770,24 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode
TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout);
- if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout)) + if (WaitForSingleObject(This->evqueue.msg_event, msTimeout)) + { + *lEventCode = 0; + return E_ABORT; + } + + EnterCriticalSection(&This->cs); + + if (EventsQueue_GetEvent(&This->evqueue, &evt)) { *lEventCode = evt.lEventCode; *lParam1 = evt.lParam1; *lParam2 = evt.lParam2; + LeaveCriticalSection(&This->cs); return S_OK; }
+ LeaveCriticalSection(&This->cs); *lEventCode = 0; return E_ABORT; } @@ -5280,8 +5274,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCo
TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2);
- /* We need thread safety here, let's use the events queue's one */ - EnterCriticalSection(&This->evqueue.msg_crst); + EnterCriticalSection(&This->cs);
if ((EventCode == EC_COMPLETE) && This->HandleEcComplete) { @@ -5324,7 +5317,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCo PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); }
- LeaveCriticalSection(&This->evqueue.msg_crst); + LeaveCriticalSection(&This->cs); return S_OK; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 236 +++++++++++++++----------------------- 1 file changed, 93 insertions(+), 143 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 681893a1e11..25aa78433b9 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -49,82 +49,12 @@ typedef struct { int disabled; /* Disabled messages posting */ } WndNotify;
-typedef struct { - LONG lEventCode; /* Event code */ - LONG_PTR lParam1; /* Param1 */ - LONG_PTR lParam2; /* Param2 */ -} Event; - -/* messages ring implementation for queuing events (taken from winmm) */ -#define EVENTS_RING_BUFFER_INCREMENT 64 -typedef struct { - Event* messages; - int ring_buffer_size; - int msg_tosave; - int msg_toget; - HANDLE msg_event; /* Signaled for no empty queue */ -} EventsQueue; - -static int EventsQueue_Init(EventsQueue* omr) -{ - omr->msg_toget = 0; - omr->msg_tosave = 0; - omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL); - omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT; - omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event)); - ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event)); - - return TRUE; -} - -static int EventsQueue_Destroy(EventsQueue* omr) +struct media_event { - CloseHandle(omr->msg_event); - CoTaskMemFree(omr->messages); - return TRUE; -} - -static BOOL EventsQueue_PutEvent(EventsQueue* omr, const Event* evt) -{ - if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)) - { - int old_ring_buffer_size = omr->ring_buffer_size; - omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT; - TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size); - omr->messages = CoTaskMemRealloc(omr->messages, omr->ring_buffer_size * sizeof(Event)); - /* Now we need to rearrange the ring buffer so that the new - buffers just allocated are in between omr->msg_tosave and - omr->msg_toget. - */ - if (omr->msg_tosave < omr->msg_toget) - { - memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]), - &(omr->messages[omr->msg_toget]), - sizeof(Event)*(old_ring_buffer_size - omr->msg_toget) - ); - omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT; - } - } - omr->messages[omr->msg_tosave] = *evt; - SetEvent(omr->msg_event); - omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size; - return TRUE; -} - -static BOOL EventsQueue_GetEvent(EventsQueue* omr, Event* evt) -{ - if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */ - return FALSE; - - *evt = omr->messages[omr->msg_toget]; - omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size; - - /* Mark the buffer as empty if needed */ - if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */ - ResetEvent(omr->msg_event); - - return TRUE; -} + struct list entry; + LONG code; + LONG_PTR param1, param2; +};
#define MAX_ITF_CACHE_ENTRIES 3 typedef struct _ITF_CACHE_ENTRY { @@ -180,7 +110,9 @@ struct filter_graph
IReferenceClock *refClock; IBaseFilter *refClockProvider; - EventsQueue evqueue; + + struct list media_events; + HANDLE media_event_handle; HANDLE hEventCompletion; int CompletionStatus; WndNotify notif; @@ -189,6 +121,7 @@ struct filter_graph int HandleEcComplete; int HandleEcRepaint; int HandleEcClockChanged; + CRITICAL_SECTION cs; ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES]; int nItfCacheEntries; @@ -370,6 +303,26 @@ static HRESULT create_enum_filters(struct filter_graph *graph, struct list *curs return S_OK; }
+static BOOL queue_media_event(struct filter_graph *graph, LONG code, + LONG_PTR param1, LONG_PTR param2) +{ + struct media_event *event; + + if (!(event = malloc(sizeof(*event)))) + return FALSE; + + event->code = code; + event->param1 = param1; + event->param2 = param2; + list_add_tail(&graph->media_events, &event->entry); + + SetEvent(graph->media_event_handle); + if (graph->notif.hWnd) + PostMessageW(graph->notif.hWnd, graph->notif.msg, 0, graph->notif.instance); + + return TRUE; +} + static struct filter_graph *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct filter_graph, IUnknown_inner); @@ -463,7 +416,7 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface) { struct filter_graph *This = impl_from_IUnknown(iface); ULONG ref = InterlockedDecrement(&This->ref); - struct filter *filter, *next; + struct list *cursor;
TRACE("(%p)->(): new ref = %d\n", This, ref);
@@ -474,8 +427,10 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
IMediaControl_Stop(&This->IMediaControl_iface);
- LIST_FOR_EACH_ENTRY_SAFE(filter, next, &This->filters, struct filter, entry) + while ((cursor = list_head(&This->filters))) { + struct filter *filter = LIST_ENTRY(cursor, struct filter, entry); + IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, filter->filter); }
@@ -492,8 +447,16 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
if (This->pSite) IUnknown_Release(This->pSite);
- CloseHandle(This->hEventCompletion); - EventsQueue_Destroy(&This->evqueue); + while ((cursor = list_head(&This->media_events))) + { + struct media_event *event = LIST_ENTRY(cursor, struct media_event, entry); + + list_remove(&event->entry); + free(event); + } + + CloseHandle(This->media_event_handle); + This->cs.DebugInfo->Spare[0] = 0; if (This->message_thread) { @@ -4751,45 +4714,49 @@ static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMembe }
/*** IMediaEvent methods ***/ -static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent) +static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *event) { - struct filter_graph *This = impl_from_IMediaEventEx(iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, hEvent); + struct filter_graph *graph = impl_from_IMediaEventEx(iface);
- *hEvent = (OAEVENT)This->evqueue.msg_event; + TRACE("graph %p, event %p.\n", graph, event);
+ *event = (OAEVENT)graph->media_event_handle; return S_OK; }
-static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1, - LONG_PTR *lParam2, LONG msTimeout) +static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code, + LONG_PTR *param1, LONG_PTR *param2, LONG timeout) { - struct filter_graph *This = impl_from_IMediaEventEx(iface); - Event evt; + struct filter_graph *graph = impl_from_IMediaEventEx(iface); + struct media_event *event; + struct list *entry;
- TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout); + TRACE("graph %p, code %p, param1 %p, param2 %p, timeout %d.\n", graph, code, param1, param2, timeout);
- if (WaitForSingleObject(This->evqueue.msg_event, msTimeout)) - { - *lEventCode = 0; + *code = 0; + + if (WaitForSingleObject(graph->media_event_handle, timeout)) return E_ABORT; - }
- EnterCriticalSection(&This->cs); + EnterCriticalSection(&graph->cs);
- if (EventsQueue_GetEvent(&This->evqueue, &evt)) + if (!(entry = list_head(&graph->media_events))) { - *lEventCode = evt.lEventCode; - *lParam1 = evt.lParam1; - *lParam2 = evt.lParam2; - LeaveCriticalSection(&This->cs); - return S_OK; + LeaveCriticalSection(&graph->cs); + return E_ABORT; } + event = LIST_ENTRY(entry, struct media_event, entry); + list_remove(&event->entry); + *code = event->code; + *param1 = event->param1; + *param2 = event->param2; + free(event);
- LeaveCriticalSection(&This->cs); - *lEventCode = 0; - return E_ABORT; + if (list_empty(&graph->media_events)) + ResetEvent(graph->media_event_handle); + + LeaveCriticalSection(&graph->cs); + return S_OK; }
static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout, @@ -5266,58 +5233,38 @@ static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface) return IUnknown_Release(graph->outer_unk); }
-static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode, - LONG_PTR EventParam1, LONG_PTR EventParam2) +static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code, + LONG_PTR param1, LONG_PTR param2) { - struct filter_graph *This = impl_from_IMediaEventSink(iface); - Event evt; + struct filter_graph *graph = impl_from_IMediaEventSink(iface);
- TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2); + TRACE("graph %p, code %#x, param1 %#Ix, param2 %#Ix.\n", graph, code, param1, param2);
- EnterCriticalSection(&This->cs); + EnterCriticalSection(&graph->cs);
- if ((EventCode == EC_COMPLETE) && This->HandleEcComplete) + if (code == EC_COMPLETE && graph->HandleEcComplete) { - TRACE("Process EC_COMPLETE notification\n"); - if (++This->EcCompleteCount == This->nRenderers) + if (++graph->EcCompleteCount == graph->nRenderers) { - if (!This->notif.disabled) - { - evt.lEventCode = EC_COMPLETE; - evt.lParam1 = S_OK; - evt.lParam2 = 0; - TRACE("Send EC_COMPLETE to app\n"); - EventsQueue_PutEvent(&This->evqueue, &evt); - if (This->notif.hWnd) - { - TRACE("Send Window message\n"); - PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); - } - } + if (graph->notif.disabled) + SetEvent(graph->media_event_handle); else - { - SetEvent(This->evqueue.msg_event); - } - This->CompletionStatus = EC_COMPLETE; - This->got_ec_complete = 1; - SetEvent(This->hEventCompletion); + queue_media_event(graph, EC_COMPLETE, S_OK, 0); + graph->CompletionStatus = EC_COMPLETE; + graph->got_ec_complete = 1; + SetEvent(graph->hEventCompletion); } } - else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint) + else if ((code == EC_REPAINT) && graph->HandleEcRepaint) { - /* FIXME: Not handled yet */ + FIXME("EC_REPAINT is not handled.\n"); } - else if (!This->notif.disabled) + else if (!graph->notif.disabled) { - evt.lEventCode = EventCode; - evt.lParam1 = EventParam1; - evt.lParam2 = EventParam2; - EventsQueue_PutEvent(&This->evqueue, &evt); - if (This->notif.hWnd) - PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); + queue_media_event(graph, code, param1, param2); }
- LeaveCriticalSection(&This->cs); + LeaveCriticalSection(&graph->cs); return S_OK; }
@@ -5625,12 +5572,15 @@ static HRESULT filter_graph_common_create(IUnknown *outer, IUnknown **out, BOOL object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": filter_graph.cs");
object->defaultclock = TRUE; - EventsQueue_Init(&object->evqueue); + + object->media_event_handle = CreateEventW(NULL, TRUE, FALSE, NULL); + list_init(&object->media_events); list_init(&object->filters); object->HandleEcClockChanged = TRUE; object->HandleEcComplete = TRUE; object->HandleEcRepaint = TRUE; object->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0); + object->name_index = 1; object->timeformatseek = TIME_FORMAT_MEDIA_TIME;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 61 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 31 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 25aa78433b9..a060ee840db 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -42,13 +42,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
-typedef struct { - HWND hWnd; /* Target window */ - UINT msg; /* User window message */ - LONG_PTR instance; /* User data */ - int disabled; /* Disabled messages posting */ -} WndNotify; - struct media_event { struct list entry; @@ -113,9 +106,11 @@ struct filter_graph
struct list media_events; HANDLE media_event_handle; + HWND media_event_window; + UINT media_event_message; + LPARAM media_event_lparam; HANDLE hEventCompletion; int CompletionStatus; - WndNotify notif; int nRenderers; int EcCompleteCount; int HandleEcComplete; @@ -141,6 +136,7 @@ struct filter_graph
unsigned int needs_async_run : 1; unsigned int got_ec_complete : 1; + unsigned int media_events_disabled : 1; };
struct enum_filters @@ -317,8 +313,8 @@ static BOOL queue_media_event(struct filter_graph *graph, LONG code, list_add_tail(&graph->media_events, &event->entry);
SetEvent(graph->media_event_handle); - if (graph->notif.hWnd) - PostMessageW(graph->notif.hWnd, graph->notif.msg, 0, graph->notif.instance); + if (graph->media_event_window) + PostMessageW(graph->media_event_window, graph->media_event_message, 0, graph->media_event_lparam);
return TRUE; } @@ -4826,44 +4822,47 @@ static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvC }
/*** IMediaEventEx methods ***/ -static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg, - LONG_PTR lInstanceData) +static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, + OAHWND window, LONG message, LONG_PTR lparam) { - struct filter_graph *This = impl_from_IMediaEventEx(iface); + struct filter_graph *graph = impl_from_IMediaEventEx(iface);
- TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData); + TRACE("graph %p, window %#Ix, message %#x, lparam %#Ix.\n", graph, window, message, lparam);
- This->notif.hWnd = (HWND)hwnd; - This->notif.msg = lMsg; - This->notif.instance = lInstanceData; + graph->media_event_window = (HWND)window; + graph->media_event_message = message; + graph->media_event_lparam = lparam;
return S_OK; }
-static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags) +static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG flags) { - struct filter_graph *This = impl_from_IMediaEventEx(iface); + struct filter_graph *graph = impl_from_IMediaEventEx(iface);
- TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags); + TRACE("graph %p, flags %#x.\n", graph, flags);
- if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1)) - return E_INVALIDARG; + if (flags & ~AM_MEDIAEVENT_NONOTIFY) + { + WARN("Invalid flags %#x, returning E_INVALIDARG.\n", flags); + return E_INVALIDARG; + }
- This->notif.disabled = lNoNotifyFlags; + graph->media_events_disabled = flags;
return S_OK; }
-static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags) +static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *flags) { - struct filter_graph *This = impl_from_IMediaEventEx(iface); + struct filter_graph *graph = impl_from_IMediaEventEx(iface);
- TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags); + TRACE("graph %p, flags %p.\n", graph, flags);
- if (!lplNoNotifyFlags) - return E_POINTER; + if (!flags) + return E_POINTER;
- *lplNoNotifyFlags = This->notif.disabled; + *flags = graph->media_events_disabled;
return S_OK; } @@ -5246,7 +5245,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code, { if (++graph->EcCompleteCount == graph->nRenderers) { - if (graph->notif.disabled) + if (graph->media_events_disabled) SetEvent(graph->media_event_handle); else queue_media_event(graph, EC_COMPLETE, S_OK, 0); @@ -5259,7 +5258,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code, { FIXME("EC_REPAINT is not handled.\n"); } - else if (!graph->notif.disabled) + else if (!graph->media_events_disabled) { queue_media_event(graph, code, param1, param2); }
Based on a patch by Anton Baskanov.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 28 ++++++++++++++++++++-------- dlls/quartz/tests/filtergraph.c | 6 +++--- 2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index a060ee840db..8909ba64024 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -319,6 +319,19 @@ static BOOL queue_media_event(struct filter_graph *graph, LONG code, return TRUE; }
+static void flush_media_events(struct filter_graph *graph) +{ + struct list *cursor; + + while ((cursor = list_head(&graph->media_events))) + { + struct media_event *event = LIST_ENTRY(cursor, struct media_event, entry); + + list_remove(&event->entry); + free(event); + } +} + static struct filter_graph *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct filter_graph, IUnknown_inner); @@ -443,14 +456,7 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
if (This->pSite) IUnknown_Release(This->pSite);
- while ((cursor = list_head(&This->media_events))) - { - struct media_event *event = LIST_ENTRY(cursor, struct media_event, entry); - - list_remove(&event->entry); - free(event); - } - + flush_media_events(This); CloseHandle(This->media_event_handle);
This->cs.DebugInfo->Spare[0] = 0; @@ -4850,6 +4856,12 @@ static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG flags
graph->media_events_disabled = flags;
+ if (flags) + { + flush_media_events(graph); + ResetEvent(graph->media_event_handle); + } + return S_OK; }
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 6288e3095dd..5d22ba410af 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -5215,10 +5215,10 @@ static void test_set_notify_flags(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(flags == AM_MEDIAEVENT_NONOTIFY, "Got flags %#x\n", flags);
- todo_wine ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n"); + ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
hr = IMediaEventEx_GetEvent(media_event, &code, ¶m1, ¶m2, 50); - todo_wine ok(hr == E_ABORT, "Got hr %#x.\n", hr); + ok(hr == E_ABORT, "Got hr %#x.\n", hr);
hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -5282,7 +5282,7 @@ static void test_set_notify_flags(void) hr = IMediaEventEx_SetNotifyFlags(media_event, AM_MEDIAEVENT_NONOTIFY); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n"); + ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
From: Anton Baskanov baskanov@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 4 +--- dlls/quartz/tests/filtergraph.c | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 8909ba64024..131e022b0ba 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -4744,6 +4744,7 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code,
if (!(entry = list_head(&graph->media_events))) { + ResetEvent(graph->media_event_handle); LeaveCriticalSection(&graph->cs); return E_ABORT; } @@ -4754,9 +4755,6 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code, *param2 = event->param2; free(event);
- if (list_empty(&graph->media_events)) - ResetEvent(graph->media_event_handle); - LeaveCriticalSection(&graph->cs); return S_OK; } diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 5d22ba410af..81b13255382 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -5260,7 +5260,7 @@ static void test_set_notify_flags(void) hr = IMediaEventEx_GetEvent(media_event, &code, ¶m1, ¶m2, 50); ok(hr == E_ABORT, "Got hr %#x.\n", hr);
- todo_wine ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n"); + ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
hr = IMediaEventEx_SetNotifyFlags(media_event, 0); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -5474,7 +5474,7 @@ static void test_events(void) hr = IMediaEventEx_GetEvent(media_event, &code, ¶m1, ¶m2, 50); ok(hr == E_ABORT, "Got hr %#x.\n", hr);
- todo_wine ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n"); + ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
Based on a patch by Anton Baskanov.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 12 ++++++++++++ dlls/quartz/tests/filtergraph.c | 22 +++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 131e022b0ba..a8c6cc3391c 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -1690,6 +1690,7 @@ static void update_render_count(struct filter_graph *graph) /* Perform the paused -> running transition. The caller must hold graph->cs. */ static HRESULT graph_start(struct filter_graph *graph, REFERENCE_TIME stream_start) { + struct media_event *event, *next; REFERENCE_TIME stream_stop; struct filter *filter; HRESULT hr = S_OK; @@ -1697,6 +1698,17 @@ static HRESULT graph_start(struct filter_graph *graph, REFERENCE_TIME stream_sta graph->EcCompleteCount = 0; update_render_count(graph);
+ LIST_FOR_EACH_ENTRY_SAFE(event, next, &graph->media_events, struct media_event, entry) + { + if (event->code == EC_COMPLETE) + { + list_remove(&event->entry); + free(event); + } + } + if (list_empty(&graph->media_events)) + ResetEvent(graph->media_event_handle); + 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 81b13255382..4822b65a7a6 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -5249,7 +5249,7 @@ static void test_set_notify_flags(void) hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n"); + ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
hr = IMediaEventSink_Notify(media_event_sink, EC_COMPLETE, S_OK, (LONG_PTR)&filter.IBaseFilter_iface); @@ -5298,9 +5298,9 @@ static void test_set_notify_flags(void) DestroyWindow(window); }
-#define check_events(a, b, c, d) check_events_(__LINE__, a, b, c, d) +#define check_events(a, b, c) check_events_(__LINE__, a, b, c) static void check_events_(unsigned int line, IMediaEventEx *media_event, - int expected_ec_complete_count, int expected_ec_status_count, BOOL todo) + int expected_ec_complete_count, int expected_ec_status_count) { int ec_complete_count = 0; int ec_status_count = 0; @@ -5320,7 +5320,7 @@ static void check_events_(unsigned int line, IMediaEventEx *media_event, ok(hr == S_OK, "Got hr %#x.\n", hr); } ok(hr == E_ABORT, "Got hr %#x.\n", hr); - todo_wine_if(todo) ok_(__FILE__, line)(ec_complete_count == expected_ec_complete_count, + ok_(__FILE__, line)(ec_complete_count == expected_ec_complete_count, "Expected %d EC_COMPLETE events.\n", expected_ec_complete_count); ok_(__FILE__, line)(ec_status_count == expected_ec_status_count, "Expected %d EC_STATUS events.\n", expected_ec_status_count); @@ -5378,7 +5378,7 @@ static void test_events(void) hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 0, 2, FALSE); + check_events(media_event, 0, 2);
hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -5391,12 +5391,12 @@ static void test_events(void) hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 0, 2, FALSE); + check_events(media_event, 0, 2);
hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 0, 0, FALSE); + check_events(media_event, 0, 0);
/* Pausing and then running the graph clears pending EC_COMPLETE events. * This remains true even with default handling canceled. */ @@ -5415,7 +5415,7 @@ static void test_events(void) hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 1, 2, FALSE); + check_events(media_event, 1, 2);
hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -5433,7 +5433,7 @@ static void test_events(void) hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 0, 2, TRUE); + check_events(media_event, 0, 2);
hr = IMediaEventSink_Notify(media_event_sink, EC_STATUS, (LONG_PTR)status, (LONG_PTR)status); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -5448,7 +5448,7 @@ static void test_events(void) hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 1, 2, FALSE); + check_events(media_event, 1, 2);
hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -5465,7 +5465,7 @@ static void test_events(void) hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
- check_events(media_event, 0, 2, TRUE); + check_events(media_event, 0, 2);
/* GetEvent() resets the event object if there are no events available. */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85831
Your paranoid android.
=== w1064 (64 bit report) ===
quartz: filtergraph.c:533: Test failed: expected 524874, got 0
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=85825
Your paranoid android.
=== w1064_2qxl (64 bit report) ===
quartz: filtergraph.c:529: Test failed: didn't get EOS filtergraph.c:533: Test failed: expected f4240, got 0