Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/oleobj.c | 26 +++++---- dlls/wmp/player.c | 92 ++++++++++++++++++++++++++++++- dlls/wmp/tests/media.c | 113 ++++++++++++++++++++++++++++++++++---- dlls/wmp/tests/rsrc.rc | 3 + dlls/wmp/tests/test1s.mp3 | Bin 0 -> 4365 bytes dlls/wmp/wmp_main.c | 1 + dlls/wmp/wmp_private.h | 7 ++- 7 files changed, 216 insertions(+), 26 deletions(-) create mode 100644 dlls/wmp/tests/test1s.mp3
diff --git a/dlls/wmp/oleobj.c b/dlls/wmp/oleobj.c index cbf183c1f6..a90a0c2c6c 100644 --- a/dlls/wmp/oleobj.c +++ b/dlls/wmp/oleobj.c @@ -899,18 +899,20 @@ HRESULT WINAPI WMPFactory_CreateInstance(IClassFactory *iface, IUnknown *outer,
wmp->ref = 1;
- init_player(wmp); - - ConnectionPointContainer_Init(wmp); - hdc = GetDC(0); - dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); - dpi_y = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(0, hdc); - - wmp->extent.cx = MulDiv(192, 2540, dpi_x); - wmp->extent.cy = MulDiv(192, 2540, dpi_y); - - hres = IOleObject_QueryInterface(&wmp->IOleObject_iface, riid, ppv); + if (init_player(wmp)) { + ConnectionPointContainer_Init(wmp); + hdc = GetDC(0); + dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); + dpi_y = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(0, hdc); + + wmp->extent.cx = MulDiv(192, 2540, dpi_x); + wmp->extent.cy = MulDiv(192, 2540, dpi_y); + + hres = IOleObject_QueryInterface(&wmp->IOleObject_iface, riid, ppv); + } else { + hres = E_FAIL; + } IOleObject_Release(&wmp->IOleObject_iface); return hres; } diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index 8e01200788..f4ce62a447 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -24,6 +24,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(wmp);
+static ATOM player_msg_class; +static INIT_ONCE class_init_once; +static UINT WM_WMPEVENT; +static const WCHAR WMPmessageW[] = {'_', 'W', 'M', 'P', 'M','e','s','s','a','g','e',0}; + + static void update_state(WindowsMediaPlayer *wmp, LONG type, LONG state) { DISPPARAMS dispparams; @@ -212,18 +218,20 @@ static HRESULT WINAPI WMPPlayer4_put_currentMedia(IWMPPlayer4 *iface, IWMPMedia { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); TRACE("(%p)->(%p)\n", This, pMedia); + if(pMedia == NULL) { return E_POINTER; } update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistChanging); if(This->wmpmedia != NULL) { + IWMPControls_stop(&This->IWMPControls_iface); IWMPMedia_Release(This->wmpmedia); } update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistChanged); update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistOpenNoMedia);
+ IWMPMedia_AddRef(pMedia); This->wmpmedia = pMedia; - IWMPMedia_AddRef(This->wmpmedia); return S_OK; }
@@ -1425,6 +1433,20 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) (void**)&This->media_control); if (SUCCEEDED(hres)) update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposMediaOpen); + if (SUCCEEDED(hres)) + hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaEvent, + (void**)&This->media_event); + if (SUCCEEDED(hres)) + { + IMediaEventEx *media_event_ex = NULL; + hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaEventEx, + (void**)&media_event_ex); + if (SUCCEEDED(hres)) { + hres = IMediaEventEx_SetNotifyWindow(media_event_ex, (OAHWND)This->msg_window, + WM_WMPEVENT, (LONG_PTR)This); + IMediaEventEx_Release(media_event_ex); + } + } }
update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsTransitioning); @@ -1457,9 +1479,15 @@ static HRESULT WINAPI WMPControls_stop(IWMPControls *iface) hres = IMediaControl_Stop(This->media_control); IMediaControl_Release(This->media_control); } + if (This->media_event) { + IMediaEvent_Release(This->media_event); + } + IGraphBuilder_Release(This->filter_graph); This->filter_graph = NULL; This->media_control = NULL; + This->media_event = NULL; + update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistOpenNoMedia); update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsStopped); return hres; @@ -1823,8 +1851,66 @@ static const IWMPMediaVtbl WMPMediaVtbl = { WMPMedia_isReadOnlyItem };
-void init_player(WindowsMediaPlayer *wmp) +static LRESULT WINAPI player_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_WMPEVENT && wParam == 0) { + WindowsMediaPlayer *wmp = (WindowsMediaPlayer*)lParam; + LONG event_code; + LONG_PTR p1, p2; + HRESULT hr; + if (wmp->media_event) { + do { + hr = IMediaEvent_GetEvent(wmp->media_event, &event_code, &p1, &p2, 0); + if (SUCCEEDED(hr)) { + TRACE("got event_code = 0x%02x\n", event_code); + IMediaEvent_FreeEventParams(wmp->media_event, event_code, p1, p2); + /* For now we only handle EC_COMPLETE */ + if (event_code == EC_COMPLETE) { + update_state(wmp, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsMediaEnded); + update_state(wmp, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsTransitioning); + update_state(wmp, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsStopped); + } + } + } while (hr == S_OK); + } else { + FIXME("Got event from quartz when interfaces are already released\n"); + } + } + return DefWindowProcW(hwnd, msg, wParam, lParam); +} + +static BOOL WINAPI register_player_msg_class(INIT_ONCE *once, void *param, void **context) { + static WNDCLASSEXW wndclass = { + sizeof(wndclass), CS_DBLCLKS, player_wnd_proc, 0, 0, + NULL, NULL, NULL, NULL, NULL, + WMPmessageW, NULL + }; + + wndclass.hInstance = wmp_instance; + player_msg_class = RegisterClassExW(&wndclass); + WM_WMPEVENT= RegisterWindowMessageW(WMPmessageW); + return TRUE; +} + +void unregister_player_msg_class(void) { + if(player_msg_class) + UnregisterClassW(MAKEINTRESOURCEW(player_msg_class), wmp_instance); +} + +BOOL init_player(WindowsMediaPlayer *wmp) { + 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 ); + if (!wmp->msg_window) { + ERR("Failed to create message window, GetLastError: %d\n", GetLastError()); + return FALSE; + } + if (!WM_WMPEVENT) { + ERR("Failed to register window message, GetLastError: %d\n", GetLastError()); + return FALSE; + } + wmp->IWMPPlayer4_iface.lpVtbl = &WMPPlayer4Vtbl; wmp->IWMPPlayer_iface.lpVtbl = &WMPPlayerVtbl; wmp->IWMPSettings_iface.lpVtbl = &WMPSettingsVtbl; @@ -1833,6 +1919,7 @@ void init_player(WindowsMediaPlayer *wmp)
wmp->invoke_urls = VARIANT_TRUE; wmp->auto_start = VARIANT_TRUE; + return TRUE; }
void destroy_player(WindowsMediaPlayer *wmp) @@ -1840,6 +1927,7 @@ void destroy_player(WindowsMediaPlayer *wmp) IWMPControls_stop(&wmp->IWMPControls_iface); if(wmp->wmpmedia) IWMPMedia_Release(wmp->wmpmedia); + DestroyWindow(wmp->msg_window); }
WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) diff --git a/dlls/wmp/tests/media.c b/dlls/wmp/tests/media.c index a7f611c826..f8201813b0 100644 --- a/dlls/wmp/tests/media.c +++ b/dlls/wmp/tests/media.c @@ -40,16 +40,15 @@ called_ ## kind |= (1 << index); \ }while(0)
-#define CHECK_CALLED(kind, index) \ +#define CLEAR_CALLED(kind, index) \ do { \ - ok(called_ ## kind & (1 << index), "expected " #kind ", %d\n", index); \ expect_ ## kind &= ~(1 << index); \ called_ ## kind &= ~(1 << index); \ }while(0)
-#define CHECK_CALLED_OR_BROKEN(kind, index) \ +#define CHECK_CALLED(kind, index) \ do { \ - ok(called_ ## kind & (1 << index) || broken(1), "expected " #kind ", %d\n", index); \ + ok(called_ ## kind & (1 << index), "expected " #kind ", %d\n", index); \ expect_ ## kind &= ~(1 << index); \ called_ ## kind &= ~(1 << index); \ }while(0) @@ -65,9 +64,11 @@ DEFINE_EXPECT(PLAYSTATE); DEFINE_EXPECT(OPENSTATE);
static HANDLE playing_event; +static HANDLE completed_event; static DWORD main_thread_id;
static const WCHAR mp3file[] = {'t','e','s','t','.','m','p','3',0}; +static const WCHAR mp3file1s[] = {'t','e','s','t','1','s','.','m','p','3',0}; static inline WCHAR *load_resource(const WCHAR *name) { static WCHAR pathW[MAX_PATH]; @@ -151,6 +152,8 @@ static HRESULT WINAPI WMPOCXEvents_Invoke(IDispatch *iface, DISPID dispIdMember, CHECK_EXPECT(PLAYSTATE, V_UI4(pDispParams->rgvarg)); if (V_UI4(pDispParams->rgvarg) == wmppsPlaying) { SetEvent(playing_event); + } else if (V_UI4(pDispParams->rgvarg) == wmppsMediaEnded) { + SetEvent(completed_event); } if (winetest_debug > 1) trace("DISPID_WMPCOREEVENT_PLAYSTATECHANGE, %d\n", V_UI4(pDispParams->rgvarg)); @@ -208,18 +211,16 @@ static HRESULT pump_messages(DWORD timeout, DWORD count, const HANDLE *handles) return res; }
-static void test_wmp(void) +static void test_completion_event(void) { DWORD res = 0; IWMPPlayer4 *player4; - IWMPControls *controls; HRESULT hres; BSTR filename; IConnectionPointContainer *container; IConnectionPoint *point; IOleObject *oleobj; static DWORD dw = 100; - IWMPSettings *settings;
hres = CoCreateInstance(&CLSID_WindowsMediaPlayer, NULL, CLSCTX_INPROC_SERVER, &IID_IOleObject, (void**)&oleobj); if(hres == REGDB_E_CLASSNOTREG) { @@ -243,6 +244,86 @@ static void test_wmp(void) hres = IOleObject_QueryInterface(oleobj, &IID_IWMPPlayer4, (void**)&player4); ok(hres == S_OK, "Could not get IWMPPlayer4 iface: %08x\n", hres);
+ filename = SysAllocString(load_resource(mp3file1s)); + + SET_EXPECT(OPENSTATE, wmposPlaylistChanging); + SET_EXPECT(OPENSTATE, wmposPlaylistOpenNoMedia); + SET_EXPECT(OPENSTATE, wmposPlaylistChanged); + SET_EXPECT(OPENSTATE, wmposOpeningUnknownURL); + SET_EXPECT(OPENSTATE, wmposMediaOpen); + SET_EXPECT(OPENSTATE, wmposMediaOpening); + SET_EXPECT(PLAYSTATE, wmppsPlaying); + SET_EXPECT(PLAYSTATE, wmppsMediaEnded); + SET_EXPECT(PLAYSTATE, wmppsStopped); + SET_EXPECT(PLAYSTATE, wmppsTransitioning); + /* following two are sent on vistau64 vms only */ + SET_EXPECT(OPENSTATE, wmposMediaChanging); + SET_EXPECT(PLAYSTATE, wmppsReady); + hres = IWMPPlayer4_put_URL(player4, filename); + ok(hres == S_OK, "IWMPPlayer4_put_URL failed: %08x\n", hres); + res = pump_messages(3000, 1, &completed_event); + ok(res == WAIT_OBJECT_0, "Timed out while waiting for media to complete\n"); + + /* following two are sent on vistau64 vms only */ + CLEAR_CALLED(OPENSTATE, wmposMediaChanging); + CLEAR_CALLED(PLAYSTATE, wmppsReady); + + CHECK_CALLED(OPENSTATE, wmposPlaylistChanging); + CHECK_CALLED(OPENSTATE, wmposPlaylistChanged); + CHECK_CALLED(OPENSTATE, wmposPlaylistOpenNoMedia); + CHECK_CALLED(PLAYSTATE, wmppsTransitioning); + CHECK_CALLED(OPENSTATE, wmposOpeningUnknownURL); + CHECK_CALLED(OPENSTATE, wmposMediaOpen); + CHECK_CALLED(PLAYSTATE, wmppsPlaying); + CHECK_CALLED(PLAYSTATE, wmppsMediaEnded); + CHECK_CALLED(PLAYSTATE, wmppsStopped); + /* MediaOpening happens only on xp, 2003 */ + CLEAR_CALLED(OPENSTATE, wmposMediaOpening); + + hres = IConnectionPoint_Unadvise(point, dw); + ok(hres == S_OK, "Unadvise failed: %08x\n", hres); + + IConnectionPoint_Release(point); + IWMPPlayer4_Release(player4); + IOleObject_Release(oleobj); + DeleteFileW(filename); + SysFreeString(filename); +} + +static BOOL test_wmp(void) +{ + DWORD res = 0; + IWMPPlayer4 *player4; + IWMPControls *controls; + HRESULT hres; + BSTR filename; + IConnectionPointContainer *container; + IConnectionPoint *point; + IOleObject *oleobj; + static DWORD dw = 100; + IWMPSettings *settings; + BOOL test_ran = TRUE; + + 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 FALSE; + } + ok(hres == S_OK, "Could not create CLSID_WindowsMediaPlayer instance: %08x\n", hres); + + hres = IOleObject_QueryInterface(oleobj, &IID_IConnectionPointContainer, (void**)&container); + ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres); + + hres = IConnectionPointContainer_FindConnectionPoint(container, &IID__WMPOCXEvents, &point); + IConnectionPointContainer_Release(container); + ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); + + hres = IConnectionPoint_Advise(point, (IUnknown*)&WMPOCXEvents, &dw); + ok(hres == S_OK, "Advise failed: %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); @@ -277,9 +358,10 @@ static void test_wmp(void)
SET_EXPECT(OPENSTATE, wmposOpeningUnknownURL); SET_EXPECT(OPENSTATE, wmposMediaOpen); - SET_EXPECT(OPENSTATE, wmposMediaOpening); SET_EXPECT(PLAYSTATE, wmppsPlaying); SET_EXPECT(PLAYSTATE, wmppsTransitioning); + /* MediaOpening happens only on xp, 2003 */ + 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); @@ -288,14 +370,15 @@ static void test_wmp(void) /* This happens on Vista Ultimate 64 vms * I have been unable to find out source of this behaviour */ win_skip("Failed to transition media to playing state.\n"); + test_ran = FALSE; goto playback_skip; } CHECK_CALLED(OPENSTATE, wmposOpeningUnknownURL); CHECK_CALLED(OPENSTATE, wmposMediaOpen); - /* MediaOpening happens only on xp, 2003 */ - todo_wine CHECK_CALLED_OR_BROKEN(OPENSTATE, wmposMediaOpening); CHECK_CALLED(PLAYSTATE, wmppsPlaying); CHECK_CALLED(PLAYSTATE, wmppsTransitioning); + /* MediaOpening happens only on xp, 2003 */ + CLEAR_CALLED(OPENSTATE, wmposMediaOpening);
SET_EXPECT(PLAYSTATE, wmppsStopped); /* The following happens on wine only since we close media on stop */ @@ -331,6 +414,8 @@ playback_skip: IOleObject_Release(oleobj); DeleteFileW(filename); SysFreeString(filename); + + return test_ran; }
START_TEST(media) @@ -339,9 +424,15 @@ START_TEST(media)
main_thread_id = GetCurrentThreadId(); playing_event = CreateEventW(NULL, FALSE, FALSE, NULL); - test_wmp(); + completed_event = CreateEventW(NULL, FALSE, FALSE, NULL); + if (test_wmp()) { + test_completion_event(); + } else { + win_skip("Failed to play media\n"); + }
CloseHandle(playing_event); + CloseHandle(completed_event);
CoUninitialize(); } diff --git a/dlls/wmp/tests/rsrc.rc b/dlls/wmp/tests/rsrc.rc index f33acc1256..ea25a2dea1 100644 --- a/dlls/wmp/tests/rsrc.rc +++ b/dlls/wmp/tests/rsrc.rc @@ -21,3 +21,6 @@ /* 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" +/* ffmpeg -ar 48000 -t 1 -f s16le -acodec pcm_s16le -ac 2 -i /dev/zero -acodec libmp3lame -aq 4 dlls/wmp/tests/test1s.mp3 */ +/* @makedep: test1s.mp3 */ +test1s.mp3 RCDATA "test1s.mp3" diff --git a/dlls/wmp/tests/test1s.mp3 b/dlls/wmp/tests/test1s.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..3e0b407e3fb8b292bf47fdb383a42b66d06d5568 GIT binary patch literal 4365 zcmeZtF=k-^0p*b3U{@f`&%nU!lUSB!YOZHttY>Io0G5Ri|9^)d@vt*J^V0HxGC*S( zv>6x#9xw<Biiyd{C@CqatLy3-8yj0#*x9+bxOjT{`-g^xMn@+kq@|_h<P;W`mzUSp zHZ^s0boBL2o;-8r%=z<|ELpW`)rJk*w(Z`%`{2Rj$IqNObLrBJ8+Y&Cef;?4%XjbI zefje1*Z=<@mjK<I40N+0vU?d+m=A#DK<=10|Dfvs-y$gt{2v$?GJ!%I3=F&q3=E7w zv;@cnGEEv77+8E9eO<x+209J{;FSyw1(`2Lz<dldkp+k_--gEKN72~)3L2X~jmGA0 zp|SawXl(w&e*EblIXPmmiAbNL=7S1NjF1BhfXau_@EHvs?5P7NI-0*&aE1*?Vl;e4 m!)LVq8m(V&6%wQ6!@!mgxZ(vWPI3EZ)O`H$I~qO|g%1GKzMp&m
literal 0 HcmV?d00001
diff --git a/dlls/wmp/wmp_main.c b/dlls/wmp/wmp_main.c index 9a33b2762b..273d193e58 100644 --- a/dlls/wmp/wmp_main.c +++ b/dlls/wmp/wmp_main.c @@ -92,6 +92,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) break; case DLL_PROCESS_DETACH: unregister_wmp_class(); + unregister_player_msg_class(); break; }
diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 9e84d56ea8..3792e52abd 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -75,9 +75,13 @@ struct WindowsMediaPlayer { /* DirectShow stuff */ IGraphBuilder* filter_graph; IMediaControl* media_control; + IMediaEvent* media_event; + + /* Async event notification */ + HWND msg_window; };
-void init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; +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; @@ -88,6 +92,7 @@ void call_sink(ConnectionPoint *This, DISPID dispid, DISPPARAMS *dispparams) DEC HRESULT WINAPI WMPFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
void unregister_wmp_class(void) DECLSPEC_HIDDEN; +void unregister_player_msg_class(void) DECLSPEC_HIDDEN;
extern HINSTANCE wmp_instance DECLSPEC_HIDDEN;
Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/player.c | 66 +++++++++++++++++++++++++++++++++++------- dlls/wmp/tests/media.c | 33 +++++++++++++++++++++ dlls/wmp/wmp_private.h | 3 ++ 3 files changed, 92 insertions(+), 10 deletions(-)
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index f4ce62a447..bd7e2f7184 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -1396,8 +1396,22 @@ 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); + *pIsAvailable = VARIANT_FALSE; + 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) @@ -1428,11 +1442,16 @@ 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 +1478,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 +1504,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 +1542,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 +1805,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 f8201813b0..396d11d53a 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);
@@ -380,6 +389,29 @@ 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); + + hres = IWMPControls_put_currentPosition(controls, duration); + ok(hres == S_OK, "IWMPControls_put_currentPosition failed: %08x\n", hres); + + 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) == 60 || + broken(round(duration) == 30) || + broken(round(duration) == 57) + , "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 +446,7 @@ playback_skip: IOleObject_Release(oleobj); DeleteFileW(filename); SysFreeString(filename); + SysFreeString(bstrcurrentPosition);
return test_ran; } diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 3792e52abd..e8d534803f 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -42,6 +42,8 @@ typedef struct { LONG ref;
WCHAR *url; + + DOUBLE duration; } WMPMedia;
struct WindowsMediaPlayer { @@ -76,6 +78,7 @@ struct WindowsMediaPlayer { IGraphBuilder* filter_graph; IMediaControl* media_control; IMediaEvent* media_event; + IMediaSeeking* media_seeking;
/* Async event notification */ HWND msg_window;
Hi Anton,
On 04/13/2018 07:55 AM, Anton Romanov wrote:
Signed-off-by: Anton Romanov theli.ua@gmail.com
dlls/wmp/player.c | 66 +++++++++++++++++++++++++++++++++++------- dlls/wmp/tests/media.c | 33 +++++++++++++++++++++ dlls/wmp/wmp_private.h | 3 ++ 3 files changed, 92 insertions(+), 10 deletions(-)
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index f4ce62a447..bd7e2f7184 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -1396,8 +1396,22 @@ 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);
- *pIsAvailable = VARIANT_FALSE;
This is not needed, you set it anyway below.
- 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;
}
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);
- hres = IWMPControls_put_currentPosition(controls, duration);
- ok(hres == S_OK, "IWMPControls_put_currentPosition failed: %08x\n", hres);
It would be more interesting to set currentPosition to something different.
- 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) == 60 ||
broken(round(duration) == 30) ||
broken(round(duration) == 57)
, "unexpected value: %f\n", duration);
Indention looks weird here.
Thanks, Jacek
Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/player.c | 27 +++++++++++++++++++++++---- dlls/wmp/tests/media.c | 16 ++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index bd7e2f7184..e9442abc8e 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -1150,8 +1150,17 @@ static HRESULT WINAPI WMPNetwork_get_bufferingCount(IWMPNetwork *iface, LONG *pl static HRESULT WINAPI WMPNetwork_get_bufferingProgress(IWMPNetwork *iface, LONG *plBufferingProgress) { WindowsMediaPlayer *This = impl_from_IWMPNetwork(iface); - FIXME("(%p)->(%p)\n", This, plBufferingProgress); - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", This, plBufferingProgress); + if (!This->filter_graph) { + return S_FALSE; + } + /* Ideally we would use IAMOpenProgress for URL reader but we don't have it in wine (yet) + * For file sources FileAsyncReader->Length should work + * */ + FIXME("stub: Returning buffering progress 100\n"); + *plBufferingProgress = 100; + + return S_OK; }
static HRESULT WINAPI WMPNetwork_get_bufferingTime(IWMPNetwork *iface, LONG *plBufferingTime) @@ -1276,8 +1285,18 @@ static HRESULT WINAPI WMPNetwork_put_maxBandwidth(IWMPNetwork *iface, LONG lMaxB static HRESULT WINAPI WMPNetwork_get_downloadProgress(IWMPNetwork *iface, LONG *plDownloadProgress) { WindowsMediaPlayer *This = impl_from_IWMPNetwork(iface); - FIXME("(%p)->(%p)\n", This, plDownloadProgress); - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", This, plDownloadProgress); + if (!This->filter_graph) { + return S_FALSE; + } + /* Ideally we would use IAMOpenProgress for URL reader but we don't have it in wine (yet) + * For file sources FileAsyncReader->Length could work or it should just be + * 100 + * */ + FIXME("stub: Returning download progress 100\n"); + *plDownloadProgress = 100; + + return S_OK; }
static HRESULT WINAPI WMPNetwork_get_encodedFrameRate(IWMPNetwork *iface, LONG *plFrameRate) diff --git a/dlls/wmp/tests/media.c b/dlls/wmp/tests/media.c index 396d11d53a..2c4fe2cedb 100644 --- a/dlls/wmp/tests/media.c +++ b/dlls/wmp/tests/media.c @@ -303,8 +303,10 @@ static BOOL test_wmp(void) static DWORD dw = 100; IWMPSettings *settings; BOOL test_ran = TRUE; + IWMPNetwork *network; DOUBLE duration; VARIANT_BOOL vbool; + LONG progress; 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); @@ -412,6 +414,20 @@ static BOOL test_wmp(void) , "unexpected value: %f\n", duration); IWMPMedia_Release(media);
+ network = NULL; + hres = IWMPPlayer4_get_network(player4, &network); + ok(hres == S_OK, "get_network failed: %08x\n", hres); + ok(network != NULL, "network = NULL\n"); + progress = 0; + hres = IWMPNetwork_get_bufferingProgress(network, &progress); + ok(hres == S_OK || broken(hres == S_FALSE), "IWMPNetwork_get_bufferingProgress failed: %08x\n", hres); + ok(progress == 100, "unexpected value: %d\n", progress); + progress = 0; + hres = IWMPNetwork_get_downloadProgress(network, &progress); + ok(hres == S_OK, "IWMPNetwork_get_downloadProgress failed: %08x\n", hres); + ok(progress == 100, "unexpected value: %d\n", progress); + IWMPNetwork_Release(network); + SET_EXPECT(PLAYSTATE, wmppsStopped); /* The following happens on wine only since we close media on stop */ SET_EXPECT(OPENSTATE, wmposPlaylistOpenNoMedia);
Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/player.c | 30 ++++++++++++++++++++++++++---- dlls/wmp/tests/media.c | 8 +++++++- dlls/wmp/wmp_private.h | 1 + 3 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index e9442abc8e..480e1bb42b 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -957,16 +957,32 @@ static HRESULT WINAPI WMPSettings_put_balance(IWMPSettings *iface, LONG v)
static HRESULT WINAPI WMPSettings_get_volume(IWMPSettings *iface, LONG *p) { + HRESULT hres; WindowsMediaPlayer *This = impl_from_IWMPSettings(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", This, p); + if (!This->filter_graph) { + return S_FALSE; + } + hres = IBasicAudio_get_Volume(This->basic_audio, p); + /* IBasicAudio - [-10000, 0], wmp - [0, 100] */ + if (SUCCEEDED(hres)) + *p = (*p + 10000) * 100 / 10000; + return hres; }
static HRESULT WINAPI WMPSettings_put_volume(IWMPSettings *iface, LONG v) { + HRESULT hres; WindowsMediaPlayer *This = impl_from_IWMPSettings(iface); - FIXME("(%p)->(%d)\n", This, v); - return E_NOTIMPL; + TRACE("(%p)->(%d)\n", This, v); + if (!This->filter_graph) { + return S_FALSE; + } + /* IBasicAudio - [-10000, 0], wmp - [0, 100] */ + v = 10000 * v / 100 - 10000; + hres = IBasicAudio_put_Volume(This->basic_audio, v); + TRACE("ret: %d", hres); + return hres; }
static HRESULT WINAPI WMPSettings_getMode(IWMPSettings *iface, BSTR mode, VARIANT_BOOL *p) @@ -1485,6 +1501,8 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) IMediaEventEx_Release(media_event_ex); } } + if (SUCCEEDED(hres)) + hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IBasicAudio, (void**)&This->basic_audio); }
update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsTransitioning); @@ -1526,11 +1544,15 @@ static HRESULT WINAPI WMPControls_stop(IWMPControls *iface) if (This->media_seeking) { IMediaSeeking_Release(This->media_seeking); } + if (This->basic_audio) { + IBasicAudio_Release(This->basic_audio); + } IGraphBuilder_Release(This->filter_graph); This->filter_graph = NULL; This->media_control = NULL; This->media_event = NULL; This->media_seeking = NULL; + This->basic_audio = NULL;
update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, wmposPlaylistOpenNoMedia); update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, wmppsStopped); diff --git a/dlls/wmp/tests/media.c b/dlls/wmp/tests/media.c index 2c4fe2cedb..5200e27ab7 100644 --- a/dlls/wmp/tests/media.c +++ b/dlls/wmp/tests/media.c @@ -338,7 +338,6 @@ static BOOL test_wmp(void)
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); @@ -456,7 +455,14 @@ playback_skip: hres = IConnectionPoint_Unadvise(point, dw); ok(hres == S_OK, "Unadvise failed: %08x\n", hres);
+ hres = IWMPSettings_put_volume(settings, 36); + ok(hres == S_OK, "IWMPSettings_put_volume failed: %08x\n", hres); + hres = IWMPSettings_get_volume(settings, &progress); + ok(hres == S_OK, "IWMPSettings_get_volume failed: %08x\n", hres); + ok(progress == 36, "unexpected value: %d\n", progress); + IConnectionPoint_Release(point); + IWMPSettings_Release(settings); IWMPControls_Release(controls); IWMPPlayer4_Release(player4); IOleObject_Release(oleobj); diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index e8d534803f..5fad4b1878 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -79,6 +79,7 @@ struct WindowsMediaPlayer { IMediaControl* media_control; IMediaEvent* media_event; IMediaSeeking* media_seeking; + IBasicAudio* basic_audio;
/* Async event notification */ HWND msg_window;