[PATCH v7 3/6] wmp: Add media completion notifications
Anton Romanov
theli.ua at gmail.com
Wed Mar 28 10:31:45 CDT 2018
Signed-off-by: Anton Romanov <theli.ua at 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 b3da663637..d40b0fe9cb 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);
@@ -1443,9 +1451,18 @@ 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;
+
+ 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;
@@ -1819,6 +1836,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)
@@ -1826,6 +1844,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)
@@ -1873,3 +1893,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;
--
2.16.2
More information about the wine-devel
mailing list