From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/winegstreamer/media_source.c | 92 +++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 8dc8145b60f..88056b27c5d 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -174,12 +174,15 @@ struct media_source IMFGetService IMFGetService_iface; IMFRateSupport IMFRateSupport_iface; IMFRateControl IMFRateControl_iface; + IMFMediaShutdownNotify IMFMediaShutdownNotify_iface; IMFAsyncCallback async_commands_callback; LONG ref; DWORD async_commands_queue; IMFMediaEventQueue *event_queue; IMFByteStream *byte_stream;
+ IMFAsyncResult *shutdown_result; + CRITICAL_SECTION cs;
UINT64 file_size; @@ -229,6 +232,11 @@ static inline struct media_source *impl_from_IMFRateControl(IMFRateControl *ifac return CONTAINING_RECORD(iface, struct media_source, IMFRateControl_iface); }
+static inline struct media_source *impl_from_IMFMediaShutdownNotify(IMFMediaShutdownNotify *iface) +{ + return CONTAINING_RECORD(iface, struct media_source, IMFMediaShutdownNotify_iface); +} + static inline struct media_source *impl_from_async_commands_callback_IMFAsyncCallback(IMFAsyncCallback *iface) { return CONTAINING_RECORD(iface, struct media_source, async_commands_callback); @@ -1315,6 +1323,76 @@ static const IMFRateControlVtbl media_source_rate_control_vtbl = media_source_rate_control_GetRate, };
+static void media_source_release_shutdown_callback(struct media_source *source) +{ + if (source->shutdown_result) + IMFAsyncResult_Release(source->shutdown_result); + source->shutdown_result = NULL; +} + +static HRESULT WINAPI media_source_shutdown_notify_QueryInterface(IMFMediaShutdownNotify *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFMediaShutdownNotify) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_source_shutdown_notify_AddRef(IMFMediaShutdownNotify *iface) +{ + struct media_source *source = impl_from_IMFMediaShutdownNotify(iface); + return IMFMediaSource_AddRef(&source->IMFMediaSource_iface); +} + +static ULONG WINAPI media_source_shutdown_notify_Release(IMFMediaShutdownNotify *iface) +{ + struct media_source *source = impl_from_IMFMediaShutdownNotify(iface); + return IMFMediaSource_Release(&source->IMFMediaSource_iface); +} + +static HRESULT WINAPI media_source_shutdown_notify_set_notification_callback(IMFMediaShutdownNotify *iface, + IMFAsyncCallback *callback, IUnknown *state) +{ + struct media_source *source = impl_from_IMFMediaShutdownNotify(iface); + IMFAsyncResult *result = NULL; + HRESULT hr = S_OK; + + EnterCriticalSection(&source->cs); + + if (source->state == SOURCE_SHUTDOWN) + hr = MF_E_SHUTDOWN; + else + { + if (callback && FAILED(hr = MFCreateAsyncResult(NULL, callback, state, &result))) + { + LeaveCriticalSection(&source->cs); + return hr; + } + + media_source_release_shutdown_callback(source); + source->shutdown_result = result; + } + + LeaveCriticalSection(&source->cs); + + return hr; +} + +static const IMFMediaShutdownNotifyVtbl media_source_shutdown_notify_vtbl = +{ + media_source_shutdown_notify_QueryInterface, + media_source_shutdown_notify_AddRef, + media_source_shutdown_notify_Release, + media_source_shutdown_notify_set_notification_callback, +}; + static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out) { struct media_source *source = impl_from_IMFMediaSource(iface); @@ -1331,6 +1409,10 @@ static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID { *out = &source->IMFGetService_iface; } + else if (IsEqualIID(riid, &IID_IMFMediaShutdownNotify)) + { + *out = &source->IMFMediaShutdownNotify_iface; + } else { FIXME("%s, %p.\n", debugstr_guid(riid), out); @@ -1361,6 +1443,7 @@ static ULONG WINAPI media_source_Release(IMFMediaSource *iface)
if (!ref) { + media_source_release_shutdown_callback(source); IMFMediaSource_Shutdown(iface); IMFMediaEventQueue_Release(source->event_queue); IMFByteStream_Release(source->byte_stream); @@ -1543,6 +1626,7 @@ static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface) static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface) { struct media_source *source = impl_from_IMFMediaSource(iface); + HRESULT hr;
TRACE("%p.\n", iface);
@@ -1575,6 +1659,13 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface) free(source->descriptors); free(source->streams);
+ if (source->shutdown_result) + { + if (FAILED(hr = MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_STANDARD, source->shutdown_result))) + WARN("Failed to put shutdown notification, hr %#lx.\n", hr); + media_source_release_shutdown_callback(source); + } + LeaveCriticalSection(&source->cs);
MFUnlockWorkQueue(source->async_commands_queue); @@ -1633,6 +1724,7 @@ static HRESULT media_source_create(struct object_context *context, IMFMediaSourc object->IMFGetService_iface.lpVtbl = &media_source_get_service_vtbl; object->IMFRateSupport_iface.lpVtbl = &media_source_rate_support_vtbl; object->IMFRateControl_iface.lpVtbl = &media_source_rate_control_vtbl; + object->IMFMediaShutdownNotify_iface.lpVtbl = &media_source_shutdown_notify_vtbl; object->async_commands_callback.lpVtbl = &source_async_commands_callback_vtbl; object->ref = 1; object->byte_stream = context->stream;