From cd1c681ee71332e18081730ce7f8794fedb55f5b Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 17 Aug 2018 18:05:16 +0300 Subject: [PATCH] wmp: Improve media items handling. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/wmp/player.c | 98 +++++++++++++++++++++--------------------- dlls/wmp/tests/media.c | 77 +++++++++++++++++++++++++++++++++ dlls/wmp/wmp_private.h | 20 ++++++++- 3 files changed, 144 insertions(+), 51 deletions(-) diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index 56b408f5b15..fd8c17d60f9 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -129,14 +129,17 @@ static HRESULT WINAPI WMPPlayer4_close(IWMPPlayer4 *iface) return E_NOTIMPL; } -static HRESULT WINAPI WMPPlayer4_get_URL(IWMPPlayer4 *iface, BSTR *pbstrURL) +static HRESULT WINAPI WMPPlayer4_get_URL(IWMPPlayer4 *iface, BSTR *url) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); - TRACE("(%p)->(%p)\n", This, pbstrURL); - if(This->wmpmedia == NULL) { + + TRACE("(%p)->(%p)\n", This, url); + + if(This->media == NULL) { return S_FALSE; } - return IWMPMedia_get_sourceURL(This->wmpmedia, pbstrURL); + + return return_bstr(This->media->url, url); } static HRESULT WINAPI WMPPlayer4_put_URL(IWMPPlayer4 *iface, BSTR url) @@ -149,7 +152,7 @@ static HRESULT WINAPI WMPPlayer4_put_URL(IWMPPlayer4 *iface, BSTR url) return E_POINTER; } - hres = create_media_from_url(url, &media); + hres = create_media_from_url(url, 0.0, &media); if (SUCCEEDED(hres)) { update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsTransitioning); @@ -202,16 +205,18 @@ static HRESULT WINAPI WMPPlayer4_get_settings(IWMPPlayer4 *iface, IWMPSettings * return S_OK; } -static HRESULT WINAPI WMPPlayer4_get_currentMedia(IWMPPlayer4 *iface, IWMPMedia **ppMedia) +static HRESULT WINAPI WMPPlayer4_get_currentMedia(IWMPPlayer4 *iface, IWMPMedia **media) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); - TRACE("(%p)->(%p)\n", This, ppMedia); - if(This->wmpmedia == NULL) { + + TRACE("(%p)->(%p)\n", This, media); + + *media = NULL; + + if (This->media == NULL) return S_FALSE; - } - IWMPMedia_AddRef(This->wmpmedia); - *ppMedia = This->wmpmedia; - return S_OK; + + return create_media_from_url(This->media->url, This->media->duration, media); } static HRESULT WINAPI WMPPlayer4_put_currentMedia(IWMPPlayer4 *iface, IWMPMedia *pMedia) @@ -223,15 +228,15 @@ static HRESULT WINAPI WMPPlayer4_put_currentMedia(IWMPPlayer4 *iface, IWMPMedia return E_POINTER; } update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistChanging); - if(This->wmpmedia != NULL) { + if(This->media != NULL) { IWMPControls_stop(&This->IWMPControls_iface); - IWMPMedia_Release(This->wmpmedia); + IWMPMedia_Release(&This->media->IWMPMedia_iface); } update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistChanged); update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistOpenNoMedia); IWMPMedia_AddRef(pMedia); - This->wmpmedia = pMedia; + This->media = unsafe_impl_from_IWMPMedia(pMedia); return S_OK; } @@ -259,8 +264,7 @@ static HRESULT WINAPI WMPPlayer4_get_versionInfo(IWMPPlayer4 *iface, BSTR *versi if (!version) return E_POINTER; - *version = SysAllocString(versionW); - return *version ? S_OK : E_OUTOFMEMORY; + return return_bstr(versionW, version); } static HRESULT WINAPI WMPPlayer4_launchURL(IWMPPlayer4 *iface, BSTR url) @@ -343,11 +347,13 @@ static HRESULT WINAPI WMPPlayer4_newPlaylist(IWMPPlayer4 *iface, BSTR name, BSTR return E_NOTIMPL; } -static HRESULT WINAPI WMPPlayer4_newMedia(IWMPPlayer4 *iface, BSTR url, IWMPMedia **ppMedia) +static HRESULT WINAPI WMPPlayer4_newMedia(IWMPPlayer4 *iface, BSTR url, IWMPMedia **media) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); - FIXME("(%p)->(%p)\n", This, ppMedia); - return E_NOTIMPL; + + TRACE("(%p)->(%s %p)\n", This, debugstr_w(url), media); + + return create_media_from_url(url, 0.0, media); } static HRESULT WINAPI WMPPlayer4_get_enabled(IWMPPlayer4 *iface, VARIANT_BOOL *pbEnabled) @@ -1450,20 +1456,13 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) { HRESULT hres = S_OK; WindowsMediaPlayer *This = impl_from_IWMPControls(iface); - WMPMedia *media; TRACE("(%p)\n", This); - if (!This->wmpmedia) { + if (!This->media) { return NS_S_WMPCORE_COMMAND_NOT_AVAILABLE; } - media = unsafe_impl_from_IWMPMedia(This->wmpmedia); - if (!media) { - FIXME("No support for non-builtin IWMPMedia implementations\n"); - return E_INVALIDARG; - } - if (!This->filter_graph) { hres = CoCreateInstance(&CLSID_FilterGraph, NULL, @@ -1473,7 +1472,7 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposOpeningUnknownURL); if (SUCCEEDED(hres)) - hres = IGraphBuilder_RenderFile(This->filter_graph, media->url, NULL); + hres = IGraphBuilder_RenderFile(This->filter_graph, This->media->url, NULL); if (SUCCEEDED(hres)) update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposMediaOpen); if (SUCCEEDED(hres)) @@ -1517,7 +1516,7 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) LONGLONG duration; update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsPlaying); if (SUCCEEDED(IMediaSeeking_GetDuration(This->media_seeking, &duration))) - media->duration = (DOUBLE)duration / 10000000.0f; + This->media->duration = (DOUBLE)duration / 10000000.0f; } else { update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsUndefined); } @@ -1781,24 +1780,23 @@ static HRESULT WINAPI WMPMedia_get_isIdentical(IWMPMedia *iface, IWMPMedia *othe return E_NOTIMPL; } -static HRESULT WINAPI WMPMedia_get_sourceURL(IWMPMedia *iface, BSTR *pbstrSourceUrl) +static HRESULT WINAPI WMPMedia_get_sourceURL(IWMPMedia *iface, BSTR *url) { WMPMedia *This = impl_from_IWMPMedia(iface); - BSTR url; - TRACE("(%p)->(%p)\n", This, pbstrSourceUrl); - url = SysAllocString(This->url); - if (url) { - *pbstrSourceUrl = url; - return S_OK; - } - return E_OUTOFMEMORY; + + TRACE("(%p)->(%p)\n", This, url); + + return return_bstr(This->url, url); } -static HRESULT WINAPI WMPMedia_get_name(IWMPMedia *iface, BSTR *pbstrName) +static HRESULT WINAPI WMPMedia_get_name(IWMPMedia *iface, BSTR *name) { WMPMedia *This = impl_from_IWMPMedia(iface); - FIXME("(%p)->(%p)\n", This, pbstrName); - return E_NOTIMPL; + + FIXME("(%p)->(%p)\n", This, name); + + /* FIXME: this should be a display name */ + return return_bstr(This->url, name); } static HRESULT WINAPI WMPMedia_put_name(IWMPMedia *iface, BSTR pbstrName) @@ -2012,8 +2010,8 @@ BOOL init_player(WindowsMediaPlayer *wmp) void destroy_player(WindowsMediaPlayer *wmp) { IWMPControls_stop(&wmp->IWMPControls_iface); - if(wmp->wmpmedia) - IWMPMedia_Release(wmp->wmpmedia); + if (wmp->media) + IWMPMedia_Release(&wmp->media->IWMPMedia_iface); DestroyWindow(wmp->msg_window); } @@ -2025,16 +2023,18 @@ WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) return NULL; } -HRESULT create_media_from_url(BSTR url, IWMPMedia **ppMedia) +HRESULT create_media_from_url(BSTR url, double duration, IWMPMedia **ppMedia) { - WMPMedia *media = heap_alloc_zero(sizeof(WMPMedia)); + static const WCHAR emptyW[] = {0}; + WMPMedia *media; - if (!media) { + media = heap_alloc_zero(sizeof(*media)); + if (!media) return E_OUTOFMEMORY; - } media->IWMPMedia_iface.lpVtbl = &WMPMediaVtbl; - media->url = heap_strdupW(url); + media->url = url ? heap_strdupW(url) : heap_strdupW(emptyW); + media->duration = duration; media->ref = 1; if (media->url) { diff --git a/dlls/wmp/tests/media.c b/dlls/wmp/tests/media.c index aeca6180b00..bd9aefc975f 100644 --- a/dlls/wmp/tests/media.c +++ b/dlls/wmp/tests/media.c @@ -487,6 +487,81 @@ playback_skip: return test_ran; } +static void test_media_item(void) +{ + static const WCHAR testW[] = {'t','e','s','t',0}; + IWMPMedia *media, *media2; + IWMPPlayer4 *player; + HRESULT hr; + BSTR str; + + hr = CoCreateInstance(&CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, &IID_IWMPPlayer4, (void **)&player); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("CLSID_WindowsMediaPlayer is not registered.\n"); + return; + } + ok(hr == S_OK, "Failed to create media player instance, hr %#x.\n", hr); + + hr = IWMPPlayer4_newMedia(player, NULL, &media); + ok(hr == S_OK, "Failed to create a media item, hr %#x.\n", hr); + hr = IWMPMedia_get_name(media, &str); + ok(hr == S_OK, "Failed to get item name, hr %#x.\n", hr); + ok(*str == 0, "Unexpected name %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); + + media2 = (void *)0xdeadbeef; + hr = IWMPPlayer4_get_currentMedia(player, &media2); + ok(hr == S_FALSE, "Failed to get current media, hr %#x.\n", hr); + ok(media2 == NULL, "Unexpected media instance.\n"); + + hr = IWMPPlayer4_put_currentMedia(player, media); + ok(hr == S_OK, "Failed to set current media, hr %#x.\n", hr); + + hr = IWMPPlayer4_get_currentMedia(player, &media2); + ok(hr == S_OK, "Failed to get current media, hr %#x.\n", hr); + ok(media2 != NULL && media != media2, "Unexpected media instance.\n"); + IWMPMedia_Release(media2); + + IWMPMedia_Release(media); + + str = SysAllocStringLen(NULL, 0); + hr = IWMPPlayer4_newMedia(player, str, &media); + ok(hr == S_OK, "Failed to create a media item, hr %#x.\n", hr); + SysFreeString(str); + hr = IWMPMedia_get_name(media, &str); + ok(hr == S_OK, "Failed to get item name, hr %#x.\n", hr); + ok(*str == 0, "Unexpected name %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); + IWMPMedia_Release(media); + + str = SysAllocString(mp3file); + hr = IWMPPlayer4_newMedia(player, str, &media); + ok(hr == S_OK, "Failed to create a media item, hr %#x.\n", hr); + SysFreeString(str); + hr = IWMPMedia_get_name(media, &str); + ok(hr == S_OK, "Failed to get item name, hr %#x.\n", hr); +todo_wine + ok(!lstrcmpW(str, testW), "Unexpected name %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); + + hr = IWMPPlayer4_put_currentMedia(player, media); + ok(hr == S_OK, "Failed to set current media, hr %#x.\n", hr); + IWMPMedia_Release(media); + + hr = IWMPPlayer4_get_currentMedia(player, &media2); + ok(hr == S_OK, "Failed to get current media, hr %#x.\n", hr); + ok(media2 != NULL, "Unexpected media instance.\n"); + hr = IWMPMedia_get_name(media2, &str); + ok(hr == S_OK, "Failed to get item name, hr %#x.\n", hr); +todo_wine + ok(!lstrcmpW(str, testW), "Unexpected name %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); + IWMPMedia_Release(media2); + + IWMPPlayer4_Release(player); +} + START_TEST(media) { CoInitialize(NULL); @@ -494,6 +569,8 @@ START_TEST(media) main_thread_id = GetCurrentThreadId(); playing_event = CreateEventW(NULL, FALSE, FALSE, NULL); completed_event = CreateEventW(NULL, FALSE, FALSE, NULL); + + test_media_item(); if (test_wmp()) { test_completion_event(); } else { diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index b0861dd302d..9617be0c7f1 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -73,7 +73,7 @@ struct WindowsMediaPlayer { ConnectionPoint *wmpocx; - IWMPMedia *wmpmedia; + WMPMedia *media; /* DirectShow stuff */ IGraphBuilder* filter_graph; @@ -89,7 +89,7 @@ struct WindowsMediaPlayer { BOOL init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; void destroy_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) DECLSPEC_HIDDEN; -HRESULT create_media_from_url(BSTR url, IWMPMedia **ppMedia) DECLSPEC_HIDDEN; +HRESULT create_media_from_url(BSTR url, double duration, IWMPMedia **ppMedia) DECLSPEC_HIDDEN; void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN; void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN; void call_sink(ConnectionPoint *This, DISPID dispid, DISPPARAMS *dispparams) DECLSPEC_HIDDEN; @@ -116,3 +116,19 @@ static inline WCHAR *heap_strdupW(const WCHAR *str) return ret; } + +static inline HRESULT return_bstr(const WCHAR *value, BSTR *p) +{ + if(!p) + return E_INVALIDARG; + + if(value) { + *p = SysAllocString(value); + if(!*p) + return E_OUTOFMEMORY; + }else { + *p = NULL; + } + + return S_OK; +}