[PATCH v6 3/6] wmp: Add media completion notifications

Anton Romanov theli.ua at gmail.com
Wed Mar 28 10:04:42 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 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;
-- 
2.16.2




More information about the wine-devel mailing list