Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/player.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- dlls/wmp/wmp_private.h | 5 ++++ 2 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index bf7885790e..5b4bf71d78 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wmp);
static void update_state(WindowsMediaPlayer *wmp, LONG type, LONG state); +static DWORD CALLBACK WMP_event_thread(LPVOID parm);
static inline WMPMedia *impl_from_IWMPMedia(IWMPMedia *iface) { @@ -197,18 +198,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, WMP_OPEN_STATE_PLAYLIST_CHANGING); if(This->wmpmedia != NULL) { + IWMPControls_stop(&This->IWMPControls_iface); IWMPMedia_Release(This->wmpmedia); } update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_PLAYLIST_CHANGED); update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_PLAYLIST_OPEN_NO_MEDIA);
+ IWMPMedia_AddRef(pMedia); This->wmpmedia = pMedia; - IWMPMedia_AddRef(This->wmpmedia); return S_OK; }
@@ -1409,6 +1412,11 @@ static HRESULT WINAPI WMPControls_play(IWMPControls *iface) hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaControl, (void**)&This->media_control); update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_MEDIA_OPEN); + if (SUCCEEDED(hres)) + hres = IGraphBuilder_QueryInterface(This->filter_graph, &IID_IMediaEvent, + (void**)&This->media_event); + if (SUCCEEDED(hres)) + This->event_thread = CreateThread(NULL, 0, WMP_event_thread, This, 0, NULL); }
update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_TRANSITIONING); @@ -1446,8 +1454,17 @@ static HRESULT WINAPI WMPControls_stop(IWMPControls *iface) if (This->filter_graph) { IGraphBuilder_Release(This->filter_graph); } + if (This->media_event) { + IMediaEvent_Release(This->media_event); + } This->filter_graph = NULL; This->media_control = NULL; + This->media_event = NULL; + + SetEvent(This->stop_event); + WaitForSingleObject(This->event_thread, INFINITE); + CloseHandle(This->event_thread); + update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_PLAYLIST_OPEN_NO_MEDIA); update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_STOPPED); return hres; @@ -1821,6 +1838,7 @@ void init_player(WindowsMediaPlayer *wmp)
wmp->invoke_urls = VARIANT_TRUE; wmp->auto_start = VARIANT_TRUE; + wmp->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL); }
void destroy_player(WindowsMediaPlayer *wmp) @@ -1828,6 +1846,8 @@ void destroy_player(WindowsMediaPlayer *wmp) IWMPControls_stop(&wmp->IWMPControls_iface); if(wmp->wmpmedia) IWMPMedia_Release(wmp->wmpmedia); + CloseHandle(wmp->stop_event); + }
WMPMedia *unsafe_impl_from_IWMPMedia(IWMPMedia *iface) @@ -1875,3 +1895,47 @@ static void update_state(WindowsMediaPlayer *wmp, LONG type, LONG state) call_sink(wmp->wmpocx, type, &dispparams); } + +static DWORD CALLBACK WMP_event_thread(LPVOID parm) +{ + WindowsMediaPlayer* wmp = (WindowsMediaPlayer *)parm; + HRESULT hr; + HANDLE handle[2]; + DWORD n = 0, ret = 0; + + handle[n++] = wmp->stop_event; + IMediaEvent_GetEventHandle(wmp->media_event, (OAEVENT *)&handle[n++]); + for (;;) { + DWORD r; + + r = WaitForMultipleObjects(n, handle, FALSE, INFINITE); + if (r == WAIT_OBJECT_0) { + TRACE("got stop event\n"); + break; + } + else if (r == WAIT_OBJECT_0+1) { + LONG event_code; + LONG_PTR p1, p2; + do { + hr = IMediaEvent_GetEvent(wmp->media_event, &event_code, &p1, &p2, 0); + if (SUCCEEDED(hr)) { + TRACE("got event_code = 0x%02x\n", event_code); + /* For now we only handle EC_COMPLETE */ + if (event_code == EC_COMPLETE) { + update_state(wmp, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_MEDIA_ENDED); + update_state(wmp, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_TRANSITIONING); + update_state(wmp, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_STOPPED); + } + + IMediaEvent_FreeEventParams(wmp->media_event, event_code, p1, p2); + } + } while (hr == S_OK); + } + else { + ERR("Unknown error (%d)\n", (int)r); + break; + } + } + + return ret; +} diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 9e84d56ea8..0095e4ce26 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -75,6 +75,11 @@ struct WindowsMediaPlayer { /* DirectShow stuff */ IGraphBuilder* filter_graph; IMediaControl* media_control; + IMediaEvent* media_event; + + /* Async event notification */ + HANDLE event_thread; + HANDLE stop_event; };
void init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN;