[PATCH v2 7/7] wmp: Implement minimal headless WMP

Anton Romanov theli.ua at gmail.com
Fri Feb 2 00:00:17 CST 2018


Signed-off-by: Anton Romanov <theli.ua at gmail.com>
---
 dlls/wmp/player.c      | 319 +++++++++++++++++++++++++++++++++++++++++++------
 dlls/wmp/wmp_private.h |  34 ++++++
 2 files changed, 317 insertions(+), 36 deletions(-)

diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c
index 69979be21d..268764955a 100644
--- a/dlls/wmp/player.c
+++ b/dlls/wmp/player.c
@@ -17,12 +17,14 @@
  */
 
 #include "wmp_private.h"
+#include "wmpids.h"
 
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(wmp);
 
-static void update_state(WindowsMediaPlayer *wmp, int state);
+static void update_state(WindowsMediaPlayer *wmp, LONG type, LONG state);
+static void media_change(WindowsMediaPlayer *wmp, LONG type, IDispatch *pItem);
 
 static inline WindowsMediaPlayer *impl_from_IWMPNetwork(IWMPNetwork *iface)
 {
@@ -44,6 +46,20 @@ static inline WindowsMediaPlayer *impl_from_IWMPControls(IWMPControls *iface)
     return CONTAINING_RECORD(iface, WindowsMediaPlayer, IWMPControls_iface);
 }
 
+HRESULT WINAPI WMPControls_play(IWMPControls *iface)
+{
+    HRESULT hres;
+    WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
+    TRACE("(%p)\n", This);
+    hres = IMediaControl_Run(This->media_control);
+    if (SUCCEEDED(hres))
+    {
+        update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_PLAYING);
+        media_change(This, DISPID_WMPCOREEVENT_MEDIACHANGE, (IDispatch*)&This->IWMPMedia_iface);
+    }
+    return hres;
+}
+
 static HRESULT WINAPI WMPPlayer4_QueryInterface(IWMPPlayer4 *iface, REFIID riid, void **ppv)
 {
     WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface);
@@ -111,9 +127,38 @@ static HRESULT WINAPI WMPPlayer4_get_URL(IWMPPlayer4 *iface, BSTR *pbstrURL)
 
 static HRESULT WINAPI WMPPlayer4_put_URL(IWMPPlayer4 *iface, BSTR url)
 {
+    HRESULT hres;
     WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface);
-    FIXME("(%p)->(%s)\n", This, debugstr_w(url));
-    return E_NOTIMPL;
+    TRACE("(%p)->(%s)\n", This, debugstr_w(url));
+    if (!url)
+        return E_POINTER;
+    if (This->url) {
+        heap_free(This->url);
+    }
+    This->url = heap_strdupW(url);
+
+    if (!This->url)
+        return E_OUTOFMEMORY;
+
+    update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_PLAYLIST_CHANGING);
+    update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_TRANSITIONING);
+    media_change(This, DISPID_WMPCOREEVENT_CURRENTITEMCHANGE, (IDispatch*)&This->IWMPMedia_iface);
+    update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_PLAYLIST_CHANGED);
+    update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_PLAYLIST_OPEN_NO_MEDIA);
+    media_change(This, DISPID_WMPCOREEVENT_CURRENTITEMCHANGE, (IDispatch*)&This->IWMPMedia_iface);
+    update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_OPENING_UNKNOWN_URL);
+    update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_TRANSITIONING);
+    media_change(This, DISPID_WMPCOREEVENT_CURRENTITEMCHANGE, (IDispatch*)&This->IWMPMedia_iface);
+
+    hres = IGraphBuilder_RenderFile(This->pFilterGraph, url, NULL);
+    if (SUCCEEDED(hres)) {
+        update_state(This, DISPID_WMPCOREEVENT_OPENSTATECHANGE, WMP_OPEN_STATE_MEDIA_OPEN);
+    }
+
+    if (SUCCEEDED(hres) && This->autoStart)
+        WMPControls_play((IWMPControls*)This);
+
+    return hres;
 }
 
 static HRESULT WINAPI WMPPlayer4_get_openState(IWMPPlayer4 *iface, WMPOpenState *pwmpos)
@@ -504,15 +549,19 @@ static HRESULT WINAPI WMPSettings_get_isAvailable(IWMPSettings *iface, BSTR item
 static HRESULT WINAPI WMPSettings_get_autoStart(IWMPSettings *iface, VARIANT_BOOL *p)
 {
     WindowsMediaPlayer *This = impl_from_IWMPSettings(iface);
-    FIXME("(%p)->(%p)\n", This, p);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%p)\n", This, p);
+    if (!p)
+        return E_POINTER;
+    *p = This->autoStart;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPSettings_put_autoStart(IWMPSettings *iface, VARIANT_BOOL v)
 {
     WindowsMediaPlayer *This = impl_from_IWMPSettings(iface);
-    FIXME("(%p)->(%x)\n", This, v);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%x)\n", This, v);
+    This->autoStart = v;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPSettings_get_baseURL(IWMPSettings *iface, BSTR *p)
@@ -546,15 +595,21 @@ static HRESULT WINAPI WMPSettings_put_defaultFrame(IWMPSettings *iface, BSTR v)
 static HRESULT WINAPI WMPSettings_get_invokeURLs(IWMPSettings *iface, VARIANT_BOOL *p)
 {
     WindowsMediaPlayer *This = impl_from_IWMPSettings(iface);
+    /* Leaving as FIXME as we don't currently use this */
     FIXME("(%p)->(%p)\n", This, p);
-    return E_NOTIMPL;
+    if (!p)
+        return E_POINTER;
+    *p = This->invokeURLs;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPSettings_put_invokeURLs(IWMPSettings *iface, VARIANT_BOOL v)
 {
     WindowsMediaPlayer *This = impl_from_IWMPSettings(iface);
+    /* Leaving as FIXME as we don't currently use this */
     FIXME("(%p)->(%x)\n", This, v);
-    return E_NOTIMPL;
+    This->invokeURLs = v;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPSettings_get_mute(IWMPSettings *iface, VARIANT_BOOL *p)
@@ -615,16 +670,26 @@ 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);
+    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);
+    /* 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)
@@ -644,15 +709,21 @@ static HRESULT WINAPI WMPSettings_setMode(IWMPSettings *iface, BSTR mode, VARIAN
 static HRESULT WINAPI WMPSettings_get_enableErrorDialogs(IWMPSettings *iface, VARIANT_BOOL *p)
 {
     WindowsMediaPlayer *This = impl_from_IWMPSettings(iface);
+    /* Leaving as FIXME as we don't currently use this */
     FIXME("(%p)->(%p)\n", This, p);
-    return E_NOTIMPL;
+    if (!p)
+        return E_POINTER;
+    *p = This->enableErrorDialogs;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPSettings_put_enableErrorDialogs(IWMPSettings *iface, VARIANT_BOOL v)
 {
     WindowsMediaPlayer *This = impl_from_IWMPSettings(iface);
+    /* Leaving as FIXME as we don't currently use this */
     FIXME("(%p)->(%x)\n", This, v);
-    return E_NOTIMPL;
+    This->enableErrorDialogs = v;
+    return S_OK;
 }
 
 static const IWMPSettingsVtbl WMPSettingsVtbl = {
@@ -689,9 +760,124 @@ static const IWMPSettingsVtbl WMPSettingsVtbl = {
 };
 
 void destroy_player(WindowsMediaPlayer* wmp) {
+    /* shutdown event thread */
+    if (wmp->event_thread)
+    {
+        SetEvent(wmp->stop_event);
+        WaitForSingleObject(wmp->event_thread, INFINITE);
+        CloseHandle(wmp->event_thread);
+        CloseHandle(wmp->stop_event);
+    }
+
+    if (wmp->media_seeking)
+        IMediaSeeking_Release(wmp->media_seeking);
+    if (wmp->media_event)
+        IBasicAudio_Release(wmp->basic_audio);
+    if (wmp->media_event)
+        IMediaEvent_Release(wmp->media_event);
+    if (wmp->media_control)
+        IMediaControl_Release(wmp->media_control);
+    if (wmp->pFilterGraph)
+        IGraphBuilder_Release(wmp->pFilterGraph);
+    if (wmp->url)
+        heap_free(wmp->url);
     heap_free(wmp);
 }
 
+static void status_change(WindowsMediaPlayer *wmp)
+{
+    DISPPARAMS dispparams;
+
+    dispparams.cArgs = 1;
+    dispparams.cNamedArgs = 0;
+    dispparams.rgdispidNamedArgs = NULL;
+    dispparams.rgvarg = NULL;
+
+    call_sink(wmp->wmpocx, DISPID_WMPCOREEVENT_STATUSCHANGE,
+            &dispparams);
+}
+
+static void media_change(WindowsMediaPlayer *wmp, LONG type, IDispatch *pItem)
+{
+    DISPPARAMS dispparams;
+    VARIANTARG params[1];
+
+    dispparams.cArgs = 1;
+    dispparams.cNamedArgs = 0;
+    dispparams.rgdispidNamedArgs = NULL;
+    dispparams.rgvarg = params;
+
+    V_VT(params) = VT_DISPATCH;
+    V_DISPATCH(params) = pItem;
+
+    call_sink(wmp->wmpocx, type,
+            &dispparams);
+    status_change(wmp);
+}
+static void update_state(WindowsMediaPlayer *wmp, LONG type, LONG state)
+{
+    DISPPARAMS dispparams;
+    VARIANTARG params[1];
+
+    dispparams.cArgs = 1;
+    dispparams.cNamedArgs = 0;
+    dispparams.rgdispidNamedArgs = NULL;
+    dispparams.rgvarg = params;
+
+    V_VT(params) = VT_UI4;
+    V_UI4(params) = state;
+
+    call_sink(wmp->wmpocx, type,
+            &dispparams);
+    status_change(wmp);
+}
+
+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);
+                        media_change(wmp, DISPID_WMPCOREEVENT_MEDIACHANGE, (IDispatch*)&wmp->IWMPMedia_iface);
+                        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 {
+            TRACE("Unknown error (%d)\n", (int)r);
+            break;
+        }
+    }
+
+    return ret;
+}
+
+
 HRESULT WINAPI WMPControls_fastForward(IWMPControls *iface)
 {
     WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
@@ -723,8 +909,14 @@ HRESULT WINAPI WMPControls_get_currentMarker(IWMPControls *iface, LONG *plMarker
 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);
+    hres = IMediaSeeking_GetCurrentPosition(This->media_seeking, &currentPosition);
+    *pdCurrentPosition = (DOUBLE) currentPosition / 10000000.0f;
+    TRACE("hres: %d, pos: %f\n", hres, *pdCurrentPosition);
+    return hres;
 }
 
 HRESULT WINAPI WMPControls_get_currentPositionString(IWMPControls *iface, BSTR *pbstrCurrentPosition)
@@ -736,9 +928,22 @@ HRESULT WINAPI WMPControls_get_currentPositionString(IWMPControls *iface, BSTR *
 
 static HRESULT WINAPI WMPControls_get_isAvailable(IWMPControls *iface, BSTR bstrItem, VARIANT_BOOL *pIsAvailable)
 {
+    HRESULT hres = E_NOTIMPL;
     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 (strcmpW(currentPosition, bstrItem) == 0) {
+        DWORD capabilities;
+        hres = IMediaSeeking_GetCapabilities(This->media_seeking, &capabilities);
+        *pIsAvailable = (capabilities & AM_SEEKING_CanSeekAbsolute) ? 
+            VARIANT_TRUE : VARIANT_FALSE;
+    } else {
+        FIXME("%s not implemented\n", debugstr_w(bstrItem));
+    }
+    hres = S_OK;
+    *pIsAvailable = VARIANT_TRUE;
+
+    return hres;
 }
 
 HRESULT WINAPI WMPControls_next(IWMPControls *iface)
@@ -755,13 +960,6 @@ HRESULT WINAPI WMPControls_pause(IWMPControls *iface)
     return E_NOTIMPL;
 }
 
-HRESULT WINAPI WMPControls_play(IWMPControls *iface)
-{
-    WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
-    FIXME("(%p)\n", This);
-    return E_NOTIMPL;
-}
-
 HRESULT WINAPI WMPControls_playItem(IWMPControls *iface, IWMPMedia *pIWMPMedia)
 {
     WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
@@ -792,16 +990,27 @@ HRESULT WINAPI WMPControls_put_currentMarker(IWMPControls *iface, LONG lMarker)
 
 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);
+    Current = 10000000 * dCurrentPosition;
+    hres = IMediaSeeking_SetPositions(This->media_seeking, &Current,
+            AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
+
+    return hres;
 }
 
 HRESULT WINAPI WMPControls_stop(IWMPControls *iface)
 {
+    HRESULT hres;
     WindowsMediaPlayer *This = impl_from_IWMPControls(iface);
-    FIXME("(%p)\n", This);
-    return E_NOTIMPL;
+    TRACE("(%p)\n", This);
+    update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_TRANSITIONING);
+    hres = IMediaControl_Stop(This->media_control);
+    if (SUCCEEDED(hres))
+        update_state(This, DISPID_WMPCOREEVENT_PLAYSTATECHANGE, WMP_PLAY_STATE_STOPPED);
+    return hres;
 }
 
 static HRESULT WINAPI WMPControls_QueryInterface(IWMPControls *iface, REFIID riid, void **ppv)
@@ -946,9 +1155,15 @@ HRESULT WINAPI WMPMedia_getMarkerName(IWMPMedia *iface, LONG MarkerNum, BSTR *pb
 
 HRESULT WINAPI WMPMedia_get_duration(IWMPMedia *iface, DOUBLE *pDuration)
 {
+    LONGLONG duration;
+    HRESULT hres;
     WindowsMediaPlayer *This = impl_from_IWMPMedia(iface);
-    FIXME("(%p)->(%p)\n", This, pDuration);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%p)\n", This, pDuration);
+    hres = IMediaSeeking_GetDuration(This->media_seeking, &duration);
+    if (SUCCEEDED(hres))
+        *pDuration = (DOUBLE)duration / 10000000.0f;
+    TRACE("%d, %f, %lld\n", hres, *pDuration, duration);
+    return hres;
 }
 
 HRESULT WINAPI WMPMedia_get_durationString(IWMPMedia *iface, BSTR *pbstrDuration)
@@ -1189,8 +1404,9 @@ 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;
+    FIXME("stub, returning 100 (%p)->(%p)\n", This, plBufferingProgress);
+    *plBufferingProgress = 100;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPNetwork_get_bufferingTime(IWMPNetwork *iface, LONG *plBufferingTime)
@@ -1315,8 +1531,9 @@ 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;
+    FIXME("stub, returning 100 (%p)->(%p)\n", This, plDownloadProgress);
+    *plDownloadProgress = 100;
+    return S_OK;
 }
 
 static HRESULT WINAPI WMPNetwork_get_encodedFrameRate(IWMPNetwork *iface, LONG *plFrameRate)
@@ -1373,11 +1590,41 @@ static const IWMPNetworkVtbl WMPNetworkVtbl = {
 
 HRESULT init_player(WindowsMediaPlayer *wmp)
 {
+    HRESULT hres;
+
     wmp->IWMPPlayer4_iface.lpVtbl = &WMPPlayer4Vtbl;
     wmp->IWMPSettings_iface.lpVtbl = &WMPSettingsVtbl;
     wmp->IWMPControls_iface.lpVtbl = &WMPControlsVtbl;
     wmp->IWMPMedia_iface.lpVtbl = &WMPMediaVtbl;
     wmp->IWMPNetwork_iface.lpVtbl = &WMPNetworkVtbl;
 
+    wmp->invokeURLs = TRUE;
+    wmp->autoStart = TRUE;
+
+
+    hres = CoCreateInstance(&CLSID_FilterGraph,
+            NULL,
+            CLSCTX_INPROC_SERVER,
+            &IID_IGraphBuilder,
+            (void **)&wmp->pFilterGraph);
+    if (SUCCEEDED(hres))
+        hres = IGraphBuilder_QueryInterface(wmp->pFilterGraph, &IID_IMediaControl, (void**)&wmp->media_control);
+    if (SUCCEEDED(hres))
+        hres = IGraphBuilder_QueryInterface(wmp->pFilterGraph, &IID_IMediaEvent, (void**)&wmp->media_event);
+    if (SUCCEEDED(hres))
+        hres = IGraphBuilder_QueryInterface(wmp->pFilterGraph, &IID_IBasicAudio, (void**)&wmp->basic_audio);
+    if (SUCCEEDED(hres))
+        hres = IGraphBuilder_QueryInterface(wmp->pFilterGraph, &IID_IMediaSeeking, (void**)&wmp->media_seeking);
+    if (SUCCEEDED(hres))
+        hres = IMediaSeeking_SetTimeFormat(wmp->media_seeking, &TIME_FORMAT_MEDIA_TIME);
+    if (SUCCEEDED(hres))
+    {
+        wmp->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+        wmp->event_thread = CreateThread(NULL, 0, WMP_event_thread, wmp, 0, NULL);
+    }
+    if (!wmp->event_thread) {
+        TRACE("Can't create thread\n");
+        return E_FAIL;
+    }
     return S_OK;
 }
diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h
index b9c66a952a..810fafaf27 100644
--- a/dlls/wmp/wmp_private.h
+++ b/dlls/wmp/wmp_private.h
@@ -22,6 +22,8 @@
 #include "wine/heap.h"
 #include "ole2.h"
 #include "wmp.h"
+#include "wine/unicode.h"
+#include "dshow.h"
 
 typedef struct {
     IConnectionPoint IConnectionPoint_iface;
@@ -55,6 +57,23 @@ struct WindowsMediaPlayer {
     SIZEL extent;
 
     ConnectionPoint *wmpocx;
+
+    /* Settings */
+    VARIANT_BOOL autoStart;
+    VARIANT_BOOL invokeURLs;
+    VARIANT_BOOL enableErrorDialogs;
+    BSTR url;
+
+    /* DirectShow stuff */
+    IGraphBuilder* pFilterGraph;
+    IMediaControl* media_control;
+    IMediaEvent*  media_event;
+    IBasicAudio * basic_audio;
+    IMediaSeeking * media_seeking;
+
+    /* Async event notification */
+    HANDLE event_thread;
+    HANDLE stop_event;
 };
 
 HRESULT init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN;
@@ -69,3 +88,18 @@ void call_sink(ConnectionPoint *This, DISPID dispid, DISPPARAMS *dispparams);
 void unregister_wmp_class(void) DECLSPEC_HIDDEN;
 
 extern HINSTANCE wmp_instance DECLSPEC_HIDDEN;
+static inline WCHAR *heap_strdupW(const WCHAR *str)
+{
+    WCHAR *ret;
+
+    if(str) {
+        size_t size = strlenW(str)+1;
+        ret = heap_alloc(size*sizeof(WCHAR));
+        if(ret)
+            memcpy(ret, str, size*sizeof(WCHAR));
+    }else {
+        ret = NULL;
+    }
+
+    return ret;
+}
-- 
2.16.1




More information about the wine-devel mailing list