From bb2d13b44c5268f62356a39c52ddd70a8acb56f5 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Wed, 18 Apr 2018 22:01:46 -0700 Subject: [PATCH] wmp: Add seeking and duration. Signed-off-by: Anton Romanov Signed-off-by: Alexandre Julliard --- dlls/wmp/player.c | 65 ++++++++++++++++++++++++++++++++++++++++-------- dlls/wmp/tests/media.c | 39 ++++++++++++++++++++++++++++- dlls/wmp/tests/rsrc.rc | 2 +- dlls/wmp/tests/test.mp3 | Bin 240333 -> 24494 bytes dlls/wmp/wmp_private.h | 3 +++ 5 files changed, 97 insertions(+), 12 deletions(-) rewrite dlls/wmp/tests/test.mp3 (99%) diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index f4ce62a4479..0a6d598dc22 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -1396,8 +1396,21 @@ static HRESULT WINAPI WMPControls_Invoke(IWMPControls *iface, DISPID dispIdMembe static HRESULT WINAPI WMPControls_get_isAvailable(IWMPControls *iface, BSTR bstrItem, VARIANT_BOOL *pIsAvailable) { WindowsMediaPlayer *This = impl_from_IWMPControls(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(bstrItem)); - return E_NOTIMPL; + static const WCHAR currentPosition[] = {'c','u','r','r','e','n','t','P','o','s','i','t','i','o','n',0}; + TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrItem), pIsAvailable); + if (!This->filter_graph) { + *pIsAvailable = VARIANT_FALSE; + } else if (strcmpW(currentPosition, bstrItem) == 0) { + DWORD capabilities; + IMediaSeeking_GetCapabilities(This->media_seeking, &capabilities); + *pIsAvailable = (capabilities & AM_SEEKING_CanSeekAbsolute) ? + VARIANT_TRUE : VARIANT_FALSE; + } else { + FIXME("%s not implemented\n", debugstr_w(bstrItem)); + return E_NOTIMPL; + } + + return S_OK; } static HRESULT WINAPI WMPControls_play(IWMPControls *iface) @@ -1429,10 +1442,15 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) if (SUCCEEDED(hres)) hres = IGraphBuilder_RenderFile(This->filter_graph, media->url, NULL); if (SUCCEEDED(hres)) + update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposMediaOpen); + if (SUCCEEDED(hres)) hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaControl, (void**)&This->media_control); if (SUCCEEDED(hres)) - update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposMediaOpen); + hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaSeeking, + (void**)&This->media_seeking); + if (SUCCEEDED(hres)) + hres = IMediaSeeking_SetTimeFormat(This->media_seeking, &TIME_FORMAT_MEDIA_TIME); if (SUCCEEDED(hres)) hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaEvent, (void**)&This->media_event); @@ -1459,7 +1477,10 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) } if (SUCCEEDED(hres)) { + LONGLONG duration; update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsPlaying); + if (SUCCEEDED(IMediaSeeking_GetDuration(This->media_seeking, &duration))) + media->duration = (DOUBLE)duration / 10000000.0f; } else { update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsUndefined); } @@ -1482,11 +1503,14 @@ static HRESULT WINAPI WMPControls_stop(IWMPControls *iface) if (This->media_event) { IMediaEvent_Release(This->media_event); } - + if (This->media_seeking) { + IMediaSeeking_Release(This->media_seeking); + } IGraphBuilder_Release(This->filter_graph); This->filter_graph = NULL; This->media_control = NULL; This->media_event = NULL; + This->media_seeking = NULL; update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistOpenNoMedia); update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsStopped); @@ -1517,15 +1541,33 @@ static HRESULT WINAPI WMPControls_fastReverse(IWMPControls *iface) static HRESULT WINAPI WMPControls_get_currentPosition(IWMPControls *iface, DOUBLE *pdCurrentPosition) { WindowsMediaPlayer *This = impl_from_IWMPControls(iface); - FIXME("(%p)->(%p)\n", This, pdCurrentPosition); - return E_NOTIMPL; + HRESULT hres; + LONGLONG currentPosition; + + TRACE("(%p)->(%p)\n", This, pdCurrentPosition); + if (!This->media_seeking) + return S_FALSE; + + hres = IMediaSeeking_GetCurrentPosition(This->media_seeking, ¤tPosition); + *pdCurrentPosition = (DOUBLE) currentPosition / 10000000.0f; + TRACE("hres: %d, pos: %f\n", hres, *pdCurrentPosition); + return hres; } static HRESULT WINAPI WMPControls_put_currentPosition(IWMPControls *iface, DOUBLE dCurrentPosition) { + LONGLONG Current; + HRESULT hres; WindowsMediaPlayer *This = impl_from_IWMPControls(iface); - FIXME("(%p)->(%f)\n", This, dCurrentPosition); - return E_NOTIMPL; + TRACE("(%p)->(%f)\n", This, dCurrentPosition); + if (!This->media_seeking) + return S_FALSE; + + Current = 10000000 * dCurrentPosition; + hres = IMediaSeeking_SetPositions(This->media_seeking, &Current, + AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); + + return hres; } static HRESULT WINAPI WMPControls_get_currentPositionString(IWMPControls *iface, BSTR *pbstrCurrentPosition) @@ -1762,9 +1804,12 @@ static HRESULT WINAPI WMPMedia_getMarkerName(IWMPMedia *iface, LONG MarkerNum, B static HRESULT WINAPI WMPMedia_get_duration(IWMPMedia *iface, DOUBLE *pDuration) { + /* MSDN: If this property is used with a media item other than the one + * specified in Player.currentMedia, it may not contain a valid value. */ WMPMedia *This = impl_from_IWMPMedia(iface); - FIXME("(%p)->(%p)\n", This, pDuration); - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", This, pDuration); + *pDuration = This->duration; + return S_OK; } static HRESULT WINAPI WMPMedia_get_durationString(IWMPMedia *iface, BSTR *pbstrDuration) diff --git a/dlls/wmp/tests/media.c b/dlls/wmp/tests/media.c index c2cd1cf9412..2372763d254 100644 --- a/dlls/wmp/tests/media.c +++ b/dlls/wmp/tests/media.c @@ -303,6 +303,11 @@ static BOOL test_wmp(void) static DWORD dw = 100; IWMPSettings *settings; BOOL test_ran = TRUE; + DOUBLE duration; + VARIANT_BOOL vbool; + IWMPMedia *media; + static const WCHAR currentPosition[] = {'c','u','r','r','e','n','t','P','o','s','i','t','i','o','n',0}; + BSTR bstrcurrentPosition = SysAllocString(currentPosition); hres = CoCreateInstance(&CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, &IID_IOleObject, (void**)&oleobj); if(hres == REGDB_E_CLASSNOTREG) { @@ -338,6 +343,10 @@ static BOOL test_wmp(void) ok(hres == S_OK, "get_controls failed: %08x\n", hres); ok(controls != NULL, "controls = NULL\n"); + hres = IWMPControls_get_isAvailable(controls, bstrcurrentPosition, &vbool); + ok(hres == S_OK, "IWMPControls_get_isAvailable failed: %08x\n", hres); + ok(vbool == VARIANT_FALSE, "unexpected value\n"); + hres = IWMPControls_play(controls); ok(hres == NS_S_WMPCORE_COMMAND_NOT_AVAILABLE, "IWMPControls_play is available: %08x\n", hres); @@ -364,7 +373,7 @@ static BOOL test_wmp(void) SET_EXPECT(OPENSTATE, wmposMediaOpening); hres = IWMPControls_play(controls); ok(hres == S_OK, "IWMPControls_play failed: %08x\n", hres); - res = pump_messages(5000, 1, &playing_event); + res = pump_messages(1000, 1, &playing_event); ok(res == WAIT_OBJECT_0 || broken(res == WAIT_TIMEOUT), "Timed out while waiting for media to become ready\n"); if (res == WAIT_TIMEOUT) { /* This happens on Vista Ultimate 64 vms @@ -380,6 +389,33 @@ static BOOL test_wmp(void) /* MediaOpening happens only on xp, 2003 */ CLEAR_CALLED(OPENSTATE, wmposMediaOpening); + hres = IWMPControls_get_isAvailable(controls, bstrcurrentPosition, &vbool); + ok(hres == S_OK, "IWMPControls_get_isAvailable failed: %08x\n", hres); + ok(vbool == VARIANT_TRUE, "unexpected value\n"); + + duration = 0.0; + hres = IWMPControls_get_currentPosition(controls, &duration); + ok(hres == S_OK, "IWMPControls_get_currentPosition failed: %08x\n", hres); + ok((int)duration == 0, "unexpected value %f\n", duration); + + duration = 1.1; + hres = IWMPControls_put_currentPosition(controls, duration); + ok(hres == S_OK, "IWMPControls_put_currentPosition failed: %08x\n", hres); + + duration = 0.0; + hres = IWMPControls_get_currentPosition(controls, &duration); + ok(hres == S_OK, "IWMPControls_get_currentPosition failed: %08x\n", hres); + /* builtin quartz does not handle this currently and resets to 0.0, works + * with native quartz */ + todo_wine ok(duration >= 1.05 /* save some fp errors */, "unexpected value %f\n", duration); + + hres = IWMPPlayer4_get_currentMedia(player4, &media); + ok(hres == S_OK, "IWMPPlayer4_get_currentMedia failed: %08x\n", hres); + hres = IWMPMedia_get_duration(media, &duration); + ok(hres == S_OK, "IWMPMedia_get_duration failed: %08x\n", hres); + ok(round(duration) == 3, "unexpected value: %f\n", duration); + IWMPMedia_Release(media); + SET_EXPECT(PLAYSTATE, wmppsStopped); /* The following happens on wine only since we close media on stop */ SET_EXPECT(OPENSTATE, wmposPlaylistOpenNoMedia); @@ -414,6 +450,7 @@ playback_skip: IOleObject_Release(oleobj); DeleteFileW(filename); SysFreeString(filename); + SysFreeString(bstrcurrentPosition); return test_ran; } diff --git a/dlls/wmp/tests/rsrc.rc b/dlls/wmp/tests/rsrc.rc index a92079e798b..c781df97a45 100644 --- a/dlls/wmp/tests/rsrc.rc +++ b/dlls/wmp/tests/rsrc.rc @@ -18,7 +18,7 @@ #include "windef.h" -/* ffmpeg -ar 48000 -t 60 -f s16le -acodec pcm_s16le -ac 2 -i /dev/zero -acodec libmp3lame -aq 4 output.mp3 */ +/* ffmpeg -f lavfi -i anullsrc -t 3 -acodec libmp3lame -b:a 64k dlls/wmp/tests/test.mp3 */ /* @makedep: test.mp3 */ test.mp3 RCDATA "test.mp3" /* ffmpeg -ar 48000 -t 1 -f s16le -acodec pcm_s16le -ac 2 -i /dev/zero -acodec libmp3lame -aq 4 test1s.mp3 */ diff --git a/dlls/wmp/tests/test.mp3 b/dlls/wmp/tests/test.mp3 dissimilarity index 99% index 149a2cd346ee52ae179c46198ce290a5dd4d6251..5328ce2425e41393626cf01a5423d828471f469f 100644 GIT binary patch literal 24494 zcwX(=Uqqd89LMo*E0f64#h6T@B`f8mR*}i9(wVb4YELtxKROOcbx|@&Iwl!YT_lq1 zCbKfSND{M)88b7xnIy4`NhC8_W{zpkX=dpr-F)giz26?5-;c-hd|%IV`vj^>QY>E1 zy@rMw_v|xE4z~71u9p{8loS>F{r128Sjdhm&=u*ngWFiIS##7brlzI)GA>=typolj zn|H0C&|g|sQF){4R&Cww;N6gO|G~qimT;uKqqDoG?@|B2;N#(uCr?MmCnl$+XP(VI ze=+}ZVR31B<<;vqZ{NND@bS~<)wT7FFJCvews*em?*04~`yGF-J9C>mbMfJM?dpXe ze;3Ws#z21I(OF$j*nHp3+TBg6S$eivl6%a$TX$JHWR?=Vd8fv4ocQVBbvS3Z{aAgt z@fgp)YZC@E2j~n32#`2HfW!d;Bn}WDaex4c0|ZDMAVA^(0TKrYkT^hq!~p^%4iF%5 zfB=aD1W4R@1|@{Yi=a?=Zp=HN6MP^*rxGAQ;s5~>2MCZjK!C&n0wfL)AaQ^Ii30>k z93VjA009yQ2#`2HfW!d;Bn}WDaezDoN(he^LHz#*NEskN;s5~>2MCZjK!C)ZYfwVu GInW;%f6a3M literal 240333 zcwX(#f23b!9Ki9X?qbDUG9u}RRz$8{>&K{A>e8}_cCVPoG*>Z8VkTl#Br%a9NhwK^ zs7OR&B9Rh_#6(79B+}&ey;sy9d*9nX-+%IYJ3Qw($9X-Uv-|cPo5pHaF7Dg6Fj;5E znAvmS$ny0!&h6YWH@|)R_@|XKi({j9A6|ZFtTE@G7&C9ZGG@-(e8HC43%6c$@guAQ6Tal_7=ZrOF)!X0<+z3cA9d-mUZ-+_b64;(uD@FPc#KKj_P$De%a>1U2V z``imJzVz~|uf6f++wZ*l-UlCk^zkR3p7`wZFTVWhn{U7S{)dx4{&ec+Urzt}+wXt; zxq9wo=KCiz&;NVgvF+SlYwKi=m8+gOwQ^?b!7+P!j0Y#rHjlC8@-fbtT(3{IliTZ# zjj?IZt$P>N{(I>xt^0CmY1O}U1OMz_{@s7@Z=SNhf6D&RDf`b)*?)h^{?}9XPafy< zBR-$culRgEzvA=x{EE-#^D91|&#(A=KELAg`TUB{=kqH*pU