Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index 0a953dde10f..cef44c8b7ce 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -50,6 +50,7 @@ struct media_item LONG refcount; IMFPMediaPlayer *player; IMFMediaSource *source; + IMFPresentationDescriptor *pd; DWORD_PTR user_data; };
@@ -124,6 +125,8 @@ static ULONG WINAPI media_item_Release(IMFPMediaItem *iface) IMFPMediaPlayer_Release(item->player); if (item->source) IMFMediaSource_Release(item->source); + if (item->pd) + IMFPresentationDescriptor_Release(item->pd); heap_free(item); }
@@ -328,7 +331,24 @@ static HRESULT create_media_item(IMFPMediaPlayer *player, DWORD_PTR user_data, s
static HRESULT media_item_set_source(struct media_item *item, IUnknown *object) { - return IUnknown_QueryInterface(object, &IID_IMFMediaSource, (void **)&item->source); + IMFPresentationDescriptor *pd; + IMFMediaSource *source; + HRESULT hr; + + if (FAILED(hr = IUnknown_QueryInterface(object, &IID_IMFMediaSource, (void **)&source))) + return hr; + + if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd))) + { + WARN("Failed to get presentation descriptor, hr %#x.\n", hr); + IMFMediaSource_Release(source); + return hr; + } + + item->source = source; + item->pd = pd; + + return hr; }
static HRESULT WINAPI media_player_QueryInterface(IMFPMediaPlayer *iface, REFIID riid, void **obj)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 49 +++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 12 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index cef44c8b7ce..bc9e04c91b7 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -229,39 +229,64 @@ static HRESULT WINAPI media_item_GetDuration(IMFPMediaItem *iface, REFGUID forma
static HRESULT WINAPI media_item_GetNumberOfStreams(IMFPMediaItem *iface, DWORD *count) { - FIXME("%p, %p.\n", iface, count); + struct media_item *item = impl_from_IMFPMediaItem(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, count); + + return IMFPresentationDescriptor_GetStreamDescriptorCount(item->pd, count); }
-static HRESULT WINAPI media_item_GetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL *enabled) +static HRESULT WINAPI media_item_GetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL *selected) { - FIXME("%p, %u, %p.\n", iface, index, enabled); + struct media_item *item = impl_from_IMFPMediaItem(iface); + IMFStreamDescriptor *sd; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, index, selected); + + if (SUCCEEDED(hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(item->pd, index, selected, &sd))) + IMFStreamDescriptor_Release(sd); + + return hr; }
-static HRESULT WINAPI media_item_SetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL enabled) +static HRESULT WINAPI media_item_SetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL select) { - FIXME("%p, %u, %d.\n", iface, index, enabled); + struct media_item *item = impl_from_IMFPMediaItem(iface);
- return E_NOTIMPL; + TRACE("%p, %u, %d.\n", iface, index, select); + + return select ? IMFPresentationDescriptor_SelectStream(item->pd, index) : + IMFPresentationDescriptor_DeselectStream(item->pd, index); }
static HRESULT WINAPI media_item_GetStreamAttribute(IMFPMediaItem *iface, DWORD index, REFGUID key, PROPVARIANT *value) { - FIXME("%p, %u, %s, %p.\n", iface, index, debugstr_guid(key), value); + struct media_item *item = impl_from_IMFPMediaItem(iface); + IMFStreamDescriptor *sd; + BOOL selected; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %u, %s, %p.\n", iface, index, debugstr_guid(key), value); + + if (SUCCEEDED(hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(item->pd, index, &selected, &sd))) + { + hr = IMFStreamDescriptor_GetItem(sd, key, value); + IMFStreamDescriptor_Release(sd); + } + + return hr; }
static HRESULT WINAPI media_item_GetPresentationAttribute(IMFPMediaItem *iface, REFGUID key, PROPVARIANT *value) { - FIXME("%p, %s, %p.\n", iface, debugstr_guid(key), value); + struct media_item *item = impl_from_IMFPMediaItem(iface);
- return E_NOTIMPL; + TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value); + + return IMFPresentationDescriptor_GetItem(item->pd, key, value); }
static HRESULT WINAPI media_item_GetCharacteristics(IMFPMediaItem *iface, MFP_MEDIAITEM_CHARACTERISTICS *flags)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/Makefile.in | 2 +- dlls/mfplay/player.c | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplay/Makefile.in b/dlls/mfplay/Makefile.in index 91a8e5cc5a6..8f0fb61fe6f 100644 --- a/dlls/mfplay/Makefile.in +++ b/dlls/mfplay/Makefile.in @@ -1,6 +1,6 @@ MODULE = mfplay.dll IMPORTLIB = mfplay -IMPORTS = mfplat uuid mfuuid +IMPORTS = mfplat mf uuid mfuuid
EXTRADLLFLAGS = -mno-cygwin -Wb,--prefer-native
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index bc9e04c91b7..854698774a6 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -215,9 +215,13 @@ static HRESULT WINAPI media_item_HasAudio(IMFPMediaItem *iface, BOOL *has_audio,
static HRESULT WINAPI media_item_IsProtected(IMFPMediaItem *iface, BOOL *protected) { - FIXME("%p, %p.\n", iface, protected); + struct media_item *item = impl_from_IMFPMediaItem(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, protected); + + *protected = MFRequireProtectedEnvironment(item->pd) == S_OK; + + return S_OK; }
static HRESULT WINAPI media_item_GetDuration(IMFPMediaItem *iface, REFGUID format, PROPVARIANT *value)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index 854698774a6..5a85d9f0505 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -295,9 +295,20 @@ static HRESULT WINAPI media_item_GetPresentationAttribute(IMFPMediaItem *iface,
static HRESULT WINAPI media_item_GetCharacteristics(IMFPMediaItem *iface, MFP_MEDIAITEM_CHARACTERISTICS *flags) { - FIXME("%p, %p.\n", iface, flags); + struct media_item *item = impl_from_IMFPMediaItem(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, flags); + + *flags = 0; + + if (SUCCEEDED(hr = IMFMediaSource_GetCharacteristics(item->source, flags))) + { + *flags &= (MFP_MEDIAITEM_IS_LIVE | MFP_MEDIAITEM_CAN_SEEK | + MFP_MEDIAITEM_CAN_PAUSE | MFP_MEDIAITEM_HAS_SLOW_SEEK); + } + + return hr; }
static HRESULT WINAPI media_item_SetStreamSink(IMFPMediaItem *iface, DWORD index, IUnknown *sink)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/mfplay.idl | 104 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+)
diff --git a/include/mfplay.idl b/include/mfplay.idl index 1a20a6b8900..f130ce12287 100644 --- a/include/mfplay.idl +++ b/include/mfplay.idl @@ -20,6 +20,8 @@ import "unknwn.idl"; import "propsys.idl"; import "evr.idl";
+interface IMFNetCredential; + typedef [v1_enum] enum _MFP_CREATION_OPTIONS { MFP_OPTION_NONE = 0, @@ -64,6 +66,18 @@ typedef [v1_enum] enum _MFP_MEDIAITEM_CHARACTERISTICS MFP_MEDIAITEM_HAS_SLOW_SEEK = 0x00000008, } _MFP_MEDIAITEM_CHARACTERISTICS;
+typedef UINT32 MFP_CREDENTIAL_FLAGS; + +typedef [v1_enum] enum _MFP_CREDENTIAL_FLAGS +{ + MFP_CREDENTIAL_PROMPT = 0x00000001, + MFP_CREDENTIAL_SAVE = 0x00000002, + MFP_CREDENTIAL_DO_NOT_CACHE = 0x00000004, + MFP_CREDENTIAL_CLEAR_TEXT = 0x00000008, + MFP_CREDENTIAL_PROXY = 0x00000010, + MFP_CREDENTIAL_LOGGED_ON_USER = 0x00000020, +} _MFP_CREDENTIAL_FLAGS; + interface IMFPMediaPlayer; interface IMFPMediaItem;
@@ -76,6 +90,96 @@ typedef struct MFP_EVENT_HEADER IPropertyStore *pPropertyStore; } MFP_EVENT_HEADER;
+typedef struct MFP_PLAY_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_PLAY_EVENT; + +typedef struct MFP_PAUSE_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_PAUSE_EVENT; + +typedef struct MFP_STOP_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_STOP_EVENT; + +typedef struct MFP_POSITION_SET_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_POSITION_SET_EVENT; + +typedef struct MFP_RATE_SET_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; + float flRate; +} MFP_RATE_SET_EVENT; + +typedef struct MFP_MEDIAITEM_CREATED_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; + DWORD_PTR dwUserData; +} MFP_MEDIAITEM_CREATED_EVENT; + +typedef struct MFP_MEDIAITEM_SET_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_MEDIAITEM_SET_EVENT; + +typedef struct MFP_FRAME_STEP_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_FRAME_STEP_EVENT; + +typedef struct MFP_MEDIAITEM_CLEARED_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_MEDIAITEM_CLEARED_EVENT; + +typedef struct MFP_MF_EVENT +{ + MFP_EVENT_HEADER header; + MediaEventType MFEventType; + IMFMediaEvent *pMFMediaEvent; + IMFPMediaItem *pMediaItem; +} MFP_MF_EVENT; + +typedef struct MFP_ERROR_EVENT +{ + MFP_EVENT_HEADER header; +} MFP_ERROR_EVENT; + +typedef struct MFP_PLAYBACK_ENDED_EVENT +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *pMediaItem; +} MFP_PLAYBACK_ENDED_EVENT; + +typedef struct MFP_ACQUIRE_USER_CREDENTIAL_EVENT +{ + MFP_EVENT_HEADER header; + DWORD_PTR dwUserData; + BOOL fProceedWithAuthentication; + HRESULT hrAuthenticationStatus; + LPCWSTR pwszURL; + LPCWSTR pwszSite; + LPCWSTR pwszRealm; + LPCWSTR pwszPackage; + LONG nRetries; + MFP_CREDENTIAL_FLAGS flags; + IMFNetCredential *pCredential; +} MFP_ACQUIRE_USER_CREDENTIAL_EVENT; + [ object, uuid(766c8ffb-5fdb-4fea-a28d-b912996f51bd),
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 222 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 216 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index 5a85d9f0505..c08f496b508 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -59,10 +59,41 @@ struct media_player IMFPMediaPlayer IMFPMediaPlayer_iface; IPropertyStore IPropertyStore_iface; IMFAsyncCallback resolver_callback; + IMFAsyncCallback events_callback; LONG refcount; IMFPMediaPlayerCallback *callback; IPropertyStore *propstore; IMFSourceResolver *resolver; + MFP_CREATION_OPTIONS options; +}; + +struct generic_event +{ + MFP_EVENT_HEADER header; + IMFPMediaItem *item; +}; + +struct media_event +{ + IUnknown IUnknown_iface; + LONG refcount; + union + { + MFP_EVENT_HEADER header; + struct generic_event generic; + MFP_PLAY_EVENT play; + MFP_PAUSE_EVENT pause; + MFP_STOP_EVENT stop; + MFP_POSITION_SET_EVENT position_set; + MFP_RATE_SET_EVENT rate_set; + MFP_MEDIAITEM_CREATED_EVENT item_created; + MFP_MEDIAITEM_SET_EVENT item_set; + MFP_MEDIAITEM_CLEARED_EVENT item_cleared; + MFP_MF_EVENT event; + MFP_ERROR_EVENT error; + MFP_PLAYBACK_ENDED_EVENT ended; + MFP_ACQUIRE_USER_CREDENTIAL_EVENT acquire_creds; + } u; };
static struct media_player *impl_from_IMFPMediaPlayer(IMFPMediaPlayer *iface) @@ -80,11 +111,120 @@ static struct media_player *impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback return CONTAINING_RECORD(iface, struct media_player, resolver_callback); }
+static struct media_player *impl_from_events_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct media_player, events_callback); +} + static struct media_item *impl_from_IMFPMediaItem(IMFPMediaItem *iface) { return CONTAINING_RECORD(iface, struct media_item, IMFPMediaItem_iface); }
+static struct media_event *impl_event_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct media_event, IUnknown_iface); +} + +static HRESULT WINAPI media_event_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_event_AddRef(IUnknown *iface) +{ + struct media_event *event = impl_event_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&event->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI media_event_Release(IUnknown *iface) +{ + struct media_event *event = impl_event_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&event->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (event->u.header.pMediaPlayer) + IMFPMediaPlayer_Release(event->u.header.pMediaPlayer); + if (event->u.header.pPropertyStore) + IPropertyStore_Release(event->u.header.pPropertyStore); + + switch (event->u.header.eEventType) + { + /* Most types share same layout. */ + case MFP_EVENT_TYPE_PLAY: + case MFP_EVENT_TYPE_PAUSE: + case MFP_EVENT_TYPE_STOP: + case MFP_EVENT_TYPE_POSITION_SET: + case MFP_EVENT_TYPE_RATE_SET: + case MFP_EVENT_TYPE_MEDIAITEM_CREATED: + case MFP_EVENT_TYPE_MEDIAITEM_SET: + case MFP_EVENT_TYPE_FRAME_STEP: + case MFP_EVENT_TYPE_MEDIAITEM_CLEARED: + case MFP_EVENT_TYPE_PLAYBACK_ENDED: + if (event->u.generic.item) + IMFPMediaItem_Release(event->u.generic.item); + break; + case MFP_EVENT_TYPE_MF: + if (event->u.event.pMFMediaEvent) + IMFMediaEvent_Release(event->u.event.pMFMediaEvent); + if (event->u.event.pMediaItem) + IMFPMediaItem_Release(event->u.event.pMediaItem); + break; + default: + FIXME("Unsupported event %u.\n", event->u.header.eEventType); + break; + } + + heap_free(event); + } + + return refcount; +} + +static const IUnknownVtbl media_event_vtbl = +{ + media_event_QueryInterface, + media_event_AddRef, + media_event_Release, +}; + +static HRESULT media_event_create(MFP_EVENT_TYPE event_type, HRESULT hr, + IMFPMediaPlayer *player, struct media_event **event) +{ + struct media_event *object; + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IUnknown_iface.lpVtbl = &media_event_vtbl; + object->refcount = 1; + object->u.header.eEventType = event_type; + object->u.header.hrEvent = hr; + object->u.header.pMediaPlayer = player; + IMFPMediaPlayer_AddRef(object->u.header.pMediaPlayer); + /* FIXME: set player state field */ + /* FIXME: set properties for some events? */ + + *event = object; + + return S_OK; +} + static HRESULT WINAPI media_item_QueryInterface(IMFPMediaItem *iface, REFIID riid, void **obj) { TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); @@ -391,6 +531,18 @@ static HRESULT media_item_set_source(struct media_item *item, IUnknown *object) return hr; }
+static void media_player_queue_event(struct media_player *player, struct media_event *event) +{ + if (player->options & MFP_OPTION_FREE_THREADED_CALLBACK) + { + MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &player->events_callback, &event->IUnknown_iface); + } + else + { + /* FIXME: same-thread callback notification */ + } +} + static HRESULT WINAPI media_player_QueryInterface(IMFPMediaPlayer *iface, REFIID riid, void **obj) { struct media_player *player = impl_from_IMFPMediaPlayer(iface); @@ -863,7 +1015,7 @@ static const IPropertyStoreVtbl media_player_propstore_vtbl = media_player_propstore_Commit, };
-static HRESULT WINAPI media_player_resolver_callback_QueryInterface(IMFAsyncCallback *iface, +static HRESULT WINAPI media_player_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFAsyncCallback) || @@ -890,7 +1042,7 @@ static ULONG WINAPI media_player_resolver_callback_Release(IMFAsyncCallback *ifa return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface); }
-static HRESULT WINAPI media_player_resolver_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, +static HRESULT WINAPI media_player_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) { return E_NOTIMPL; @@ -899,9 +1051,10 @@ static HRESULT WINAPI media_player_resolver_callback_GetParameters(IMFAsyncCallb static HRESULT WINAPI media_player_resolver_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface); - struct media_item *item; + struct media_event *event; IUnknown *object, *state; MF_OBJECT_TYPE obj_type; + struct media_item *item; HRESULT hr;
if (FAILED(IMFAsyncResult_GetState(result, &state))) @@ -918,8 +1071,23 @@ static HRESULT WINAPI media_player_resolver_callback_Invoke(IMFAsyncCallback *if if (FAILED(hr)) WARN("Failed to set media source, hr %#x.\n", hr);
- /* FIXME: callback notification */ + if (FAILED(media_event_create(MFP_EVENT_TYPE_MEDIAITEM_CREATED, hr, &player->IMFPMediaPlayer_iface, &event))) + { + WARN("Failed to create event object.\n"); + IUnknown_Release(state); + return S_OK; + } + + if (SUCCEEDED(hr)) + { + event->u.item_created.pMediaItem = &item->IMFPMediaItem_iface; + IMFPMediaItem_AddRef(event->u.item_created.pMediaItem); + } + event->u.item_created.dwUserData = item->user_data; + + media_player_queue_event(player, event);
+ IUnknown_Release(&event->IUnknown_iface); IUnknown_Release(state);
return S_OK; @@ -927,13 +1095,53 @@ static HRESULT WINAPI media_player_resolver_callback_Invoke(IMFAsyncCallback *if
static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl = { - media_player_resolver_callback_QueryInterface, + media_player_callback_QueryInterface, media_player_resolver_callback_AddRef, media_player_resolver_callback_Release, - media_player_resolver_callback_GetParameters, + media_player_callback_GetParameters, media_player_resolver_callback_Invoke, };
+static ULONG WINAPI media_player_events_callback_AddRef(IMFAsyncCallback *iface) +{ + struct media_player *player = impl_from_events_IMFAsyncCallback(iface); + return IMFPMediaPlayer_AddRef(&player->IMFPMediaPlayer_iface); +} + +static ULONG WINAPI media_player_events_callback_Release(IMFAsyncCallback *iface) +{ + struct media_player *player = impl_from_events_IMFAsyncCallback(iface); + return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface); +} + +static HRESULT WINAPI media_player_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct media_player *player = impl_from_events_IMFAsyncCallback(iface); + struct media_event *event; + IUnknown *state; + + if (FAILED(IMFAsyncResult_GetState(result, &state))) + return S_OK; + + event = impl_event_from_IUnknown(state); + + if (player->callback) + IMFPMediaPlayerCallback_OnMediaPlayerEvent(player->callback, &event->u.header); + + IUnknown_Release(state); + + return S_OK; +} + +static const IMFAsyncCallbackVtbl media_player_events_callback_vtbl = +{ + media_player_callback_QueryInterface, + media_player_events_callback_AddRef, + media_player_events_callback_Release, + media_player_callback_GetParameters, + media_player_events_callback_Invoke, +}; + HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_CREATION_OPTIONS options, IMFPMediaPlayerCallback *callback, HWND hwnd, IMFPMediaPlayer **player) { @@ -950,8 +1158,10 @@ HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_C object->IMFPMediaPlayer_iface.lpVtbl = &media_player_vtbl; object->IPropertyStore_iface.lpVtbl = &media_player_propstore_vtbl; object->resolver_callback.lpVtbl = &media_player_resolver_callback_vtbl; + object->events_callback.lpVtbl = &media_player_events_callback_vtbl; object->refcount = 1; object->callback = callback; + object->options = options; if (object->callback) IMFPMediaPlayerCallback_AddRef(object->callback); if (FAILED(hr = CreatePropertyStore(&object->propstore)))
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/Makefile.in | 2 +- dlls/mfplay/player.c | 59 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplay/Makefile.in b/dlls/mfplay/Makefile.in index 8f0fb61fe6f..c353fa33cc1 100644 --- a/dlls/mfplay/Makefile.in +++ b/dlls/mfplay/Makefile.in @@ -1,6 +1,6 @@ MODULE = mfplay.dll IMPORTLIB = mfplay -IMPORTS = mfplat mf uuid mfuuid +IMPORTS = mfplat mf user32 uuid mfuuid
EXTRADLLFLAGS = -mno-cygwin -Wb,--prefer-native
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index c08f496b508..246704c2799 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -30,7 +30,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+static const WCHAR eventclassW[] = L"MediaPlayerEventCallbackClass"; + static LONG startup_refcount; +static HINSTANCE mfplay_instance;
static void platform_startup(void) { @@ -65,6 +68,7 @@ struct media_player IPropertyStore *propstore; IMFSourceResolver *resolver; MFP_CREATION_OPTIONS options; + HWND event_window; };
struct generic_event @@ -225,6 +229,23 @@ static HRESULT media_event_create(MFP_EVENT_TYPE event_type, HRESULT hr, return S_OK; }
+static LRESULT WINAPI media_player_event_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + struct media_event *event = (void *)lparam; + struct media_player *player; + + if (msg == WM_USER) + { + player = impl_from_IMFPMediaPlayer(event->u.header.pMediaPlayer); + if (player->callback) + IMFPMediaPlayerCallback_OnMediaPlayerEvent(player->callback, &event->u.header); + IUnknown_Release(&event->IUnknown_iface); + return 0; + } + + return DefWindowProcW(hwnd, msg, wparam, lparam); +} + static HRESULT WINAPI media_item_QueryInterface(IMFPMediaItem *iface, REFIID riid, void **obj) { TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); @@ -539,7 +560,8 @@ static void media_player_queue_event(struct media_player *player, struct media_e } else { - /* FIXME: same-thread callback notification */ + IUnknown_AddRef(&event->IUnknown_iface); + PostMessageW(player->event_window, WM_USER, 0, (LPARAM)event); } }
@@ -595,6 +617,7 @@ static ULONG WINAPI media_player_Release(IMFPMediaPlayer *iface) IPropertyStore_Release(player->propstore); if (player->resolver) IMFSourceResolver_Release(player->resolver); + DestroyWindow(player->event_window); heap_free(player);
platform_shutdown(); @@ -1168,6 +1191,11 @@ HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_C goto failed; if (FAILED(hr = MFCreateSourceResolver(&object->resolver))) goto failed; + if (!(object->options & MFP_OPTION_FREE_THREADED_CALLBACK)) + { + object->event_window = CreateWindowW(eventclassW, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, + 0, mfplay_instance, NULL); + }
*player = &object->IMFPMediaPlayer_iface;
@@ -1179,3 +1207,32 @@ failed:
return hr; } + +static void media_player_register_window_class(void) +{ + WNDCLASSW cls = { 0 }; + + cls.lpfnWndProc = media_player_event_proc; + cls.hInstance = mfplay_instance; + cls.lpszClassName = eventclassW; + + RegisterClassW(&cls); +} + +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + mfplay_instance = instance; + DisableThreadLibraryCalls(instance); + media_player_register_window_class(); + break; + case DLL_PROCESS_DETACH: + if (reserved) break; + UnregisterClassW(eventclassW, instance); + break; + } + + return TRUE; +}