Signed-off-by: Gijs Vermeulen gijsvrm@codeweavers.com ---
v3: release name and url in IWMPPlaylist::Release
dlls/wmp/player.c | 255 +++++++++++++++++++++++++++++++++++++++- dlls/wmp/tests/oleobj.c | 15 +++ dlls/wmp/wmp_private.h | 12 ++ 3 files changed, 279 insertions(+), 3 deletions(-)
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index fc4439d6f0..de0f15bece 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -47,6 +47,11 @@ static void update_state(WindowsMediaPlayer *wmp, LONG type, LONG state) call_sink(wmp->wmpocx, type, &dispparams); }
+static inline WMPPlaylist *impl_from_IWMPPlaylist(IWMPPlaylist *iface) +{ + return CONTAINING_RECORD(iface, WMPPlaylist, IWMPPlaylist_iface); +} + static inline WMPMedia *impl_from_IWMPMedia(IWMPMedia *iface) { return CONTAINING_RECORD(iface, WMPMedia, IWMPMedia_iface); @@ -337,11 +342,13 @@ static HRESULT WINAPI WMPPlayer4_get_dvd(IWMPPlayer4 *iface, IWMPDVD **ppDVD) return E_NOTIMPL; }
-static HRESULT WINAPI WMPPlayer4_newPlaylist(IWMPPlayer4 *iface, BSTR name, BSTR url, IWMPPlaylist **ppPlaylist) +static HRESULT WINAPI WMPPlayer4_newPlaylist(IWMPPlayer4 *iface, BSTR name, BSTR url, IWMPPlaylist **playlist) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); - FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(url), ppPlaylist); - return E_NOTIMPL; + + TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(name), debugstr_w(url), playlist); + + return create_playlist(name, url, playlist); }
static HRESULT WINAPI WMPPlayer4_newMedia(IWMPPlayer4 *iface, BSTR url, IWMPMedia **media) @@ -1937,6 +1944,210 @@ static const IWMPMediaVtbl WMPMediaVtbl = { WMPMedia_isReadOnlyItem };
+static HRESULT WINAPI WMPPlaylist_QueryInterface(IWMPPlaylist *iface, REFIID riid, void **ppv) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + TRACE("(%p)\n", This); + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IWMPPlaylist_iface; + }else if(IsEqualGUID(&IID_IDispatch, riid)) { + TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); + *ppv = &This->IWMPPlaylist_iface; + }else if(IsEqualGUID(&IID_IWMPPlaylist, riid)) { + TRACE("(%p)->(IID_IWMPPlaylist %p)\n", This, ppv); + *ppv = &This->IWMPPlaylist_iface; + }else { + WARN("Unsupported interface %s\n", debugstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI WMPPlaylist_AddRef(IWMPPlaylist *iface) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI WMPPlaylist_Release(IWMPPlaylist *iface) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + heap_free(This->url); + heap_free(This->name); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI WMPPlaylist_GetTypeInfoCount(IWMPPlaylist *iface, UINT *pctinfo) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p)\n", This, pctinfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_GetTypeInfo(IWMPPlaylist *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%u %d %p)\n", This, iTInfo, lcid, ppTInfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_GetIDsOfNames(IWMPPlaylist *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_Invoke(IWMPPlaylist *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%d %s %d %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_get_count(IWMPPlaylist *iface, LONG *count) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p)\n", This, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_get_name(IWMPPlaylist *iface, BSTR *name) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p)\n", This, name); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_put_name(IWMPPlaylist *iface, BSTR name) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(name)); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_get_attributeCount(IWMPPlaylist *iface, LONG *count) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p)\n", This, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_get_attributeName(IWMPPlaylist *iface, LONG index, BSTR *attribute_name) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%d %p)\n", This, index, attribute_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_get_Item(IWMPPlaylist *iface, LONG index, IWMPMedia **media) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%d %p)\n", This, index, media); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_getItemInfo(IWMPPlaylist *iface, BSTR name, BSTR *value) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%s %p)\n", This, debugstr_w(name), value); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_setItemInfo(IWMPPlaylist *iface, BSTR name, BSTR value) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%s %s)\n", This, debugstr_w(name), debugstr_w(value)); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_get_isIdentical(IWMPPlaylist *iface, IWMPPlaylist *playlist, VARIANT_BOOL *var) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p %p)\n", This, playlist, var); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_clear(IWMPPlaylist *iface) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_insertItem(IWMPPlaylist *iface, LONG index, IWMPMedia *media) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%d %p)\n", This, index, media); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_appendItem(IWMPPlaylist *iface, IWMPMedia *media) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p)\n", This, media); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_removeItem(IWMPPlaylist *iface, IWMPMedia *media) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%p)\n", This, media); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPPlaylist_moveItem(IWMPPlaylist *iface, LONG old_index, LONG new_index) +{ + WMPPlaylist *This = impl_from_IWMPPlaylist(iface); + FIXME("(%p)->(%d %d)\n", This, old_index, new_index); + return E_NOTIMPL; +} + +static const IWMPPlaylistVtbl WMPPlaylistVtbl = { + WMPPlaylist_QueryInterface, + WMPPlaylist_AddRef, + WMPPlaylist_Release, + WMPPlaylist_GetTypeInfoCount, + WMPPlaylist_GetTypeInfo, + WMPPlaylist_GetIDsOfNames, + WMPPlaylist_Invoke, + WMPPlaylist_get_count, + WMPPlaylist_get_name, + WMPPlaylist_put_name, + WMPPlaylist_get_attributeCount, + WMPPlaylist_get_attributeName, + WMPPlaylist_get_Item, + WMPPlaylist_getItemInfo, + WMPPlaylist_setItemInfo, + WMPPlaylist_get_isIdentical, + WMPPlaylist_clear, + WMPPlaylist_insertItem, + WMPPlaylist_appendItem, + WMPPlaylist_removeItem, + WMPPlaylist_moveItem +}; + static LRESULT WINAPI player_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_WMPEVENT && wParam == 0) { @@ -1985,6 +2196,8 @@ void unregister_player_msg_class(void) {
BOOL init_player(WindowsMediaPlayer *wmp) { + IWMPPlaylist *playlist; + InitOnceExecuteOnce(&class_init_once, register_player_msg_class, NULL, NULL); wmp->msg_window = CreateWindowW( MAKEINTRESOURCEW(player_msg_class), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, wmp_instance, wmp ); @@ -2003,6 +2216,11 @@ BOOL init_player(WindowsMediaPlayer *wmp) wmp->IWMPControls_iface.lpVtbl = &WMPControlsVtbl; wmp->IWMPNetwork_iface.lpVtbl = &WMPNetworkVtbl;
+ if (SUCCEEDED(create_playlist(NULL, NULL, &playlist))) + wmp->playlist = unsafe_impl_from_IWMPPlaylist(playlist); + else + wmp->playlist = NULL; + wmp->invoke_urls = VARIANT_TRUE; wmp->auto_start = VARIANT_TRUE; wmp->volume = 100; @@ -2025,6 +2243,14 @@ WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) return NULL; }
+WMPPlaylist *unsafe_impl_from_IWMPPlaylist(IWMPPlaylist *iface) +{ + if (iface->lpVtbl == &WMPPlaylistVtbl) { + return CONTAINING_RECORD(iface, WMPPlaylist, IWMPPlaylist_iface); + } + return NULL; +} + HRESULT create_media_from_url(BSTR url, double duration, IWMPMedia **ppMedia) { WMPMedia *media; @@ -2087,3 +2313,26 @@ HRESULT create_media_from_url(BSTR url, double duration, IWMPMedia **ppMedia) IWMPMedia_Release(&media->IWMPMedia_iface); return E_OUTOFMEMORY; } + +HRESULT create_playlist(BSTR name, BSTR url, IWMPPlaylist **ppPlaylist) +{ + WMPPlaylist *playlist; + + playlist = heap_alloc_zero(sizeof(*playlist)); + if (!playlist) + return E_OUTOFMEMORY; + + playlist->IWMPPlaylist_iface.lpVtbl = &WMPPlaylistVtbl; + playlist->url = url ? heap_strdupW(url) : heap_strdupW(emptyW); + playlist->name = name ? heap_strdupW(name) : heap_strdupW(emptyW); + playlist->ref = 1; + + if (playlist->url) + { + *ppPlaylist = &playlist->IWMPPlaylist_iface; + return S_OK; + } + + IWMPPlaylist_Release(&playlist->IWMPPlaylist_iface); + return E_OUTOFMEMORY; +} diff --git a/dlls/wmp/tests/oleobj.c b/dlls/wmp/tests/oleobj.c index deac5cd3db..dbd9e936ed 100644 --- a/dlls/wmp/tests/oleobj.c +++ b/dlls/wmp/tests/oleobj.c @@ -894,6 +894,7 @@ static void test_wmp_ifaces(IOleObject *oleobj) IWMPSettings *settings, *settings_qi; IWMPPlayer4 *player4; IWMPPlayer *player; + IWMPPlaylist *playlist; IWMPMedia *media; IWMPControls *controls; VARIANT_BOOL vbool; @@ -937,6 +938,20 @@ static void test_wmp_ifaces(IOleObject *oleobj)
IWMPNetwork_Release(network);
+ playlist = NULL; + hres = IWMPPlayer4_QueryInterface(player4, &IID_IWMPPlaylist, (void**)&playlist); + ok(hres == E_NOINTERFACE, "Getting IWMPPlaylist from IWMPPlayer4 succeeded: %08x\n", hres); + ok(playlist == NULL, "playlist != NULL\n"); + + playlist = NULL; + hres = IWMPPlayer4_get_currentPlaylist(player4, &playlist); +todo_wine { + ok(hres == S_OK, "IWMPPlayer4_get_currentPlaylist failed: %08x\n", hres); + ok(playlist != NULL, "playlist != NULL\n"); +} + + if (playlist) IWMPPlaylist_Release(playlist); + media = NULL; hres = IWMPPlayer4_QueryInterface(player4, &IID_IWMPMedia, (void**)&media); ok(hres == E_NOINTERFACE, "get_currentMedia SUCCEEDED: %08x\n", hres); diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 0b1b02305f..32b4e1f6ae 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -61,6 +61,15 @@ typedef struct { DOUBLE duration; } WMPMedia;
+typedef struct { + IWMPPlaylist IWMPPlaylist_iface; + + LONG ref; + + WCHAR *url; + WCHAR *name; +} WMPPlaylist; + struct WindowsMediaPlayer { IOleObject IOleObject_iface; IProvideClassInfo2 IProvideClassInfo2_iface; @@ -89,6 +98,7 @@ struct WindowsMediaPlayer { ConnectionPoint *wmpocx;
WMPMedia *media; + WMPPlaylist *playlist;
/* DirectShow stuff */ IGraphBuilder* filter_graph; @@ -104,7 +114,9 @@ struct WindowsMediaPlayer { BOOL init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; void destroy_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) DECLSPEC_HIDDEN; +WMPPlaylist *unsafe_impl_from_IWMPPlaylist(IWMPPlaylist *iface) DECLSPEC_HIDDEN; HRESULT create_media_from_url(BSTR url, double duration, IWMPMedia **ppMedia) DECLSPEC_HIDDEN; +HRESULT create_playlist(BSTR name, BSTR url, IWMPPlaylist **ppPlaylist) 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;