[PATCH] wmp: Improve media items handling.

Nikolay Sivov nsivov at codeweavers.com
Fri Aug 17 10:05:16 CDT 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 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 56b408f5b1..fd8c17d60f 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 aeca6180b0..bd9aefc975 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 b0861dd302..9617be0c7f 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;
+}
-- 
2.18.0




More information about the wine-devel mailing list