From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/winegstreamer/media_source.c | 94 +++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 8dc8145b60f..16307a6fa87 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -174,12 +174,16 @@ 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;
+ IMFAsyncCallback *shutdown_callback; + IUnknown *shutdown_state; + CRITICAL_SECTION cs;
UINT64 file_size; @@ -229,6 +233,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 +1324,77 @@ 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_callback) + IMFAsyncCallback_Release(source->shutdown_callback); + if (source->shutdown_state) + IUnknown_Release(source->shutdown_state); + + source->shutdown_callback = NULL; + source->shutdown_state = 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 media_source_shutdown_notify_set_notification_callback(IMFMediaShutdownNotify *iface, + IMFAsyncCallback *callback, IUnknown *state) +{ + struct media_source *source = impl_from_IMFMediaShutdownNotify(iface); + HRESULT hr = S_OK; + + EnterCriticalSection(&source->cs); + + if (source->state == SOURCE_SHUTDOWN) + hr = MF_E_SHUTDOWN; + else + { + media_source_release_shutdown_callback(source); + source->shutdown_callback = callback; + IMFAsyncCallback_AddRef(callback); + source->shutdown_state = state; + if (state) + IUnknown_AddRef(state); + } + + 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 +1411,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 +1445,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 +1628,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 +1661,13 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface) free(source->descriptors); free(source->streams);
+ if (source->shutdown_callback) + { + if (FAILED(hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, source->shutdown_callback, source->shutdown_state))) + 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 +1726,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;