Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/player.c | 82 ++++++++++++++++++++++++++++--- dlls/wmp/tests/Makefile.in | 2 +- dlls/wmp/tests/av.mp4 | Bin 1493 -> 0 bytes dlls/wmp/tests/media.c | 120 +++++++++++++++++++++++++++++++++++++++++++++ dlls/wmp/tests/oleobj.c | 6 +-- dlls/wmp/tests/rsrc.rc | 5 +- dlls/wmp/tests/test.mp3 | Bin 0 -> 240333 bytes dlls/wmp/wmp_private.h | 8 ++- 8 files changed, 208 insertions(+), 15 deletions(-) delete mode 100644 dlls/wmp/tests/av.mp4 create mode 100644 dlls/wmp/tests/media.c create mode 100644 dlls/wmp/tests/test.mp3
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index 4a0d0742fd..03f5d8f2be 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -19,6 +19,8 @@ #include "wmp_private.h"
#include "wine/debug.h" +#include <nserror.h> +#include <assert.h>
WINE_DEFAULT_DEBUG_CHANNEL(wmp);
@@ -119,12 +121,20 @@ static HRESULT WINAPI WMPPlayer4_put_URL(IWMPPlayer4 *iface, BSTR url) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); IWMPMedia *media; + HRESULT hres; TRACE("(%p)->(%s)\n", This, debugstr_w(url)); if(url == NULL) { return E_POINTER; } - media = create_media_from_url(url); - return IWMPPlayer4_put_currentMedia(iface, media); + hres = create_media_from_url(url, &media); + if (SUCCEEDED(hres)) { + hres = IWMPPlayer4_put_currentMedia(iface, media); + IWMPMedia_Release(media); /* put will addref */ + } + if (SUCCEEDED(hres) && This->auto_start) { + hres = IWMPControls_play(&This->IWMPControls_iface); + } + return hres; }
static HRESULT WINAPI WMPPlayer4_get_openState(IWMPPlayer4 *iface, WMPOpenState *pwmpos) @@ -1357,16 +1367,54 @@ static HRESULT WINAPI WMPControls_get_isAvailable(IWMPControls *iface, BSTR bstr
static HRESULT WINAPI WMPControls_play(IWMPControls *iface) { + HRESULT hres = S_OK; WindowsMediaPlayer *This = impl_from_IWMPControls(iface); - FIXME("(%p)\n", This); - return E_NOTIMPL; + WMPMedia *media; + + TRACE("(%p)\n", This); + + if (!This->wmpmedia) { + return NS_S_WMPCORE_COMMAND_NOT_AVAILABLE; + } + + media = unsafe_impl_from_IWMPMedia(This->wmpmedia); + + if (!This->pFilterGraph) { + hres = CoCreateInstance(&CLSID_FilterGraph, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IGraphBuilder, + (void **)&This->pFilterGraph); + if (SUCCEEDED(hres)) + hres = IGraphBuilder_RenderFile(This->pFilterGraph, media->url, NULL); + if (SUCCEEDED(hres)) + hres = IGraphBuilder_QueryInterface(This->pFilterGraph, &IID_IMediaControl, + (void**)&This->media_control); + } + + if (SUCCEEDED(hres)) + hres = IMediaControl_Run(This->media_control); + + if (hres == S_FALSE) { + hres = S_OK; /* S_FALSE will mean that graph is transitioning and that is fine */ + } + return hres; }
static HRESULT WINAPI WMPControls_stop(IWMPControls *iface) { + HRESULT hres = S_OK; WindowsMediaPlayer *This = impl_from_IWMPControls(iface); - FIXME("(%p)\n", This); - return E_NOTIMPL; + TRACE("(%p)\n", This); + if (!This->pFilterGraph) { + return NS_S_WMPCORE_COMMAND_NOT_AVAILABLE; + } + hres = IMediaControl_Stop(This->media_control); + IGraphBuilder_Release(This->pFilterGraph); + IMediaControl_Release(This->media_control); + This->pFilterGraph = NULL; + This->media_control = NULL; + return hres; }
static HRESULT WINAPI WMPControls_pause(IWMPControls *iface) @@ -1741,16 +1789,34 @@ void init_player(WindowsMediaPlayer *wmp)
void destroy_player(WindowsMediaPlayer *wmp) { + IWMPControls_stop(&wmp->IWMPControls_iface); if(wmp->wmpmedia) IWMPMedia_Release(wmp->wmpmedia); }
-IWMPMedia* create_media_from_url(BSTR url){ +WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) +{ + assert(iface->lpVtbl == &WMPMediaVtbl); + return CONTAINING_RECORD(iface, WMPMedia, IWMPMedia_iface); +}
+HRESULT create_media_from_url(BSTR url, IWMPMedia **ppMedia) +{ WMPMedia *media = heap_alloc_zero(sizeof(WMPMedia)); + + if (!media) { + return E_OUTOFMEMORY; + } + media->IWMPMedia_iface.lpVtbl = &WMPMediaVtbl; media->url = heap_strdupW(url); media->ref = 1;
- return &media->IWMPMedia_iface; + if (media->url) { + *ppMedia = &media->IWMPMedia_iface; + + return S_OK; + } + IWMPMedia_Release(&media->IWMPMedia_iface); + return E_OUTOFMEMORY; } diff --git a/dlls/wmp/tests/Makefile.in b/dlls/wmp/tests/Makefile.in index dded3a4a7e..b4ecf3ffda 100644 --- a/dlls/wmp/tests/Makefile.in +++ b/dlls/wmp/tests/Makefile.in @@ -1,7 +1,7 @@ TESTDLL = wmp.dll IMPORTS = ole32 oleaut32 user32 gdi32
-C_SRCS = oleobj.c +C_SRCS = oleobj.c media.c
RC_SRCS = \ rsrc.rc diff --git a/dlls/wmp/tests/av.mp4 b/dlls/wmp/tests/av.mp4 deleted file mode 100644 index 1431e98dd3f5bb28c282d3d732a3a1fc13cf3d63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001
literal 1493 zcmeHHO-sW-5Z$D$cn}OyK`=rq^=7}c+G`IUJa`ik#7o*uZD_U$*=<2j`7uHf{1GDl z1OJ2v!Gm5r>6;{NZ56!et&eVJ_RZ{@-Py2=F|(~MeMfqNF`bdc*b#oM${1U02eu9V zMQ}^yjZE%({o@Y&97zZ2!~blBKX3W>_ST2tck=HTAD{cZ@Vo&eT`}nJY3bAx=4GZa z`b{u30X;KsOfrA+Qdsb;0;`MQx#~tW!HuCOUU|%5K~!R<&M$QfHdhiFrtM0VXpus! z8w+y59SdAe@Y%E99^ge_ClAreVu!myqQRus?~Q!2$C&d&tH)iNa<paP^xAL?DW*gV zJmyUv*c2zwHkSH<n@jvhshTeQ3#sJjGAQR1Zxn5mK=T+nGsvN>0=u^4bYPYW!*CPt zTN*aoSS3n(!+3qqfYDcs1sIL`ye3uDqbLP`;L_xqDBmInpmH=QpDe|$U`GJ2p{zzd z&Pvttk^tpyV>J6*S+Hlqjx2@qU;BwW2rS>HV~<gE;!E4QQ633y;7KMC5@ko$puM+W Ks#QwWO7#=93TT)B
diff --git a/dlls/wmp/tests/media.c b/dlls/wmp/tests/media.c new file mode 100644 index 0000000000..6e4a0c170f --- /dev/null +++ b/dlls/wmp/tests/media.c @@ -0,0 +1,120 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define WIN32_LEAN_AND_MEAN +#define COBJMACROS +#include <wmp.h> +#include <olectl.h> +#include <nserror.h> + +#include "wine/test.h" + +static const WCHAR mp3file[] = {'t','e','s','t','.','m','p','3',0}; +static inline WCHAR *load_resource(const WCHAR *name) +{ + static WCHAR pathW[MAX_PATH]; + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW); + lstrcatW(pathW, name); + + file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW), + GetLastError()); + + res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA); + ok( res != 0, "couldn't find resource\n" ); + ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res )); + WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL ); + ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" ); + CloseHandle( file ); + + return pathW; +} + +static void test_wmp(void) +{ + IWMPPlayer4 *player4; + IWMPControls *controls; + HRESULT hres; + BSTR filename; + + IOleObject *oleobj; + IWMPSettings *settings; + + hres = CoCreateInstance(&CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, &IID_IOleObject, (void**)&oleobj); + if(hres == REGDB_E_CLASSNOTREG) { + win_skip("CLSID_WindowsMediaPlayer not registered\n"); + return; + } + ok(hres == S_OK, "Could not create CLSID_WindowsMediaPlayer instance: %08x\n", hres); + + hres = IOleObject_QueryInterface(oleobj, &IID_IWMPPlayer4, (void**)&player4); + ok(hres == S_OK, "Could not get IWMPPlayer4 iface: %08x\n", hres); + + settings = NULL; + hres = IWMPPlayer4_get_settings(player4, &settings); + ok(hres == S_OK, "get_settings failed: %08x\n", hres); + ok(settings != NULL, "settings = NULL\n"); + + hres = IWMPSettings_put_autoStart(settings, VARIANT_FALSE); + ok(hres == S_OK, "Could not put autoStart in IWMPSettings: %08x\n", hres); + IWMPSettings_Release(settings); + + controls = NULL; + hres = IWMPPlayer4_get_controls(player4, &controls); + ok(hres == S_OK, "get_controls failed: %08x\n", hres); + ok(controls != NULL, "controls = NULL\n"); + + hres = IWMPControls_play(controls); + ok(hres == NS_S_WMPCORE_COMMAND_NOT_AVAILABLE, "IWMPControls_play is available: %08x\n", hres); + + filename = SysAllocString(load_resource(mp3file)); + + hres = IWMPPlayer4_put_URL(player4, filename); + ok(hres == S_OK, "IWMPPlayer4_put_URL failed: %08x\n", hres); + + hres = IWMPControls_play(controls); + ok(hres == S_OK, "IWMPControls_play failed: %08x\n", hres); + + hres = IWMPControls_stop(controls); + ok(hres == S_OK, "IWMPControls_stop failed: %08x\n", hres); + + /* Already Stopped */ + hres = IWMPControls_stop(controls); + ok(hres == NS_S_WMPCORE_COMMAND_NOT_AVAILABLE, "IWMPControls_stop is available: %08x\n", hres); + + hres = IWMPControls_play(controls); + ok(hres == S_OK, "IWMPControls_play failed: %08x\n", hres); + + IWMPControls_Release(controls); + IWMPPlayer4_Release(player4); + IOleObject_Release(oleobj); + DeleteFileW(filename); + SysFreeString(filename); +} + +START_TEST(media) +{ + CoInitialize(NULL); + + test_wmp(); + + CoUninitialize(); +} diff --git a/dlls/wmp/tests/oleobj.c b/dlls/wmp/tests/oleobj.c index 937960cbaf..8bcfa4827d 100644 --- a/dlls/wmp/tests/oleobj.c +++ b/dlls/wmp/tests/oleobj.c @@ -70,7 +70,7 @@ DEFINE_EXPECT(GetWindowContext); DEFINE_EXPECT(ShowObject); DEFINE_EXPECT(OnShowWindow_FALSE);
-static const WCHAR mp4file[] = {'a','v','.','m','p','4',0}; +static const WCHAR mp3file[] = {'t','e','s','t','.','m','p','3',0}; static inline WCHAR *load_resource(const WCHAR *name) { static WCHAR pathW[MAX_PATH]; @@ -942,8 +942,7 @@ static void test_wmp_ifaces(IOleObject *oleobj) ok(hres == S_FALSE, "get_currentMedia SUCCEEDED\n"); ok(media == NULL, "media != NULL\n");
- filename = SysAllocString(load_resource(mp4file)); - + filename = SysAllocString(load_resource(mp3file));
SET_EXPECT(GetContainer); SET_EXPECT(Invoke_USERMODE); @@ -1039,6 +1038,7 @@ static void test_wmp_ifaces(IOleObject *oleobj)
IWMPSettings_Release(settings); IWMPPlayer_Release(player); + DeleteFileW(filename); SysFreeString(filename); }
diff --git a/dlls/wmp/tests/rsrc.rc b/dlls/wmp/tests/rsrc.rc index fb30ae6940..f33acc1256 100644 --- a/dlls/wmp/tests/rsrc.rc +++ b/dlls/wmp/tests/rsrc.rc @@ -18,5 +18,6 @@
#include "windef.h"
-/* @makedep: av.mp4 */ -av.mp4 RCDATA "av.mp4" +/* ffmpeg -ar 48000 -t 60 -f s16le -acodec pcm_s16le -ac 2 -i /dev/zero -acodec libmp3lame -aq 4 output.mp3 */ +/* @makedep: test.mp3 */ +test.mp3 RCDATA "test.mp3" diff --git a/dlls/wmp/tests/test.mp3 b/dlls/wmp/tests/test.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..149a2cd346ee52ae179c46198ce290a5dd4d6251 GIT binary patch literal 240333 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
literal 0 HcmV?d00001
diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index e95b194d77..13ec268a86 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -22,6 +22,7 @@ #include "wine/heap.h" #include "wine/unicode.h" #include "ole2.h" +#include "dshow.h" #include "wmp.h"
typedef struct { @@ -70,11 +71,16 @@ struct WindowsMediaPlayer { ConnectionPoint *wmpocx;
IWMPMedia *wmpmedia; + + /* DirectShow stuff */ + IGraphBuilder* pFilterGraph; + IMediaControl* media_control; };
void init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; void destroy_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; -IWMPMedia* create_media_from_url(BSTR url); +WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) DECLSPEC_HIDDEN; +HRESULT create_media_from_url(BSTR url, IWMPMedia **ppMedia) DECLSPEC_HIDDEN; void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN; void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;